【ダークソウル風ゲームを作りたい(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); } }
今回は以上です。