Unity でGame 制作 #4

前回までのユニゲー(Unity でGame 制作)は…

視界の回転(水平方向のみ)にPlayerオブジェクトの向きを追従させることで進行方向を操作できるようになった!

ということで、続きです(=゚ω゚)。

Playerオブジェクトをそれなりに動かせるようにはなりましたが、まだまだ足りません。
なのでさらに改良を加えていきます。

具体的には上下の視点の操作(Playerオブジェクトは追従しない)、カメラとプレイヤーの距離の変更(見下ろし型視点とFPS視点の切り替えまたはマウススクロールでDolly)、歩行によるカメラのブレ(上下動)あたりもつけたいところです。

[PlayerFollowCamera.cs]

~~~省略
    void LateUpdate()
    {
        // マウスの横方向の動きに追従
        hRotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * turnSpeed, 0);
        // マウスの縦方向の動きに追従
        vRotation *= Quaternion.Euler(Input.GetAxis("Mouse Y") * turnSpeed, 0, 0);
        // カメラの回転を合成
        transform.rotation = hRotation * vRotation;

        // カメラの位置(transform.position)の更新
        transform.position = player.position + cameraPosition - transform.rotation * Vector3.forward * distance;
    }
~~~省略

こんな感じに変更。さっそくPlayで動きを確認。 視点追従

クリック時のみPlayerの向きを反映してましたけど、そのまま追従に変更。 うーん、あれだ。制限をかけないとぐるんぐるんしますね。 あと、上下の回転は反転が選択できるようにしたほうがいいかな。

色々と試行錯誤の結果こんな感じになりました。

[PlayerFollowCamera.cs]

using UnityEngine;

public class PlayerFollowCamera : MonoBehaviour
{
    [SerializeField] private Transform player = null;// 追従対象

    [SerializeField] private Vector3 cameraPosition = new Vector3(0, 1.8f, 0);//カメラポジション
    [SerializeField] private float distance = 3.0f;// 追従対象からの距離

    [SerializeField] private float pitch = 24.0f;// カメラX軸回転
    [SerializeField] public float yaw = 0.0f;//カメラY軸回転
    [SerializeField] private bool pitchInverse = false;// X軸反転
    [SerializeField] private float mouseSensitivity = 10.0f;// 回転速度

    void Start()
    {
        // 角度の初期化
        transform.rotation = Quaternion.Euler(pitch, yaw, 0);
        // 位置の初期化
        transform.position = player.position + cameraPosition - transform.rotation * Vector3.forward * distance;
    }

    void LateUpdate()
    {
        // マウスの横方向の動き
        float xRot = Input.GetAxis("Mouse X");
        // マウスの縦方向の動き Y軸反転判定付き
        float yRot = (pitchInverse)? Input.GetAxis("Mouse Y") : Input.GetAxis("Mouse Y") * -1.0f;

        // カメラの向きを取得
        Vector3 angles = transform.rotation.eulerAngles;

        //Y軸回転(水平方向)を設定
        yaw += xRot * mouseSensitivity;
        yaw -= (yaw>360f)? 360f : 0;
        yaw += (yaw<0)? 360f : 0;

        //X軸回転(上下方向)を設定
        pitch = (angles.x + 180f) % 360f - 180f;
        pitch -= yRot * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, -90f, 90f);

        // カメラの向きの更新
        transform.rotation = Quaternion.Euler(pitch, yaw, 0);
        // カメラの位置の更新
        transform.position = player.position + cameraPosition - transform.rotation * Vector3.forward * distance;
    }
}
[Player.cs]

