I’m pretty certain meshes exist in a pure ECS solution.
So to do this, i did create conversion for the existing components but the main thing you need to understate is how to generate navmeshes from mesh data only without the Unity components.
I’d post code but its 7month out of date but let me give you the basics
Quick bit of setup.
private Bounds bounds;
private NavMeshData navMeshData;
private NavMeshDataInstance navMeshDataInstance;
protected override void OnCreate()
{
this.navMeshData = new NavMeshData();
this.navMeshDataInstance = NavMesh.AddNavMeshData(this.navMeshData);
this.bounds = new Bounds(Vector3.zero, new Vector3(8192, 256, 8192)); // whatever you want. for performance you can create multiple nav meshes and only update parts etc but to start just do it in one.
}
protected override void OnUpdate()
{
this.UpdateMeshLink();
this.UpdateNavMesh();
}
For links I won’t go into much detail. Once you get what’s going on these will make more sense anyway, but you can add nav mesh links with
https://docs.unity3d.com/ScriptReference/AI.NavMesh.AddLink.html
while (this.newLinks.TryDequeue(out var l))
{
NavMeshLinkInstance linkHandle = NavMesh.AddLink(l.NavMeshLinkData, l.Translation, l.Rotation);
var result = this.linkHandles.TryAdd(l.Entity, linkHandle);
Assert.IsTrue(result);
}
And you can remove nav mesh link with
https://docs.unity3d.com/ScriptReference/AI.NavMesh.RemoveLink.html
while (this.removeLinks.TryDequeue(out var entity))
{
var result = this.linkHandles.TryGetValue(entity, out var linkHandle);
Assert.IsTrue(result);
this.linkHandles.Remove(entity);
NavMesh.RemoveLink(linkHandle);
}
These queues are populated in a job from a link IComponentData I created.
To build your actual NavMesh you need to use
https://docs.unity3d.com/ScriptReference/AI.NavMeshBuilder.UpdateNavMeshDataAsync.html
This takes
AI.NavMeshData data
AI.NavMeshBuildSettings buildSettings
List sources
Bounds localBounds
You can get your settings from the scene using
var buildSettings = NavMesh.GetSettingsByID(0);
or customize it yourself.
With that you have the data, buildSettings and localBounds fields. So you need to generate your sources, which is the most important part.
https://docs.unity3d.com/ScriptReference/AI.NavMeshBuildSource.html
You can either use primitive shapes (easy) or meshes which takes a little more work.
This was done in a burst job so as meshes can’t be used I grabbed the meshIndex and stored that in a temp stash.
/// <inheritdoc />
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var meshInstanceIndex = chunk.GetSharedComponentIndex(this.MeshInstanceRendererType);
var localToWorlds = chunk.GetNativeArray(this.LocalToWorldType);
var updateNavMeshEvents = chunk.GetNativeArray(this.UpdateNavMeshEventType);
for (var index = 0; index < chunk.Count; index++)
{
var transform = localToWorlds[index].Value;
var navMeshSource = updateNavMeshEvents[index];
if (navMeshSource.Shape == NavMeshBuildSourceShape.Mesh)
{
if (meshInstanceIndex != -1)
{
this.Meshes.Enqueue(
new MeshStash
{
Area = navMeshSource.Area,
Transform = transform,
MeshIndex = meshInstanceIndex,
});
}
}
else
{
this.Source.Enqueue(new NavMeshBuildSource
{
shape = navMeshSource.Shape,
area = navMeshSource.Area,
transform = transform,
size = navMeshSource.Size,
});
}
}
}
The stash was just
private struct MeshStash
{
public Matrix4x4 Transform;
public int Area;
public int MeshIndex;
}
Then back on the main thread, I would take this and get the RenderMesh from the index and build my list of sources.
while (this.meshes.TryDequeue(out var mesh))
{
var renderMesh = this.EntityManager.GetSharedComponentData<RenderMesh>(mesh.MeshIndex);
if (renderMesh.mesh == null)
{
continue;
}
this.sources.Add(new NavMeshBuildSource
{
shape = NavMeshBuildSourceShape.Mesh,
sourceObject = renderMesh.mesh,
transform = mesh.Transform,
area = mesh.Area,
});
}
Once that is done, it’s as simple as calling update
var buildSettings = NavMesh.GetSettingsByID(0);
this.operation = NavMeshBuilder.UpdateNavMeshDataAsync(
this.navMeshData,
buildSettings,
this.sources,
this.bounds);