公開日:2023/07/08  更新日:2023/07/08

UnityのNavMeshの使い方

 前回までの記事で敵がビーム攻撃と剣による近接攻撃を使い分けるようにした。


 前回までの記事↓
TPSのキャラ移動
ジャンプ
ダッシュ実装
自作キャラを動き回らせる
剣を振る方法
剣コンボ
足が浮く対策
剣の軌跡の作り方
燃える剣の必殺技
ステータス管理
ダメージ判定・処理
HPゲージ
敵の攻撃
メッシュ変形での範囲攻撃
ビーム攻撃

 しかし、現状では敵は移動しないので、まだまだ未完成である。そこでNavMeshを使っていく。
 NavMeshを使うことでAIに3Dモデルを移動させることができる。
 具体的にはある目標地点まで移動する、障害物を避けて移動する、ある地点を経由して移動する。などといったことが可能。
 NavMeshの使い方について紹介していく。

UnityのNavMeshの使い方

NavMeshの適用
スクリプト記述
アニメーション設定
目次にもどる

NavMeshの適用

 以前の記事で作ったスケルトンがNavMeshで行動できるようになることを目指す(どの3Dモデルを動かすかはお好みでいいが、3Dモデルを用意しRigidbodyとコライダーをつけるところまではやっておく)。
 スケルトンが移動するためのステージを作成する。これもお好みで。自分はPlaneでステージの土台を作った後、いくつかCubeを配置して障害物とした。

 この時Goalとなるゲームオブジェクトも作っていこう(後でGoalの場所までスケルトンが移動する機能を実装する)。

 まずPlaneを選択し、インスペクター欄のStaticと書いている部分の右の矢印を選択しよう。

 以下のような画面が出るので、「Navigation Static」を選択しよう。

 同様に土台や障害物となるゲームオブジェクト全てで「Navigation Static」を選択する。

 上部メニューのWindows→AI→Navigationのように選択しよう。


 いつも見ているインスペクターに新たにNavigationタブが追加されているので選択しよう。加えてBakeを選択しよう。

 その一番下の「Bake」を選択することで、「Navigation Static」を選択したゲームオブジェクトの位置を元に移動できる経路を計算することができる。

 インスペクター欄に戻そう。スケルトンのコンポーネントとしてNav Mesh Agentを追加する(Add Component→Navigation→Nav Mwsh Agentのように選択すればOK)。

 なお、NavMeshで移動させているスケルトンがPlayerとぶつかると、急激に吹っ飛ぶなどおかしい動きをする(コライダーとRigidbodyを持っているゲームオブジェクト同士が衝突すると起こる場合がある)。対策としてはスケルトンのRigidbodyのFreeze PositionのX、Y、Zにチェックを入れよう。

 これでぶつかってもスケルトンの位置が動かなくなる。
目次にもどる

スクリプト記述

 スケルトンがGoalのゲームオブジェクトまで移動するように設定をしていく。
 プロジェクトビューでスクリプトを作成し、CharaNaviと名付けスケルトンにアタッチする。以下のように記述する。
 最初にシリアル化を行っている。targetObjectとしてGoalのゲームオブジェクトをセットしておこう。

 StartメソッドでスケルトンのNavMeshAgentを取得しておく。
 UpdateメソッドでmyAgent.SetDestination(targetObject.position);と記述。NavMeshによってtargetObjectの位置へ向かって移動することができる。
目次にもどる

アニメーション設定

 スケルトンはGoalまで確かに移動する。だがアニメーションの設定をしておらず、静止状態で足を動かすこともないまま移動する。
 また、以下の記事などで作った攻撃中のアニメーション再生の際も移動するので明らかに不自然だ。
ビーム攻撃

 修正のためにまずはスケルトンのAnimatorControllerにステートを追加する。以下のようにIdouステートを追加した。

 IdouステートのAnimatorClipは以下のフリー素材(2023年4月時点ではフリー)を使用。

 Melee Warrior Animations→Animations→OneHanded→Movementの1H@Run01を使用する。移動するアニメーションとなっている。
 Idouryouのfloatパラメータを作成し、Idouryouが0.01を超える時にIdleステート→Idouステートに遷移。Idouryouが0.01より小さい時にIdouステート→Idleステートに遷移するように設定しておく。
 IdouステートからAttackやAttack11への遷移もIdleから各攻撃ステートに遷移する場合と同様に設定しておく。
 各遷移のHas Exit Timeのチェックは外しておく。

 CharaNaviのスクリプトに以下のように記述を追加する。
 スケルトンのAnimatorControllerで使用しているAttackパラメータをAttackに代入している。Attackが0であれば攻撃はしておらずAttackが1以上なら何らかの攻撃を行っている。
 if文でAttackが0で攻撃していない場合にNavMeshでの移動を行うようにしている。myAgent.isStopped = false;とすることでNavMeshをアクティブ化している。
 その上でmyAgent.SetDestination(targetObject.position);で移動。
 更にNextposition = myAgent.steeringTarget;と記述することで、次に移動する位置を取得可能。今の位置から引くことで移動距離がわかる。ベクトルを正規化しその値をIdouryouパラメータに入れる。
 Idouryouパラメータに0.01を超える値が入ることで、Idouステートの移動するAnimationClipが再生される。移動距離が0である場合はIdouryouパラメータにも0が入りIdleステートとなり静止のAnimationClipが再生される。

 Attackが0ではなくif文の条件に当てはまらなかった場合はelseの中身のmyAgent.isStopped = true;が処理されNavMeshが非アクティブとなる。これで攻撃中にはNavMeshでの移動が行われなくなる。

 以上の作業でスケルトンが以下のように足を動かして目標位置(紫ゲームオブジェクト)まで移動し、Playerを見つけると足を止めて攻撃する。


 続きの記事は以下。
敵の徘徊
Unityのゲーム制作まとめへ戻る

page top