■NavmeshAgentについて
- NavmeshAgentを使えば、障害物(コライダー)を考慮して目的地に向かうオブジェクトを作ることができる
- プレイヤーの位置は操作によって変わるので、UpdateでNavMeshAgent.SetDestination (player.position)としてあげれば、現在のプレイヤーの座標を目指すオブジェクトができる
- NavmeshAgentを使うためにはツールメニューの WIndow > Navigation から、移動できる範囲を設定(Bake)する必要がある(参考)
- ゲームオーバー時などに追尾をやめさせるには、このコンポーネントを非アクティブにすればよい
■ブレンドツリーによるアニメーションの切り替え
- 参考先の記事ではVector3.sqrMagnitudeを使っていたが、NavmeshAgentはブレーキ等の速度調整に極端に小さい速度ベクトルを小刻みに織り交ぜているらしく値がひどく荒ぶった。また、コンポーネント側で設定している上限速度を大きく振り切ることも度々あった。原因不明。そのため、今回は振れ幅を少しでも抑えるためにVector3.maghitudeを使った。
- なお、Vector3.sqrMagnitudeはベクトルの大きさの2乗を返す関数。平方根の計算をしない分処理が早い。大きさの比較なら平方根である必要がないので重宝される。
■攻撃モーションとの対応
- NavMeshAgentの速度ベクトルは、前述の通りNavMeshAgent.velocityで得られる。また、この値を書き換えることで任意の速度ベクトルに書き換えることができる。これを利用することで攻撃中は減速させたり、停止させたりすることができる。
- 現在何のアニメーションを再生しているかは、Animator.GetCurrentAnimatorStateInfoで得られるAnimatorStateInfo構造体から簡易的に調べることができる。
- Animator.GetCurrentAnimatorStateInfo(0) のように末尾で指定する番号はAnimatorのレイヤーの階層である。0はBase Layerを指す。
- なお、アニメーションは文字列ではなくint 型のハッシュで判定を行う
- 詳しくはこちらの記事と、そこでの参考先を参照のこと
■スクリプト(敵キャラクターにアタッチ)
*public Transform playerでプレイヤーのTransformを参照しているが、敵をプレハブ化するとHierarchyのオブジェクトをInspectorから参照することはできない。ここはFindWithTagを用いてプレハブ化に対応したほうが良い。(>>参考記事)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class EnemyMovement : MonoBehaviour { | |
public float slowSpeed; | |
public Transform player; | |
private NavMeshAgent nav; | |
private Animator animator; | |
private int currentPath=0; | |
private GameOverManager gameOverManager; | |
readonly int attack1Path = Animator.StringToHash ("Base Layer.Attack1"); | |
readonly int attack2Path = Animator.StringToHash ("Base Layer.Attack2"); | |
// Use this for initialization | |
void Start () { | |
//HierarchyからGameOverManagerを見つけて代入 | |
GameObject manager = GameObject.FindWithTag("Manager"); | |
gameOverManager = manager.GetComponent<GameOverManager>(); | |
//コンポーネントの取得 | |
nav = GetComponent <NavMeshAgent> (); | |
animator = GetComponent <Animator> (); | |
} | |
// Update is called once per frame | |
void Update () { | |
//ゲームオーバーの監視 | |
if(gameOverManager.IsCalled){ | |
nav.enabled = false; | |
return; | |
} | |
//常にプレイヤーを向かせる | |
transform.LookAt(player.position); | |
//目的地の更新(Playerの現在の位置) | |
nav.SetDestination (player.position); | |
//アニメーターに現在の速度を渡す | |
animator.SetFloat("Speed", nav.velocity.magnitude);//<! 値が荒ぶるのでsqrMagnitudeを使えず | |
//アニメーション中の挙動 | |
BehaviourOnAnimation(); | |
} | |
void BehaviourOnAnimation(){ | |
//現在再生しているアニメーションが攻撃モーションか確認 | |
currentPath = animator.GetCurrentAnimatorStateInfo (0).fullPathHash; | |
if (currentPath == attack1Path || currentPath == attack2Path) { | |
nav.velocity = nav.velocity.normalized * slowSpeed; | |
} | |
} | |
} |
〜その他、参考にさせていただいたサイト様〜
【Unity】Rayの使い方まとめ
UnityでゲームAIを作るチュートリアル
0 件のコメント:
コメントを投稿