※ これは 2018/01/08 Unity 2017.3.0f3 時点の情報です
最新版では動作が異なる可能性がありますのでご注意ください
歩きモーションのアニメができたので、今回は歩きながらカメラに近づいてくる動きを実装してみます
少し前に書いた顔を向けるスクリプトを次のように変更
using UnityEngine; [RequireComponent(typeof(Animator))] public class Beast : MonoBehaviour { /// <summary> /// 顔の部分のボーン /// </summary> [SerializeField] private Transform coreBone = null; /// <summary> /// キャッシュ用カメラ Transform /// </summary> private Transform camra; private Animator animator; /// <summary> /// 状態の列挙型 /// </summary> internal enum State { /// <summary> /// 待機状態 /// </summary> Idle, /// <summary> /// 歩行中 /// </summary> Walk, } /// <summary> /// 現在の状態 /// </summary> private State state; /// <summary> /// 正面を向いた顔の角度 /// </summary> private static readonly Quaternion DefaultCoreAngle = Quaternion.Euler(90f, 0f, 0f); /// <summary> /// 初期処理 /// </summary> public void Start() { this.camra = Camera.main.transform; this.animator = this.GetComponent<Animator>(); this.state = State.Idle; } /// <summary> /// 可変毎フレームごとの処理 /// </summary> public void Update() { // 距離の判定に高低差を考慮しない var cameraPosition = this.camra.position; cameraPosition.y = this.transform.position.y; if (Vector3.Distance(cameraPosition, this.transform.position) > 2f) { this.animator.SetBool("IsWalking", true); this.state = State.Walk; } else { this.animator.SetBool("IsWalking", false); this.state = State.Idle; } } /// <summary> /// 固定毎フレームの処理 /// </summary> public void FixedUpdate() { var cameraPosition = this.camra.position; switch (this.state) { case State.Idle: // 目の高さに合わせる cameraPosition.y -= 0.3f; // 顔だけカメラに向かせる(X軸の回転) this.transform.LookAt(cameraPosition); var angle = this.transform.rotation.eulerAngles.x; angle = angle > 180f ? angle - 360f : angle; this.coreBone.localRotation = Quaternion.Euler(90f + Mathf.Clamp(angle, -30f, 30f), 0f, 0f); // 身体全体をカメラに向ける(Y軸の回転) cameraPosition.y = this.transform.position.y; this.transform.LookAt(cameraPosition); break; case State.Walk: // 顔を正面に向ける this.coreBone.localRotation = DefaultCoreAngle; // 身体全体をカメラに向ける(Y軸の回転) cameraPosition.y = this.transform.position.y; this.transform.LookAt(cameraPosition); // カメラに向かって移動 var delta = Mathf.Clamp(Vector3.Distance(cameraPosition, this.transform.position) - 2f, 0f, 0.01f); this.transform.position = Vector3.MoveTowards(this.transform.position, cameraPosition, delta); break; } } }
列挙型で Idle と Walk の2つの状態を定義しました
カメラとの距離が 2m より離れたら Walk 状態に切り替え、歩きモーションの再生開始と Vector3.MoveTowards() メソッドで移動する処理を追加
カメラとの距離が 2m 以内の場合は Idle 状態に切り替え、歩きモーションを停止し以前の顔を向ける処理だけを行うようにしました
状態とモーションの切替は即座に行われるように Update() メソッド内で実行しますが、移動や運動系の変化は固定フレームで実行される FixedUpdate() メソッド内で実行します
これを UnityEditor 上で試してみると
だいたい思い通り