こんにちは、ちゃらいプログラマです。
3Dモデルを触る機会がありましたので、モーションもあることからどうせなら動かしてみたい!と思って作ってみました。
移動する範囲は、 NavMeshを利用することで簡単に実装できました。
移動先は、移動対象のGameObjectに「NavMeshAgent」コンポーネントを追加しプログラム側で以下のように実装するだけで向きに合わせて回転もしてくれます。
[SerializeField] NavMeshAgent Agent = null; void Update() { Agent.SetDestination( 指定座標::Vector3 ); }
アニメーション設定も回転方向に合わせて調整。
Rotateパラメータが30を超えた時にモーションを変更するようにしています。(Walkに戻すときは30未満になったらとしています)
サンプルプログラムはこちらになります。
public class Player : MonoBehaviour { [SerializeField] private Animator Animator = null; [SerializeField] private NavMeshAgent Agent = null; [SerializeField] private Vector3[] NavPositionList = null; private int _navIndex = 0; private Vector3 _currentPosition = Vector3.zero; // Start is called before the first frame update void Start() { _setTargetPosition(); _setCurrentPosition(); } // Update is called once per frame void Update() { // 経路設定 Agent.SetDestination( NavPositionList[_navIndex] ); _setCurrentPosition(); // 回転値設定 var diff = NavPositionList[_navIndex] - _currentPosition; var axis = Vector3.Cross( transform.forward, diff ); var angle = Vector3.Angle( transform.forward, diff ) * (axis.y < 0 ? -1 : 1); Animator.SetFloat( "Rotate", angle ); // 待ちモーション設定 Animator.SetBool( "IsWait", false ); if( Random.Range(0, 500) == 0 && !Animator.GetCurrentAnimatorStateInfo(0).IsName( "IdleLookAround" ) ) { Animator.SetBool( "IsWait", true ); } // 移動値設定 Agent.speed = Animator.GetCurrentAnimatorStateInfo(0).IsName( "IdleLookAround" ) ? 0f : 1f; if( Vector3.Distance( NavPositionList[_navIndex], _currentPosition ) <= 1f ) { _setTargetPosition(); } // カメラ注視点更新 Camera.main.transform.LookAt( transform ); } private void _setTargetPosition() { _navIndex = Random.Range( 0, NavPositionList.Length ); } private void _setCurrentPosition() { _currentPosition.x = transform.position.x; _currentPosition.z = transform.position.z; } }
移動範囲内に障害物が無いので楽してますが、移動できない範囲もNavMeshで設定可能なのでよさそうですね。
今回は全てが新しい体験だったのですごく楽しかったです。上手く製品に落とし込んで行きたいです。
では、また次回!