【ダークソウル風ゲームを作りたい(Unity)。その1】
今回からダークソウル風ゲームを作っていきたいと思います。
今回はプレイヤーの移動を実装します。
youtu.be
・Planeを設置し、キャラクターを配置します。
私はmixamoからキャラクターをダウンロードしました。
・Input systemをPackageManagerでインストールします。
・Input Actionsを作成(PlayerControls)を作成し、下記のように設定しました。
RightStick[GamePad]はProcessorにStickDeadZone(デッドゾーン:特定範囲の入力値を補正すること)を設定します。
詳細は下記参照。
nekojara.city
・プレイヤーにCapsuleColliderとRigidbodyをアタッチします。
・プレイヤーに下記スクリプトを追加します。
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace SG { public class InputHandler : MonoBehaviour //+EP1 playerにアタッチ { public float horizontal; public float vertical; public float moveAmount; public float mouseX; public float mouseY; PlayerControls inputActions; Vector2 movementInput; Vector2 cameraInput; public void OnEnable() //OnEnableはオブジェクトが有効になったときに呼び出されます. { if (inputActions == null) { inputActions = new PlayerControls(); //アクション実行中(performed)に、+=でデリゲート登録されたメソッドが実行される。 inputActions.PlayerMovement.Movement.performed += inputActions => movementInput = inputActions.ReadValue<Vector2>(); inputActions.PlayerMovement.Camera.performed += i => cameraInput = i.ReadValue<Vector2>(); } //インプットアクションの有効化 inputActions.Enable(); } private void OnDisable() { //インプットアクションの無効化 inputActions.Disable(); } public void TickInput(float delta) { MoveInput(delta); } //キーボードやマウスの入力値を取得 public void MoveInput(float delta) { //Actions:Movementのx方向入力値(キーボードA(-1) or D(+1))を変数horizontalに代入 horizontal = movementInput.x; //Actions:Movementのy方向入力値(キーボードW(+1) or S(-1))を変数Verticalに代入 vertical = movementInput.y; //Clamp値(0~1)を変数moveAmountに代入。WASDの押下により1が代入される。 moveAmount = Mathf.Clamp01(Mathf.Abs(horizontal) + Mathf.Abs(vertical)); //Actions:Cameraの入力値(マウスの場合、前フレーム位置からの差分)を変数mouseに代入 //mouseXはx方向値(画面横方向のデルタ値)を代入。 //mouseYはy方向値(画面縦方向のデルタ値)を代入。 mouseX = cameraInput.x; mouseY = cameraInput.y; } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace SG { public class PlayerLocomotion : MonoBehaviour //+EP1 playerにアタッチ { Transform cameraObject; InputHandler inputHandler; Vector3 moveDirection; [HideInInspector] public Transform myTransform; [HideInInspector] public AnimatorHandler animatorHandler; public new Rigidbody rigidbody; public GameObject normalCamera; [Header("Stats")] [SerializeField] float movementSpeed = 5; //移動スピード [SerializeField] float rotationSpeed = 10; //歩行スピード private void Start() { rigidbody = GetComponent<Rigidbody>(); inputHandler = GetComponent<InputHandler>(); animatorHandler = GetComponentInChildren<AnimatorHandler>(); //MainCameraのtransformを取得 cameraObject = Camera.main.transform; myTransform = transform; animatorHandler.initialize(); } public void Update() { //Time.deltaTime:前回のフレームからの経過時間 float delta = Time.deltaTime; inputHandler.TickInput(delta); 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(); float speed = movementSpeed; moveDirection *= speed; //ProjectOnPlane:斜面に沿ったベクトルを計算 Vector3 projectedVelocity = Vector3.ProjectOnPlane(moveDirection, normalVector); //velocityによりプレイヤー移動 rigidbody.velocity = projectedVelocity; //animatorの変数Verticalと変数Horizontalの値を設定 animatorHandler.UpdateAnimatorValues(inputHandler.moveAmount, 0); if (animatorHandler.canRotate) { HandleRotaion(delta); } } #region Movement Vector3 normalVector; Vector3 targetPosition; //プレイヤーの回転方向を制御 private void HandleRotaion(float delta) { Vector3 targetDir = Vector3.zero; float moveOverride = inputHandler.moveAmount; targetDir = cameraObject.forward * inputHandler.vertical; targetDir += cameraObject.right*inputHandler.horizontal; //正規化されたときベクトルは同じ方向は維持したままで長さが 1.0 のものが作成されます。 targetDir.Normalize(); targetDir.y = 0; //WASDを押してない場合 if (targetDir == Vector3.zero) targetDir = myTransform.forward; float rs = rotationSpeed; Quaternion tr = Quaternion.LookRotation(targetDir); //指定された forward(targetDir) と upwards 方向に回転します。 //public static Quaternion Slerp (Quaternion a, Quaternion b, float t): a と b の間を t で球状に補間します。 //パラメーター t は、[0, 1] の範囲です。 //回転がゆるやかになる。 Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta); myTransform.rotation = targetRotation; } #endregion } }
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace SG { public class AnimatorHandler : MonoBehaviour //+EP1 player直下のPaladinにアタッチ { public Animator anim; int vertical; int horizontal; public bool canRotate; public void initialize() { anim = GetComponent<Animator>(); //animatorからstring名の値を取得 vertical = Animator.StringToHash("Vertical"); horizontal = Animator.StringToHash("Horizontal"); } public void UpdateAnimatorValues(float verticalMovement,float horizontalMovement) { #region Vertical float v = 0; //引数により変数vを設定 if(verticalMovement>0 && verticalMovement < 0.55f) { v = 0.5f; } else if (verticalMovement > 0.55f) { v = 1; } else if (verticalMovement < 0 && verticalMovement > -0.55f) { v = -0.5f; } else if (verticalMovement < -0.55f) { v = -1; } else { v = 0; } #endregion #region float h = 0; if(horizontalMovement>0 && horizontalMovement < 0.55f) { h = 0.5f; } else if (horizontalMovement > 0.55f) { h = 1; } else if (horizontalMovement < 0 && horizontalMovement > -0.55f) { h = -0.5f; } else if (horizontalMovement < -0.55f) { h = -1; } else { h = 0; } #endregion // anim.SetFloat(id, 値,値が変化する幅 , 1フレームの時間幅); anim.SetFloat(vertical, v, 0.1f, Time.deltaTime); anim.SetFloat(horizontal, h, 0.1f, Time.deltaTime); } public void CanRotate() { canRotate = true; } public void StopRotation() { canRotate = false; } } }
・Animatorコントローラーを作成し、BlendTree(Locomotion)を作ります。また、パラメータverticalとhorizontalを追加します。
・BlendTree(Locomotion)でIdle、walking、Runアニメーションを設定します。
アニメーションはmixamoからダウンロードしました。
アニメーションの設定です(Idle,Walking,Run全て同じ設定)。
Rig設定をHumanoidに変更。
LoopTimeとLoopPoseにチェック。
【Root Transform Rotation】
Bake Into Poseにチェック:チェックを入れるとオブジェクトの向きが、アニメ―ションによる回転に左右されなくなります。
Based UponをOriginalにする:Idle時にBody Orientation設定だと斜め前を見ているがBased UponをOriginalに設定すると正面を向くようになった為、idle以外にも適用。
アニメーション設定については下記参照。
xr-hub.com
今回は以上です。