【バイオハザード風のゲームを作ってみよう。その2】

今回も下記動画を参考に作っていきたいと思います。

youtu.be


はじめに、カメラがキャラクターを追うように動画の通り設定し、スクリプト(PlayerCamera.cs、PlayerManager.cs)を追加しました。

次に、動画では新しいInput Systmを利用して、プレイヤーの移動/アニメーションを実現しているので、動画に倣いInput Actionsを作成(PlayerControls)を作成し、下記のように設定しました。

また、スクリプト(AnimatorManager.cs、InputManager.cs、PlayerManager.cs)を追加しました。

なお、【バイオハザード風のゲームを作ってみよう。その1】 - 330Games pageで作成したスクリプト(Player_Controller.cs)はInput Managerを使用したプレイヤーの移動方法ですが、動画ではInput Systmを使用しているのでプレイヤーオブジェクトからremoveしました。


次に、マウスに合わせてカメラが回転するようにスクリプト(PlayerCamera.cs)を追加しました。
なお、現状だと、プレイヤーの移動とカメラの回転がそれぞれ独立しているので、移動中にカメラを回転した場合は、プレイヤーがカメラの向きに回転するようにスクリプト(PlayerLocomotionManager.cs)を追加する。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerCamera : MonoBehaviour
{
    public InputManager inputManager;

    public Transform cameraPivot;
    public Camera cameraObject;
    public GameObject player;

    Vector3 cameraFollowVelocity = Vector3.zero;
    Vector3 targetPosition;
    Vector3 cameraRotation;
    Quaternion targetRotation;

    [Header("Camera Speeds")] //Inspectorにヘッダーを追加
    public float cameraSmoothTime=0.2f;

    float lookAmountVertical;
    float lookAmountHorizontal;
    float maximumPivotAngle = 15;
    float minimumPivotAngle = -15;


    public void HandleAllCameraMovement()
    {
        FollowPlayer();
        RotateCamera();
    }

    //カメラをプレイヤーに追尾させる
    void FollowPlayer()
    {
        //SmoothDamp:目的地に向かって時間の経過とともに徐々にベクトルを変化させる。目的地は2番目の変数。
        targetPosition = Vector3.SmoothDamp(transform.position, player.transform.position, ref cameraFollowVelocity, cameraSmoothTime * Time.deltaTime);
        transform.position = targetPosition;
    }

    //カメラをマウスに合わせて上下、左右に回転させる
    private void RotateCamera()
    {
        //変数lookAmountVertical(unity内のy軸方向の回転量を格納)にunity内のy軸方向のマウス入力(inputManager.horizontalcameraInput)を格納。
        lookAmountVertical = lookAmountVertical + (inputManager.horizontalcameraInput);

        // lookAmountHorizontal(unity内のx軸方向の回転量を格納)にunity内のx軸方向のマウス入力(inputManager.verticalCameraInput)を格納。
        lookAmountHorizontal = lookAmountHorizontal - (inputManager.verticalCameraInput);

        // lookAmountHorizontal((unity内のx軸方向の回転量)を範囲内(minimumPivotAngle~maximumPivotAngle)の値に制限。
        //Mathf.Clamp(int value, int min, int max):min と max の範囲に値を制限し、その値を返す
          lookAmountHorizontal = Mathf.Clamp(lookAmountHorizontal, minimumPivotAngle, maximumPivotAngle);

        //unity内のy軸方向の回転量を設定
        //cameraRotationの初期化
        cameraRotation = Vector3.zero;

        cameraRotation.y = lookAmountVertical;

        //public static Quaternion Euler (Vector3 euler): z 軸を中心に z 度、x 軸を中心に x 度、y 軸を中心に y 度回転する回転を返す。
        targetRotation = Quaternion.Euler(cameraRotation);

        //public static Quaternion Slerp (Quaternion a, Quaternion b, float t): a と b の間を t で球状に補間します。パラメーター t は、[0, 1] の範囲です。
        targetRotation = Quaternion.Slerp(transform.rotation, targetRotation, cameraSmoothTime);

        //自身(player Cameraオブジェクト)のRotationをtargetRotation値に設定。
        transform.rotation = targetRotation;

        
        // unity内のx軸方向の回転量を設定
        cameraRotation = Vector3.zero;
        cameraRotation.x = lookAmountHorizontal;
        targetRotation = Quaternion.Euler(cameraRotation);
        targetRotation = Quaternion.Slerp(cameraPivot.localRotation, targetRotation, cameraSmoothTime);
        cameraPivot.localRotation = targetRotation;
        
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerManager : MonoBehaviour
{
    PlayerCamera playerCamera;
    InputManager inputManager;
    PlayerLocomotionManager playerLocomotionManager;


    private void Awake()
    {
        playerCamera=FindObjectOfType<PlayerCamera>();
        inputManager = GetComponent<InputManager>();
        playerLocomotionManager = GetComponent<PlayerLocomotionManager>();
    }

    private void Update()
    {
        inputManager.HandleAllInputs();
        inputManager.Move();
        inputManager.Turning();
    }

    //追加
    private void FixedUpdate()
    {
        playerLocomotionManager.HandleAllLocomotion();
    }

    private void LateUpdate() //毎フレーム毎、様々計算が終わった後に呼ばれる。
    {
        playerCamera.HandleAllCameraMovement();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimatorManager : MonoBehaviour
{
    
    Animator animator;
    float snappedHorizontal;
    float snappedVertical;

    public void Awake()
    {
        animator = GetComponent<Animator>();
    }

    //移動アニメーション
    public void HandleAnimatorValues(float horizontalMovememt, float verticalMovement)
    {
        if (horizontalMovememt > 0)
        {
            snappedHorizontal = 1;
        }
        else if (horizontalMovememt < 0)
        {
            snappedHorizontal = -1;
        }
        else
        {
            snappedHorizontal = 0;
        }


        if (verticalMovement > 0)
        {
            snappedVertical = 1;
        }
        else if (verticalMovement < 0)
        {
            snappedVertical = -1;
        }
        else
        {
            snappedVertical = 0;
        }

        animator.SetFloat("Horizontal", snappedHorizontal, 0.1f, Time.deltaTime);
        animator.SetFloat("Vertical", snappedVertical, 0.1f, Time.deltaTime);

    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InputManager : MonoBehaviour
{
    PlayerControls playerControls;
    AnimatorManager animatorManager;

    [Header("Player Movement")]
    public float verticalMovementInput;
    public float horizontalMovementInput;
    private Vector2 movementInput;

    [Header("Camera Rotaion")]
    public float verticalCameraInput;
    public float horizontalcameraInput;
    private Vector2 CameraInput;

    [Header("Move")]
    public float speed = 3f; //歩行スピード
    public float rotateSpeed = 1f; //体の向きのスピード
    Vector3 direction;


    private void Awake()
    {
        animatorManager = GetComponent<AnimatorManager>();
    }

    private void OnEnable() //OnEnableはオブジェクトが有効になったときに呼び出されます.
    {
        if(playerControls == null)
        {
            playerControls = new PlayerControls();

            //アクション実行中コールバック
             playerControls.PlayerMovement.Movement.performed += i => movementInput = i.ReadValue<Vector2>();
            playerControls.PlayerMovement.Camera.performed += i => CameraInput = i.ReadValue<Vector2>();
        }

        playerControls.Enable();
    }

    private void OnDisable()
    {
        playerControls.Disable();
    }

    public void HandleAllInputs()
    {
        HandMovementInput();
        HandCameraInput();
    }

    private void HandMovementInput()
    {
        horizontalMovementInput = movementInput.x;
        verticalMovementInput = movementInput.y;
        animatorManager.HandleAnimatorValues(horizontalMovementInput, verticalMovementInput);
    }

    private void HandCameraInput()
    {
        horizontalcameraInput = CameraInput.x;
        verticalCameraInput = CameraInput.y;
    }

    public void Move()
    {
        MoveInput(verticalMovementInput);
    }

    // 上下キーが押されたら前進/後進
    void MoveInput(float v)
    {
        if (v != 0)
        {
            direction = transform.TransformDirection(new Vector3(0.0f, 0.0f, v)); //ローカル空間からワールド空間へ x、y、z を変換します。
            direction *= speed;
            direction *= Time.deltaTime;
            // direction /= 2f; //歩行スピード調整
            transform.position += direction;
        }
      
    }

    public void Turning()
    {
        TurningInput(horizontalMovementInput);
    }

    //左右キーが押されたら回転
    void TurningInput(float h)
    {
        if (h != 0)
        {
            //左右に回転させるにはRotateメソッドを使用。
            //y軸の引数に左右キーが押下された時に得られる1or - 1の値にspeedとdeleteTimeをかけて引数として使用しました。
            transform.Rotate(0, 100 * Time.deltaTime * rotateSpeed * h, 0);
            
        }
    }


}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerLocomotionManager : MonoBehaviour
{
    InputManager inputManager;

    [Header("Camera Transform")]
    public Transform playerCamera;

    [Header("Movement Speed")]
    public float rotationSpeed = 3.5f;

    [Header("Rotaion Variables")]
    Quaternion targetRotation; //The place we want to rotate
    Quaternion playerRotation; //The place we are rotating now, constantly changing

    private void Awake()
    {
        inputManager = GetComponent<InputManager>();
    }

    public void HandleAllLocomotion()
    {
        HandleRotaion();
    }

    private void HandleRotaion()
    {
        //変数targetRotationにプレイヤーカメラのRotationを格納。
        targetRotation = Quaternion.Euler(0, playerCamera.eulerAngles.y, 0);

        //変数playerRotationにプレイヤー位置~変数targetRotationの値を格納。
        playerRotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);

        //プレイヤーが移動中にマウスを動かした場合、プレイヤーはマウスの動きに合わせて回転する(カメラの向きに回転する)。
        if (inputManager.verticalMovementInput !=0 || inputManager.horizontalMovementInput != 0)
        {
            transform.rotation = playerRotation;
        }
    }
}