using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private Vector3 velocity;//移動ベクトル
    [SerializeField] private float moveSpeed = 1.25f;//移動速度、歩幅
    [SerializeField] private PlayerFollowCamera pfCamera = null;//追従カメラ

    void Update()
    {
        // キー入力判定
        velocity = Vector3.zero;
        if (Input.GetKey(KeyCode.W))
            velocity.z += 1;
        if (Input.GetKey(KeyCode.A))
            velocity.x -= 1;
        if (Input.GetKey(KeyCode.S))
            velocity.z -= 1;
        if (Input.GetKey(KeyCode.D))
            velocity.x += 1;

        // 移動ベクトルを秒単位でmoveSpeedだけ進むように制限
        velocity = velocity.normalized * moveSpeed * Time.deltaTime;

        // プレイヤー回転の更新
        transform.rotation = Quaternion.Euler(0, pfCamera.yaw, 0);
        // プレイヤー位置の更新
        transform.position += transform.rotation * velocity;
    }
}

マウス移動でPleyerの方向転換。上下回転制限つき。

[PlayerFollowCamera.cs]

~~~省略
    [SerializeField] private float distanceMax = 3.0f;// 追従対象からの距離上限<=追加
~~~中略
    void LateUpdate()
    {
        // カメラの向きを取得
        Vector3 angles = transform.rotation.eulerAngles;

        // Y軸回転(水平方向)を設定
        float xRot = Input.GetAxis("Mouse X");
        yaw += xRot * mouseSensitivity;
        yaw -= (yaw>360f)? 360f : 0;
        yaw += (yaw<0)? 360f : 0;

        // X軸回転(上下方向)を設定
        float yRot = (pitchInverse)? Input.GetAxis("Mouse Y") : Input.GetAxis("Mouse Y") * -1.0f;
        pitch = (angles.x + 180f) % 360f - 180f;
        pitch -= yRot * mouseSensitivity;
        pitch = Mathf.Clamp(pitch, -90f, 90f);

        // 追従対象からの距離を設定<=追加
        distance -= Input.GetAxis("Mouse ScrollWheel") * mouseSensitivity;
        distance = Mathf.Clamp(distance, 0, distanceMax);

        // カメラの向きの更新
        transform.rotation = Quaternion.Euler(pitch, yaw, 0);
        // カメラの位置の更新
        transform.position = player.position + cameraPosition - transform.rotation * Vector3.forward * distance;
    }
~~~省略

マイスホイールでPlayerオブジェクトとの距離を変更(FPS視点、三人称視点切り替え) マウスホイールでDolly

さらに上下動(歩行時の揺れ的なもの)を追加。

[PlayerFollowCamera.cs]

~~~省略
    [SerializeField] private float bobbing = 0.0f;// 上下動
    [SerializeField] private float bobSpeed = 0.05f;// 揺れの速さ
    [SerializeField] private float bobAmount = 0.015f;// 振幅
~~~中略
        // 上下動を設定
        float waveslice = 0.0f;
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        // 停止中(キー入力なし)?
        if (Mathf.Abs(horizontal)==0 && Mathf.Abs(vertical)==0)
        {
            bobbing = 0;
        } else {
            waveslice = Mathf.Sin(bobbing);
            bobbing = bobbing + bobSpeed;
            if (bobbing > Mathf.PI * 2)
            {
                bobbing = bobbing - (Mathf.PI * 2);
            }
        }
        Vector3 camPos = cameraPosition;
        if (waveslice != 0)
        {
            float translateChange = waveslice * bobAmount;
            float totalAxis = Mathf.Abs(horizontal) + Mathf.Abs(vertical);
            totalAxis = Mathf.Clamp(totalAxis, 0.0f, 1.0f);
            translateChange = totalAxis * translateChange;
            camPos.y = cameraPosition.y + translateChange;
        } else {
            camPos.y = cameraPosition.y;
        }

        // カメラの向きの更新
        transform.rotation = Quaternion.Euler(pitch, yaw, 0);
        // カメラの位置の更新
        transform.position = player.position + camPos - transform.rotation * Vector3.forward * distance;
    }
}

各項目の数値は今後要調整だけど、とりあえずの動きはこんなかんじでしょうかね(=゚ω゚)ノ