# Timmyの移動を実装

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

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

### 3Dモデルを追加

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

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/27Gimage.png)

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

<table border="1" id="bkmrk-%C2%A0-%EF%BC%88%E2%80%BB%EF%BC%89%E3%83%8E%E3%83%BC%E3%83%9E%E3%83%AB%E3%83%9E%E3%83%83%E3%83%97%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AF%E3%80%81%E3%81%BE%E3%81%9F" style="border-collapse: collapse; width: 100%; border-width: 0px;"><colgroup><col style="width: 60.0664%;"></col><col style="width: 39.8919%;"></col></colgroup><tbody><tr><td style="border-width: 0px;">![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/cHaimage.png)

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

</td><td style="border-width: 0px;">![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/Mgximage.png)

</td></tr></tbody></table>

### 物理処理の準備

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

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/kLiimage.png)

## スクリプト

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

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/MKBimage.png)

ＡとＤでＸ軸（赤い軸）で移動し、Ｗ とＳでＺ軸（青い軸）で移動する。なお、各入力は：

- `Input.GetAxis("Horizontal")`: 入力の「水平軸」（つまりAとD）の入力をの取得ができる 
    - Ａの場合は -１ を返す
    - Ｄの場合は１を返す
    - 入力のない場合は０を返す
- `Input.GetAxis("Vertical")`: 入力の「垂直軸」（つまりＷとＳ）の入力をの取得ができる 
    - Ｗの場合は１ を返す
    - Ｄの場合は-１を返す
    - 入力のない場合は０を返す

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

```c#
// プレーヤーの移動を処理する
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;
    }
}
```

##### `Normalize()`とは

`Normalize()`はあるベクトルを長さ１（単位ベクトル）にする。今回の処理は以下の図で解析してある：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/ZmOimage.png)

上下、または左右 **<span style="text-decoration: underline;">のみ</span>** で移動する場合は、`GetAxis` が -1～1 の数値を返すので、移動速度「speed」を掛けると、問題なく、長さ５の速度ベクトルができる。一方、同時に入力すると（斜め移動）

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/Uxvimage.png)

掛け算の前に単位ベクトルにすると：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/EYDimage.png)

#### 実行確認

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

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

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

![image.png](https://class.illogic.games/uploads/images/gallery/2026-05/scaled-1680-/VhNimage.png)

#### 問題：ゆっくり落ちる

回転の問題を解決できたが、ランプから飛び出すと、ゆっくりに落ちる。なぜなら、Updateごとに<span style="color: rgb(186, 55, 42);">**速度を上書きしている**</span>からです！重力による落下をリジッドボディに任せても、縦軸（Y軸）の速度をゼロにしているので、なかなか落ちない！

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

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

これで確認しましょう。