Unity で利用できる NavMesh では、異なるパラメータを持つ Agent を作成できます。Inspector で AgentType が選択できるときは、分かりやすい名前で表示されるのですが、スクリプト内では AgentType は名前では指定できず、その代わりに AgentTypeID を利用する必要があります。この AgentTypeID が少しトリッキーで躓いたので、その腹いせに記事を書きます。
問題点
ことは NavMesh の公式拡張である NavMeshComponents のサンプルを触っていたときに起こりました。
Examples/Scenes/5_sliding_window_terrain
というシーンは、 NavMeshBuilder
クラスを使うことで Agent の周囲にランタイムに動的に NavMesh を作成できる例を示していたのですが、 AgentType が Humanoid
の Agent しか存在しなかったので、ここに新しい AgentType を追加したらどうなるんだろうという気持ちになり、試してみることにしました。
AgentTypes は見た目的にすごく Enum 然としています。実際デフォルトで設定されている Humanoid
という AgentType に対応する ID は 0
でした。
// 60行目
var defaultBuildSettings = NavMesh.GetSettingsByID(0);
なので、Humanoid
の下にある Ogre
に対応する ID は一つインクリメントされて 1
になるものだと思いますよね。そこで、上述のスクリプトの ID を 1
に書き換えて、シーン内の Agent を Orge に設定したのですが、 Failed to create agent because it is not close enough to the NavMesh
という警告が出て正常に動作しませんでした。
調べてみた結果、どうやら Ogre
に対応する NavMesh が正しく作成されていないことが分かり、 Ogre
に対応する AgentTypeID が 1
じゃないのかも、と気づきました。
対応する AgentTypeID の取得方法
色々試してみたのですが、最終的に以下の方法で AgentType に対応する ID が分かります。辞書型に保存することで、AgentType の名前からいつでも ID が取得できるようにしました。
(回りくどい書き方になっているのはちょうどいい API がなかったからです)
Dictionary<string, int> agentTypeIdDict = new private Dictionary<string, int>();
for (var i = 0; i < NavMesh.GetSettingsCount(); i++)
{
var id = NavMesh.GetSettingsByIndex(i).agentTypeID;
var name = NavMesh.GetSettingsNameFromID(id);
agentTypeIdDict.Add(name, id);
}
ここで取得できた ID を指定したところ、警告が消え、 Ogre
Agent も正しく動作しました。
最後に
結果的に自分の環境では、 Ogre
に対応する ID は -1372625422
でした!全然予想と違いましたね!!!!!