前提・実現したいこと
AssetStoreの「BasicMotions FREE Pack」を使って、モーションをアタッチした3Dモデルを操作したい(WASDで移動、spaceでジャンプ)
床と接地しているときにジャンプを行えるようにする。
発生している問題・エラーメッセージ
AnimationControllerでモーションの遷移を設定し、Rigidbodyなどの設定も行ったが、操作対象のモデルが床を貫通して落下してしまう。接地していないのでモーションが行えない。
該当のソースコード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CharCon : MonoBehaviour { private float walkSpeed = 2.0f; // 歩行速度 private float runSpeed = 4.0f; // 走行速度 private Vector3 movement; // 移動するベクター private float gravity = 20.0f; // キャラへの重力 private float speedSmoothing = 10.0f; // 回頭するときの滑らかさ private float rotateSpeed = 500.0f; // 回頭の速度 private float runAfterSeconds = 0.1f; // 走り終わったとき止まるまでの時間(秒) private Vector3 moveDirection = Vector3.zero; // カレント移動方向 private float verticalSpeed = 0.0f; // カレント垂直方向速度 private float moveSpeed = 0.0f; // カレント水平方向速度 private CollisionFlags collisionFlags; // controller.Move が返すコリジョンフラグ:キャラが何かにぶつかったとき使用 private float walkTimeStart = 0.0f; // 歩き始める速度 // Use this for initialization void Start() { moveDirection = transform.TransformDirection(Vector3.forward); // キャラの移動方向をキャラの向いている方向にセットする } // Update is called once per frame void Update() { Transform cameraTransform = Camera.main.transform; // カメラの向いている方向を得る Vector3 forward = cameraTransform.TransformDirection(Vector3.forward); // camera の x-z 平面から forward ベクターを求める forward.y = 0; // Y方向は無視:キャラは水平面しか移動しないため forward = forward.normalized; // 方向を正規化する Vector3 right = new Vector3(forward.z, 0, -forward.x); // 右方向ベクターは常にforwardに直交 float v = Input.GetAxisRaw("Vertical"); // 垂直方向の値 float h = Input.GetAxisRaw("Horizontal"); // 水平方向の値 float sp = Input.GetAxis("File3"); Vector3 targetDirection = h * right + v * forward; // カメラと連動した進行方向を計算:視点の向きが前方方向 if ((collisionFlags & CollisionFlags.CollidedBelow) != 0 && sp==0) // 接地時 { if (targetDirection != Vector3.zero) { if (moveSpeed < walkSpeed * 0.9) { moveDirection = targetDirection.normalized; } else { moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000); moveDirection = moveDirection.normalized; } } float curSmooth = speedSmoothing * Time.deltaTime; // 向きをスムースに変更 float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f); // 最低限のスピードを設定 // 歩く速度と走る速度の切り替え:最初は歩いてで時間がたつと走る if (Time.time - runAfterSeconds > walkTimeStart) targetSpeed *= runSpeed; else targetSpeed *= walkSpeed; // 移動速度を設定 moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth); Animator animator = GetComponent<Animator>(); // Animator コンポーネントを得る animator.SetFloat("speed", moveSpeed); // Animator に移動速度のパラメータを渡す animator.SetBool("air", false); // Animator に落下フラグのパラメータを渡す:落下していない if (moveSpeed < walkSpeed * 0.3) // まだ歩きはじめ walkTimeStart = Time.time; // その時間を保存しておく verticalSpeed = 0.0f; // 垂直方向の速度をゼロに設定 } else // 宙に浮いている { Animator animator = GetComponent<Animator>(); // Animator コンポーネントを得る animator.SetBool("air", true); // Animator に落下フラグのパラメータを渡す:落下している } movement = moveDirection * moveSpeed + new Vector3(0, verticalSpeed, 0); // キャラの移動量を計算 movement *= Time.deltaTime; CharacterController controller = GetComponent<CharacterController>(); // キャラクターコントローラコンポーネントを取得 collisionFlags = controller.Move(movement); // キャラを移動をキャラクターコントローラに伝える if ((collisionFlags & CollisionFlags.CollidedBelow) != 0) // 宙に浮いていない場合 { transform.rotation = Quaternion.LookRotation(moveDirection); // 移動方向に回頭:浮いていると回頭しない } } }
試したこと
3DモデルにColliderコンポーネントの代わりにCharacterControllerを設定。
![
補足情報(FW/ツールのバージョンなど)
文献としてUnityゲーム プログラミングバイブルを参考にし、プログラムもNo.3のサンプルを改変したものです。
Unityのバージョンは2020.1.4f1です。
回答1件
あなたの回答
tips
プレビュー