【ダークソウル風ゲームを作りたい(Unity)。その5】
今回はスプリントアニメーションを実装します。
youtu.be
・スプリントアニメーションを用意します。私はmixamoからダウンロードしました。
RigをHumanoidに変更します。Animationを下記のように設定します。
・スプリントアニメーションをBlend Treeに設定します。
・下記スクリプトを追加します。
public class InputHandler : MonoBehaviour //+EP1 playerにアタッチ { public float rollInputTimer; //+EP5 ローリングボタンを押下している時間を格納 public bool sprintFlag; //+EP5 スプリントフラグがOnの場合、true //+EP4 ローリングをONした場合の設定 private void HandleRollInput(float delta) { //ローリングボタン押下でb_input=true b_Input = inputActions.PlayerActions.Roll.phase == UnityEngine.InputSystem.InputActionPhase.Started; //ローリングボタンを押下中 if (b_Input) { //+EP5 rollInputTimer += delta; sprintFlag = true; } else //+EP5 { //ローリングボタンを下記条件でON/OFFした場合、ローリングを行う if(rollInputTimer>0 && rollInputTimer < 0.5f) { sprintFlag = false; rollFlag = true; } rollInputTimer = 0; } } }
public class PlayerLocomotion : MonoBehaviour //+EP1 playerにアタッチ { float sprintSpeed = 7; //+EP5 スプリントスピード public void Update() { //Time.deltaTime:前回のフレームからの経過時間 float delta = Time.deltaTime; isSprinting = inputHandler.b_Input; //+EP5 inputHandler.TickInput(delta); HandleMovement(delta); HandleRollingAndSprinting(delta); //+EP4 } //+EP4 プレイヤーの移動を制御 public void HandleMovement(float delta) { //+EP5 ローリング中の場合、以降なにもしない if (inputHandler.rollFlag) return; moveDirection = cameraObject.forward * inputHandler.vertical; //cameraObject.forward:world spaceに対するプレイヤーの前方位置(0.0, 0.0, -1.0) //inputHandler.vertical:キーボードW(+1) or S(-1) //moveDirection:キーボードW(0.0, 0.0, -1.0) or S(0.0, 0.0, 1.0) moveDirection += cameraObject.right * inputHandler.horizontal; //cameraObject.right:world spaceに対するプレイヤーの右位置(-1.0, 0.0, 0.0) //inputHandler.horizontal:キーボードA(-1) or D(+1) //cameraObject.right * inputHandler.horizontal:キーボードA(1.0, 0.0, 0.0) or D(-1.0, 0.0, 0.0) // moveDirection:キーボードW,A押下の場合(1.0, 0.0, -1.0) //正規化:ベクトルの向きは変えずに大きさを1にする moveDirection.Normalize(); moveDirection.y = 0; //+EP2 float speed = movementSpeed; //+EP5 スプリントフラグがONになった場合の設定 if (inputHandler.sprintFlag) { speed = sprintSpeed; isSprinting = true; moveDirection *= speed; } else { moveDirection *= speed; } //ProjectOnPlane:斜面に沿ったベクトルを計算 Vector3 projectedVelocity = Vector3.ProjectOnPlane(moveDirection, normalVector); //velocityによりプレイヤー移動 rigidbody.velocity = projectedVelocity; //animatorの変数Verticalと変数Horizontalの値を設定 animatorHandler.UpdateAnimatorValues(inputHandler.moveAmount, 0, isSprinting); if (animatorHandler.canRotate) { HandleRotaion(delta); } } }
public class AnimatorHandler : MonoBehaviour //+EP1 player直下のPaladinにアタッチ { public void UpdateAnimatorValues(float verticalMovement,float horizontalMovement,bool isSprinting) { Vertical Horizontal //+EP5 スプリントフラグがONになった場合の設定 if (isSprinting) { v = 2; h = horizontalMovement; } // anim.SetFloat(id, 値,値が変化する幅 , 1フレームの時間幅); anim.SetFloat(vertical, v, 0.1f, Time.deltaTime); anim.SetFloat(horizontal, h, 0.1f, Time.deltaTime); } }
public class PlayerManager : MonoBehaviour //+EP4 playerにアタッチ { void Update() { //変数isInteractingを取得 inputHandler.isInteracting = anim.GetBool("isInteracting"); inputHandler.rollFlag = false; inputHandler.sprintFlag = false; //+EP5 } }
今回は以上です。
【メタルギアソリッド風ゲームを作りたい(UE4)。その15】
今回は敵キャラクターAIの実装で、決まったルート巡回するように設定します。
youtu.be
・キャラクターのアニメーションをベースに敵キャラのアニメーションを作ります。
・BP(BP_EnemyAI)を作成し、メッシュと武器を配置します。
また、武器が特定の位置になるように下記BPを追加します。
・敵AIの実装をしていきます。AIControllerやビヘイビアツリー、ブラックボードを使用しますが、詳細は下記参照。
docs.unrealengine.com
・AIControllerを作成し、下記BPを追加します。
・ビヘイビアツリーとブラックボードを作ります。ブラックボードにキーを追加します。
・巡回ルートの設定をします。ActorクラスのBPを作成し、巡回ルートに配置します。
・TaskクラスのBPを作成します。巡回ポイントのロケーションをブラックボードに設定しています。
・ビヘイビアツリーを下図のように設定します。上記のタスクで設定したポイントに向けてMove Toノードでキャラクター移動させます。
その後、1秒間待機し、次のポイントに向けて移動します。
今回は以上です。
【ダークソウル風ゲームを作りたい(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); } }
今回は以上です。
【メタルギアソリッド風ゲームを作りたい(UE4)。その14】
今回は今後の方針についての動画になります。
youtu.be
今回は以上です。