Menu
CoddyTech

視線の方向へ移動

CoddyのUnityジャーニー「本格的なゲームを作る」セクションの一部。レッスン 42/60。

カメラがプレイヤーを斜めから見ているとき、矢印キーを押すと画面に表示されるとおりにプレイヤーが移動する必要があります。上を押すとカメラから遠ざかり、右を押すとカメラから見て右に進みます。ワールドの軸がこのように機能するのは、カメラが +z 方向を向いているときだけです。そこで、カメラ自身の方向である cam.forward と cam.right を使って移動を組み立てます。

まず、これらの方向を整える必要があります。プレイヤーを見下ろすカメラの forward は地面に向いているため、地面に沿った成分だけを残すように y を 0 に設定します。残ったベクトルは 1 より短く、30 度下向きのカメラでは約 0.87 なので、プレイヤーの移動速度が遅くなってしまいます。そのため、正規化します。このプレイヤー移動処理は、レベルの隅を見下ろすメインカメラに追従します。

Transform cam = Camera.main.transform;

Vector3 forward = cam.forward;
forward.y = 0f;
forward.Normalize();
Vector3 right = cam.right;
right.y = 0f;
right.Normalize();

Vector3 move = forward * Input.GetAxisRaw("Vertical") + right * Input.GetAxisRaw("Horizontal");
if (move.magnitude > 1f) move.Normalize();   // 斜め移動でも速くならない
controller.Move(move * speed * Time.deltaTime);

Camera.main は MainCamera タグが付いたカメラです。2つの方向は毎フレーム読み取られるため、カメラが回転しても操作の向きは画面に対して正しいままです。上と右を同時に押すと、直角に交わる2つの単位ベクトルが加算され、その長さは約 1.41 になるため、移動ベクトルの長さが 1 を超える場合は正規化します。

challenge icon

チャレンジ

中級

矢印キーで、回転するカメラを基準にプレイヤーを歩かせましょう。

  1. Update()で、cam.forwardとcam.rightをコピーし、yを0にして正規化します。
  2. dirは、forwardに生の"Vertical"軸を掛けた値と、rightに"Horizontal"を掛けた値を足したものです。長さが1を超える場合は正規化します。
  3. dir != Vector3.zeroのとき、transform.rotation = Quaternion.LookRotation(dir);を設定します。moveはdir * speedから作ります。

「プレイ」を押します。上キーを押すと、カメラがどちらを向いていても、カメラから遠ざかる方向に歩きます。その後、「確認」を押します。

自分で試してみよう

using UnityEngine;

public class Mover : MonoBehaviour
{
    public float speed = 4f;
    public float gravity = -15f;
    public Transform cam;

    CharacterController controller;
    float verticalSpeed;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (controller.isGrounded && verticalSpeed < 0f)
        {
            verticalSpeed = -2f;
        }
        verticalSpeed += gravity * Time.deltaTime;

        // ワールド座標の軸に沿って移動する:camを基準に移動し、移動方向を向くようにする
        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        move.y = verticalSpeed;
        controller.Move(move * Time.deltaTime);
    }
}

本格的なゲームを作るのすべてのレッスン

自分で練習してみよう: Unityプレイグラウンド