雑記投下場

~霊水晶園跡地~

【メモ】UnityのStarterAssetsで簡単な空中浮遊

更新履歴

  1. 可読性のために見出しを追加.一部脱字を修正,説明の追加.(2021/08/30)

記事の目的

UnityのStarterAssetsで空中浮遊を行う方法のメモ(取り急ぎ書き殴っただけなので,他に良い方法があれば教えて頂けると幸いです).

実装概要

StarterAssetsで提供されているキャラクターはスペースキーの押下でジャンプができるので,これを利用し,押しっぱなしで浮遊するようにすることを考える.

疑似コード的には次のようになる.

if (スペースキーを押している) {
    鉛直速度 = 0; // 上にも下にもいかない
}

ここのところ全然Unity触れていなかったので,これをInput.GetKey(KeyCode.Space)でやろうとしたところエラーを吐かれてしまった.するといつからか入力の取得方法などが変わったようで…(以下記事で確認させていただきました).

bibinbaleo.hatenablog.com

他の記事や,Visual Studioでプロパティを確認すると,旧バージョン(InputManager?)との対応付けは以下のようになりそう.

タイミング
押している間 Input.GetKey(KeyCode.Space) Keyboard.current.spaceKey.isPressed
押した瞬間 Input.GetKeyDown(KeyCode.Space) Keyboard.current.spaceKey.wasPressedThisFrame
離した瞬間 Input.GetKeyUp(KeyCode.Space) Keyboard.current.spaceKey.wasReleasedThisFrame

押している間はずっと浮遊させたいので,今回は.isPressedを使用する.

提供されているスクリプトを改造する

概要でも示したように,空中にいる間の鉛直速度を0にすることで落ちることはなくなるはずだが,StarterAssetsで提供されているスクリプト(StarterAssets/ThirdPersonController/Scripts/ThirdPersonController.cs)を直接改造する場合はもう少し手を加える必要がある.というのも,ジャンプに関する処理が次のようになっているため.

private void JumpAndGravity()
{
    if (Grounded)
    {
        ...
    }
    else
    {
        ... // ここに空中浮遊用の操作を書きたい
    }

    if (_verticalVelocity < _terminalVelocity)
    {
        _verticalVelocity += Gravity * Time.deltaTime;
    }
}

最後のif文で使用されているGravityは-15のようで,鉛直速度が終端速度以下であれば鉛直速度は減少(下向きに増加)するといった感じに.そのため,押している間は完全に静止させたければこの処理もなくす必要がある(なお,この処理を省くと完全に静止せず,少しずつ落ちていって自然に見えるのでこれはこれでアリかも…?).最後のif文に条件を追加してもいいが,恐らくコードが若干長くなるので今回は変数を利用する方法で制御する.

最後に,単にif (!Grounded) {}内に書くだけではジャンプした直後から処理が反映され,空中浮遊とは言えないような見た目になってしまうため,「鉛直速度が0以下(最高点から下がり始めている)」ときに処理を行うことでそれっぽく見えるようになる.

実装の詳細(結論)

最終的には以下のようなコードで,空中浮遊を実現できる.

private void JumpAndGravity()
{
    int gravityPhase = 1; // 制御用変数

    if (Grounded)
    {
        ...
    }
    else
    {
        ...
        _input.jump = false;

        // 追加
        if (Keyboard.current.spaceKey.isPressed && _verticalVelocity <= 0.0f)
        {
            _verticalVelocity = 0;
            gravityPhase = 0;
        }
    }

    // apply gravity over time if under terminal (multiply by delta time twice to linearly speed up over time)
    if (_verticalVelocity < _terminalVelocity)
    {
        _verticalVelocity += Gravity * Time.deltaTime * gravityPhase;
    }
}

実行結果

結果:

f:id:eustoma_parker:20210827205052g:plain
空中浮遊のgif

上のgifを作る際にお世話になったサイト: syncer.jp

まとめと今後の展望

キャラクターに空を飛ばせたいというのはあるが,これをどう生かせるかは現状未定….