【ダークソウル風ゲームを作りたい(Unity)。その4】

今回はローリングを実装します。
youtu.be

・ローリングのアニメーションを準備します。私はmixamoからダウンロードしました。
RigのAnimationTypeをHumanoidに変更。
Animationを下図に設定。

・AnimatorにRollingステートを追加しMotionに用意したアニメーションを設定します。また、bool型のパラメータ:isInteractingを追加します。

・PlayerControls(Input Action)でローリングのインプット設定します。キーボードの場合、LeftShiftに設定しました。

・下記スクリプトを追加します。

  public class InputHandler : MonoBehaviour //+EP1 playerにアタッチ
    {
        public bool b_Input; //+EP4
        public bool rollFlag; //+EP4
        public bool isInteracting; //+EP4

 public void TickInput(float delta)
        {
            MoveInput(delta);
            HandleRollInput(delta); //+EP4
        }

 //+EP4 ローリングをONした場合の設定
        private void HandleRollInput(float delta)
        {
            //ローリングボタン押下でb_input=true
            b_Input = inputActions.PlayerActions.Roll.phase == UnityEngine.InputSystem.InputActionPhase.Started;

            if (b_Input)
            {
                rollFlag = true;
            }
        }
}
 public class PlayerLocomotion : MonoBehaviour //+EP1 playerにアタッチ
    {
 public void Update()
        {
            //Time.deltaTime:前回のフレームからの経過時間
            float delta = Time.deltaTime;

            inputHandler.TickInput(delta);
            HandleMovement(delta);
            HandleRollingAndSprinting(delta); //+EP4
        }

 //+EP4 ローリングアニメーションを実行
        public void HandleRollingAndSprinting(float delta)
        {
            //プレイヤーがローリング中はローリングボタンを押しても何もしない
            if (animatorHandler.anim.GetBool("isInteracting"))
                return;

            //ローリングボタンを押した場合
            if (inputHandler.rollFlag)
            {
                moveDirection = cameraObject.forward * inputHandler.vertical;
                // moveDirection:カメラに対するプレイヤーの前後方向のベクトル
                //cameraObject.forward:カメラの正面の向きのベクトル。
                //カメラz軸向き(青色)をワールド座標系で表現された長さが1の単位ベクトル
                //inputHandler.vertical:プレイヤーの前後の向き。前+1,後ろー1

                moveDirection += cameraObject.right * inputHandler.horizontal;
                // moveDirection:カメラに対するプレイヤーの方向のベクトル
                //cameraObject.right:カメラの右向きのベクトル。
                //カメラx軸向き(赤色)をワールド座標系で表現された長さが1の単位ベクトル
                //inputHandler.horizontal:プレイヤーの左右の向き。右+1,左ー1

                //移動中(WASDが押された場合)
                if (inputHandler.moveAmount > 0)
                {
                    //ローリングアニメーションを実行
                    animatorHandler.PlayTargetAnimation("Rolling", true);
                    moveDirection.y = 0;

                 //   Quaternion rollRotation = Quaternion.LookRotation(moveDirection);
                    //LookRotation (Vector3 forward, Vector3 upwards= Vector3.up):指定された forward と upwards 方向に回転

                //    myTransform.rotation = rollRotation;
                }
                else
                {
                    // animatorHandler.PlayTargetAnimation("BackStep", true);
                }
            }
        }

    }
 public class AnimatorHandler : MonoBehaviour //+EP1 player直下のPaladinにアタッチ
    {
 //+EP4 キャラクターの動く速度と、アニメーションが同期してない場合に、フットスライディング(足滑り)が起こることを防ぐために、
        //キャラクターの動く速度を調整
        private void OnAnimatorMove()
        {
            //ローリング中ではない場合、関数を抜ける
            if (inputHandler.isInteracting == false)
                return;

            float delta = Time.deltaTime;

            playerLocomotion.rigidbody.drag = 0;
            //Drag (抗力) は、オブジェクトを減速するために使われます。 抗力が高いほどオブジェクトはより減速します。

            //アニメーションの1フレーム分の位置の差分
            Vector3 deltaPosition = anim.deltaPosition;

            deltaPosition.y = 0;

            //アニメーションの1フレーム分の速度
            Vector3 velocity = deltaPosition / delta;

            //アニメーションによるプレイヤー
           playerLocomotion.rigidbody.velocity = velocity;
        }
    }
 public class PlayerManager : MonoBehaviour //+EP4 playerにアタッチ
    {
        InputHandler inputHandler;
        Animator anim;

        void Start()
        {
            inputHandler = GetComponent<InputHandler>();
            anim = GetComponentInChildren<Animator>();
        }

        void Update()
        {
            //変数isInteractingを取得
            inputHandler.isInteracting = anim.GetBool("isInteracting");

            inputHandler.rollFlag = false;
        }
    }


・AnimatorのRollingノードに下記スクリプトをアタッチします。

public class ResetIsInteracting : StateMachineBehaviour
{
 //+EP4
    // OnStateExit is called when a transition ends and the state machine finishes evaluating this state
    override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        animator.SetBool("isInteracting", false);
    }
}

今回は以上です。