3rd term 5th week - dsuz/unity-game-dev1-3d-2019 GitHub Wiki
- ナビゲーション システム
- Navmesh
- Navmesh Agent コンポーネント
先週休んだり、プロジェクトが失われてしまった人は以下の要領で先週の授業終了時の状態のプロジェクトを準備してください。
- 新たに Unity のプロジェクトを作る
- テンプレートは 3D を選ぶ
- Asset Store から Basic Motions Pack をプロジェクトにインポートする
-
SDユニティちゃん 3Dモデルデータ の Ver 1.01 をダウンロードし、インポートする
- このデータをインポートすると以下のコンパイル エラーが出るので、該当行をコメントアウトもしくは削除する
Assets\UnityChan\Scripts\AutoBlinkforSD.cs(8,23): error CS0234: The type or namespace name 'Policy' does not exist in the namespace 'System.Security' (are you missing an assembly reference?)
- 3rd_week_completed.unitypackage をダウンロードし、インポートする
- 4th_week_asset.unitypackage をダウンロードし、インポートする
先週の課題を見て欲しい人は、授業が始まる前に申請してください。今週の内容のために先週の課題でやったことを戻すためです。
- 5th_week_assets.unitypackage をダウンロードし、先週のプロジェクトにインポートする
ナビゲーション システムを使うと、自動的に経路を計算してオブジェクトを移動させることができます。ナビゲーション システムを作るのに最低限必要なものは、Navmesh と Navmesh Agent コンポーネントです。
Navmesh を使うと、オブジェクトのメッシュに沿って2点間を移動する経路を自動的に計算することができます。Navmesh Agent コンポーネントを Navmesh の上に置き、目的地 (destination) を設定することで、Navmesh から自動的に経路を計算し、目的地まで移動させることができます。
シーン Navmesh を開き、以下のように動作を確認する。
- 画面内をクリックすると、その場所にカプセルが移動する
- クリックした場所に赤いマーカーを移動するために先週使った Raycast Controller を使っている
- 以下のように階段の間をジャンプしたり、階段から飛び降りることができる
- 緑色の橋は、緩い方の坂は上れるが、急な方の坂は上れない
- シーンビューを画面に表示し、メニューの Window > AI > Navigation から Navigation ウィンドウをアクティブにする
- Navigation ウィンドウが画面に表示されていると、以下のようにシーンビューに Navmesh の様子が表示される
- Referenced Script is missing の警告が出ている場合は、Package Manager から ProBuilder をインストールすることで出なくすることができる
- 警告が出るのは Arch や Stairs を作るのに ProBuilder を使っているため
シーン Navmesh の Capsule オブジェクトに Navmesh Agent コンポーネントがアタッチされているが、これの設定を変えることで動きを変えることができる。以下の要領で何を変えるとどう動きが変わるかを学んでいく。
- Base Offset を変えることで Transform の中心からどれくらい Agent の当たり判定をずらすかを設定できる
- 今回は値を変えるとカプセルが宙に浮いたりめり込んでしまうので変える必要はない
- Steering - Speed, Angular Speed でそれぞれ移動速度、回転速度を設定できる
- Speed を大きくすれば速く移動する
- Steering - Acceleration で加速度を設定できる
- 大きくすると早く最高速度に達する
- Steering - Stopping Distance で目的地 (destination) からどれくらいで停止するかを設定できる
- Steering - Auto Breaking をオンにすると、目的地にちょうど停止するように減速する
- オフにすると、少し通り過ぎてから戻るような挙動をする
その他の設定はまだ使わないが、以下に説明がある。
Navmesh Agent コンポーネントが目的地へ移動するには NavMeshAgent.SetDestination() 関数を呼び出して目的地を設定する必要がある。この処理は PlayerControllerAi.cs に実装されている。
今回扱う Navmesh は、事前に bake しておくタイプの Navmesh です。動的に(リアルタイムに)経路を計算するやり方もあります(NavMeshSurface コンポーネントを使う)が、まずは負荷の低い静的な Navmesh を学びます。
シーン Navmesh では、以下のようなことができています。
- 歩ける (walkable) 範囲から経路を計算する
- 坂道 (slope) を上る/下る
- 段差 (step) を登る/下る
- 飛ぶ (jump)
- 飛び降りる (drop)
以降では、これらの設定方法を学びます。
以下の手順でまずはもっとも基本的な Navmesh を作成する。
- 新しいシーンを作り、Plane の上に /Assets/Environment/Block プレハブを並べて以下のように適当な迷路を作る
- Plane を選択し、以下のように Inspector から Navigation Static に設定する
- 本来であれば Block も Navigation Static にしなければならないが、既に Static に設定済みである
- Static の設定は Navigation Static を設定するだけでよいが、Static のチェックボックスをクリックするだけでもよい
- Navigation ウィンドウを開き、以下のように Bake タブをクリックして Bake ボタンをクリックする
- Bake が完了すると、Scene 上に次のように Navmesh が表示される
- Navigation ウィンドウが表示されている時のみ Navmesh が Scene に表示されることを覚えておくこと
- これで Navmesh の作成は完了しており、以降の手順ではその上で動く Agent を作る
- /Assets/Environment/MarkerControl プレハブをシーンに配置する
- Capsule を Plane の上に作り、Player Controller AI コンポーネントと Navmesh Agent コンポーネントを追加する
- Player Controller AI コンポーネントの設定 Target に、Scene 内にある Marker オブジェクトをアサインする
- Marker オブジェクトは MarkerControl オブジェクトの子オブジェクトである
- Main Camera の位置と角度を調整し、以下のように迷路全体が Game ウィンドウに映るようにする
- シーンを実行して、画面をクリックしたり直接 Marker を動かすなどして Marker の場所を動かすと、Capsule がそれを追従することを確認する
Navmesh が作れたら、以下を試してみましょう。
- Block を動かして、迷路のレイアウトを変える
- 迷路のレイアウトを変えたら、シーンを実行して Navmesh Agent の挙動を確認する
- おそらく期待した挙動をしないでしょう
- Navigation ウィンドウと Scene ウィンドウを表示して、Navmesh の状態を確認する
- Navmesh を Bake する
- 再度シーンを実行して Navmesh Agent の挙動を確認する
以上のことから何がわかるのか考えてみましょう。
Navmesh では「移動できる最大角度 (Max Slope)」を設定することができる。以下の手順で「昇り降りできる/できない坂」を設定する。
- /Assets/Environment/Arch プレハブをシーンに配置する
- Navigation ウィンドウから Bake する
- Scene ビューを見て、以下のように両側から Arch に昇り降りできるようになっていることを確認する
- Navigation ウィンドウから以下のように Max Slope を 30 に変更する
- もう一度 Bake する
- 以下のように、急な方の坂が移動できなくなっていることを確認する
- シーンを実行して、Bake された Navmesh の通りに移動できることを確認する
つまり、Navigation の Max Slope の設定で「移動できる最大の角度」を設定することができる。
Navigation の Step Height を設定することで、「上ることができる段差の高さ」を設定することができる。以下の手順でそれを設定する。
- /Assets/Environment/Stairs プレハブをシーンに配置し、Navigation ウィンドウから Bake する
- Stairs は既に Static になっているので、Stairs を考慮して Navmesh が Bake される
- 以下のように段差を登れるように Navmesh が Bake される
- 以下のように、Navigation ウィンドウから Step Height を 1 に設定する
- 再度 Bake すると、Block が登れるように Navmesh が変化する
- シーンを実行し、Navmesh の通りに移動できることを確認する
つまり、Navigation の Step Height の設定で「上ることができる段差の最大の高さ」が設定できる。
Navigation の Jump Distance を指定することで、「飛ぶことができる距離」を指定することができる。以下の手順でそれを設定する。
- シーンの Stairs オブジェクトを複製し、以下のように向い合せになるよう回転・移動する
- このまま Bake しても飛べるようにはならないが、Navigation ウィンドウから Jump Distance を Stairs の離れた距離より大きく設定して Bake すると、以下のように階段を飛べるように Navmesh が Bake される
- Jump Distance の単位はメートルなので、Scene ウィンドウのグリッドが 1m x 1m であることを考慮して適当な値を設定する
- Jump できるようにするには、以下のように Static 設定の Off Mesh Link Generation にチェックを入れておく必要がある
- Stairs プレハブは既に Static 設定になっているので改めて設定する必要はないが、Jump するためには Off Mesh Link Generation にすることを覚えておくこと
- Off Mesh Link Generation とは「メッシュに接触していないつながりを生成する」という意味である
- シーンを実行して Navmesh の通りに移動できることを確認する
つまり、Mesh のあるオブジェクトを Off Mesh Link Generation に設定し、Jump Distance を設定することでオブジェクトの間をジャンプするための Off Mesh Link を生成することができる。
Navigation の Drop Height を設定することで、「飛び降りることができる高さ」を設定できる。以下の手順でそれを設定する。
- 以下のように Navigation ウィンドウの Drop Height を 2 に変更する
- Navmesh を Bake することで、以下のように階段から飛び降りる Off Mesh Link が作られる
- Drop Height も、Jump Distance と同様に Off Mesh Link Generation に設定する必要がある
- Navigation ウィンドウ Drop Height, Jump Distance の設定が Generated Off Mesh Link にカテゴライズされていることに注意しておくこと
- このカテゴライズは、これらの設定が Off Mesh Link であることを示している
- シーンを実行して Navmesh の通りに移動できることを確認する
つまり、Mesh のあるオブジェクトを Off Mesh Link Generation に設定し、Jump Distance を設定することでオブジェクトの間をジャンプするための Off Mesh Link を生成することができる。
- Arch オブジェクトは Off Mesh Link Generation になっていませんが、これを Off Mesh Link Generation に設定して Bake してみましょう
- Drop Height の値を 4 や 1 にして Bake し、Navmesh がどのように変化するか観察しましょう
ここまで Navmesh Agent で動かしているオブジェクトはカプセルだったが、これをキャラクターにしてアニメーションと組み合わせる。
- Navmesh Agent コンポーネントが追加されている Capsule オブジェクトの Mesh Renderer と Capsule Collider を無効にする
- Mesh Renderer はカプセルを見えなくするために無効にする
- Capsule Collider は必要ないので無効にしている
- SD_unitychan_humanoid のモデル(プレハブではないことに注意!) を以下のように Capsule の子オブジェクトとして配置し、位置を調整する
- Navmesh Agent コンポーネントの Base Offset, Radius, Height を調整するとよい
- Navmesh Agent は実行すると「少し浮く」ので、モデルの足が少し地面に埋まるくらいがちょうどよい
- 以下のようにモデルの Animator コンポーネントの Controller に SD_UnityChan_Ai(Animator Controller アセット)をアサインする
- 以下のように Capsule オブジェクトの Player Controller Ai コンポーネントの Animator に(シーン上の)SD_UnityChan_humanoid オブジェクトをアサインする
- シーンを実行すると、以下のようにモデルがアニメーションしながら移動する
- キャラクターの「振り返る」動作が遅いので、Navmesh Agent コンポーネントの Angular Speed を大きく(720 くらい)にするとよいでしょう
アニメーションのステートマシンは SD_UnityChan_Ai(Animator Controller アセット)に設定されており、Animator Controller のパラメータは PlayerControllerAi.cs で制御している。NavMeshAgent.velocity で速度ベクトルを取れるのでそれにより移動速度を Speed パラメータにセットし、NavMeshAgent.isOnOffMeshLink で「Off Mesh Link を移動しているかどうか」を取得できるので、Off Mesh Link を移動している時には Jump のパラメータをセットしている。
-
静的ゲームオブジェクト - Unity マニュアル
- オブジェクトの Static 設定について説明されている
-
障害物を動的に追加してルートを更新する
- Navmesh Obstacle コンポーネントを追加することで、「移動するオブジェクトを Navmesh Agent に避けさせる」ことができる
- NavMeshComponents アセットを使うことで、「実行中に動的に Navmesh を Bake することができる」ようになる