Unityで動的にNavMeshを生成する
unityUnity5.6から動的にNavMeshを生成できるようになった。
Unity-Technologies/NavMeshComponentsの Exampleの2_drop_blankのsceneを開く。
分断されたCubeの床と、その上に黄色いCylindarと赤いCubeがあって、 クリックしたところに黄色いCylindarが動くんだが、床がつながっていないのでそのままでは赤いCubeまではたどり着けない。 スペースを押すと目の前に板が出てくるのでこの上を渡って移動することができる。
板の上がNavMeshとして認識されている。
床のCubeと追加される板にはNavMeshSourceTag.csが付いていて、staticな m_Meshes と m_Terrains にそれぞれ追加している。
public static List<MeshFilter> m_Meshes = new List<MeshFilter>();
public static List<Terrain> m_Terrains = new List<Terrain>();
void OnEnable()
{
var m = GetComponent<MeshFilter>();
if (m != null)
{
m_Meshes.Add(m);
}
var t = GetComponent<Terrain>();
if (t != null)
{
m_Terrains.Add(t);
}
}
void OnDisable()
{
var m = GetComponent<MeshFilter>();
if (m != null)
{
m_Meshes.Remove(m);
}
var t = GetComponent<Terrain>();
if (t != null)
{
m_Terrains.Remove(t);
}
}
これらはCollectメソッドでNavMeshBuildSourceのリストを生成するのに使われる。
public static void Collect(ref List<NavMeshBuildSource> sources)
{
sources.Clear();
for (var i = 0; i < m_Meshes.Count; ++i)
{
var mf = m_Meshes[i];
if (mf == null) continue;
var m = mf.sharedMesh;
if (m == null) continue;
var s = new NavMeshBuildSource();
s.shape = NavMeshBuildSourceShape.Mesh;
s.sourceObject = m;
s.transform = mf.transform.localToWorldMatrix;
s.area = 0;
sources.Add(s);
}
for (var i = 0; i < m_Terrains.Count; ++i)
{
...
}
}
これをLocalNavMeshBuilder.csから呼び、NavMeshBuilder.UpdateNavMeshDataに渡してNavMeshDataを更新している。
NavMeshData m_NavMesh;
AsyncOperation m_Operation;
NavMeshDataInstance m_Instance;
List<NavMeshBuildSource> m_Sources = new List<NavMeshBuildSource>();
IEnumerator Start()
{
while (true)
{
UpdateNavMesh(true);
yield return m_Operation;
}
}
void UpdateNavMesh(bool asyncUpdate = false)
{
NavMeshSourceTag.Collect(ref m_Sources);
var defaultBuildSettings = NavMesh.GetSettingsByID(0);
var bounds = QuantizedBounds();
if (asyncUpdate)
m_Operation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
else
NavMeshBuilder.UpdateNavMeshData(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
}