主なコンテンツ

〜主なコンテンツ〜

1. Unityで製作したゲームと製作Tips
  1. 三月精チャレンジ(東方Project二次創作)
    1. 作り方
  2. 英語学習2D(オリジナルスマホアプリ)
2. UE4
3. ゲームアプリ見学
4. Bitbucket & SourceTreeでの一連の流れ
  1. 前半
  2. 後半
5. Tips
  1. UnityのTips
  5. SQL文のTips
  6. Final IK
  7. GearVR+Unity

2016年3月8日火曜日

追尾してくる敵【三月精チャレンジ】

■NavmeshAgentについて

  • NavmeshAgentを使えば、障害物(コライダー)を考慮して目的地に向かうオブジェクトを作ることができる
  • プレイヤーの位置は操作によって変わるので、UpdateでNavMeshAgent.SetDestination (player.position)としてあげれば、現在のプレイヤーの座標を目指すオブジェクトができる
  • NavmeshAgentを使うためにはツールメニューの WIndow > Navigation から、移動できる範囲を設定(Bake)する必要がある(参考
  • ゲームオーバー時などに追尾をやめさせるには、このコンポーネントを非アクティブにすればよい

■ブレンドツリーによるアニメーションの切り替え

  • NPCである敵は入力によって移動のアニメーションを切り替えることができない
  • そこで、Animatorのブレンドツリーを使う(参考
  • 閾値が何を意味するかは公式のマニュアルを参照のこと
  • 参考先の記事では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を用いてプレハブ化に対応したほうが良い。(>>参考記事

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 件のコメント:

コメントを投稿