Skip to main content

Timmyの移動を実装

主人公のゲームオブジェクトを作成

主人公のキャラクターの移動を実装しましょう。まず、空のゲームオブジェクトを作成し、「Player」という名前を付けてください。このゲームオブジェクトはプレーヤーの役割にする。

3Dモデルを追加

Characters/Timmy/Models から Timmy のモデルを追加してください。Player の子オブジェクトとして追加しましょう:

image.pngimage.png

よく見ると、色が多少おかしい。これはノーマルマップ(※)の問題であるので、解決しましょう。Characters/Timmy/Textures の中にあるノーマルテクスチャ(青い画像)を選択し、ノーマルマップであることを指定し、最後に「Apply」を押してください:

image.png

 

(※)ノーマルマップについては、また「ゲームエンジンII」で勉強する予定

image.pngimage.png

物理処理の準備

キャラクターを物理的に移動するべきなので、コライダーとリジッドボディが必要。Player に Rigidbody と CapsuleCollider を追加してください。なお、コライダーの形がある程度 3Dモデルの体に合わせましょう:

image.pngimage.png

スクリプト

Inputクラスを使用し、キャラクターを動かしましょう。後で改善するべきですが、とりあえず、WASD のキーで前後左右を移動しましょう:

image.png

AとDでX軸(赤い軸)で移動し、W とSでZ軸(青い軸)で移動する。なお、各入力は:

    Input.GetAxis("Horizontal"): 入力の「水平軸」(つまりAとD)の入力をの取得ができる
      Aの場合は -1 を返す Dの場合は1を返す 入力のない場合は0を返す Input.GetAxis("Vertical"): 入力の「垂直軸」(つまりWとS)の入力をの取得ができる
        Wの場合は1 を返す Dの場合は-1を返す 入力のない場合は0を返す

        また、移動速度をUnityで変えられるようにしましょう。この知識を活用し、移動のスクリプト「PlayerMove」を実装:

        // プレーヤーの移動を処理する
        public class PlayerMove : MonoBehaviour
        {
            // 速度をInspectorで設定
            [SerializeField]
            private float speed = 5.0f;
            
            // 物理的に移動するので、リジッドボディが必要
            private Rigidbody rbody;
        
            // 3D空間の速度ベクトル
            private Vector3 velocity;
        
            private void Start()
            {
                // 参照を取っておく
                rbody = GetComponent<Rigidbody>();
            }
        
            private void Update()
            {
                // 何も入力がない前提で、速度をゼロにする
                velocity = Vector3.zero;
                
                // A/S(水平入力)を取得し、3D空間のX軸に割り当てる
                velocity.x = Input.GetAxis("Horizontal");
                
                // W/D (垂直入力)を取得し、3D空間のZ軸に割り当てる
                velocity.z = Input.GetAxis("Vertical");
                
                // 単位ベクトルにする
                velocity.Normalize();
                
                // 速度を乗算する
                velocity *= speed;
            }
        
            private void FixedUpdate()
            {
                // 速度を設定
                rbody.linearVelocity = velocity;
            }
        }

        TODO: Explain vector normalization and what's happening with the input using drawings

        TODO: Explain FixedUpdate with drawings

        このスクリプトを「Player」にアタッチし、実行してみてください。移動し、ランプを上り、ジャンプしてみてください。なお、カメラの処理まだ行っていないので、Game ビューと Scene ビューを同時に表示するのはおすすめ。

        問題:倒れたり、回転したりする

           

        すべての動きをリジッドボディに任せているため、移動だけではなく、回転も自由になっている。今後、回転はスクリプトで実現するので、リジッドボディが回転ができないようにすれば良いでしょう。制約設定で回転を固定しましょう:


        image.png

        問題:ゆっくり落ちる

        回転の問題を解決できたが、ランプから飛び出すと、ゆっくりに落ちる。なぜなら、Updateごとに速度を上書きしているからです!重力による落下をリジッドボディに任せても、縦軸(Y軸)の速度をゼロにしているので、なかなか落ちない!

        解決としては、Y軸の速度を保守し、XとZだけを上書きすれば良い。FixedUpdate を以下のように直しましょう:

        private void FixedUpdate()
        {
            // 現在の速度を取得
            Vector3 v = rbody.linearVelocity;
            
            // XとZ を上書き
            v.x = velocity.x;
            v.z = velocity.z;
            
            // 速度を設定
            rbody.linearVelocity = v;
        }

        これで確認しましょう。