I am trying to update the mesh on a large number of entities at runtime, based on data in the entity’s other components (for some dynamic terrain). However, no matter what I try, I cannot seem to get the EntitiesGraphicsSystem to actually render the meshes, resulting in a completely empty scene.
Distilled down, my mesh building code looks like this:
private void UpdateDirtyMeshes()
{
using var dirtyEntities = tileWithDirtyGroundQuery.ToEntityArray(Allocator.Temp);
if (dirtyEntities.Length == 0)
{
// skip updating if nothing needs it
return;
}
// make some mesh data arrays for the job to build the meshes
var meshDataArrays = new UnsafeList<Mesh.MeshDataArray>(dirtyEntities.Length, Allocator.TempJob);
for (var i = 0; i < dirtyEntities.Length; i++)
{
meshDataArrays.AddNoResize(Mesh.AllocateWritableMeshData(1));
}
// pass the data arrays to the job to populate
var meshBuildJob = new MeshBuildJob
{
// other stuff...
MeshDataArrays = meshDataArrays
};
var meshBuildJobHandle = meshBuildJob.Schedule(dirtyEntities.Length, 1, Dependency);
meshBuildJobHandle.Complete();
for (var i = 0; i < dirtyEntities.Length; i++)
{
// get the "ground" entity which holds the mesh
var ground = EntityManager.GetComponentData<MapTileGroundEntity>(dirtyEntities[i]).Value;
var mmi = EntityManager.GetComponentData<MaterialMeshInfo>(ground);
// in this case, I'm dropping the old mesh and making a new one
// I have also tried to simply update the existing mesh, but that doesn't work either
if (mmi.Mesh > 0)
{
// unregister the old mesh
entitiesGraphicsSystem.UnregisterMesh(new BatchMeshID { value = (uint)mmi.Mesh });
}
// build and register a new mesh
var mesh = new Mesh() { name = "GroundMesh_" + ground.Index };
Mesh.ApplyAndDisposeWritableMeshData(meshDataArrays[i], mesh);
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.RecalculateTangents();
// for debugging, update a component that shows us the mesh in the inspector
EntityManager.SetComponentData(ground, new MapTileGroundMesh { Value = mesh });
// update the bounds on the component
var bounds = mesh.bounds;
EntityManager.SetComponentData(entity, new RenderBounds { Value = new() { Center = bounds.center, Extents = bounds.extents } });
// register the new mesh with the EGS and update the mesh ID
var meshId = entitiesGraphicsSystem.RegisterMesh(mesh);
EntityManager.SetComponentData(ground, new MaterialMeshInfo { Mesh = (int)meshId.value, Material = mmi.Material, Submesh = mmi.Submesh });
}
// additional work on other parts of the entity, cleanup/disposing things, etc.
// ...
}
For reference, this entity is built as a prototype and cloned earlier by EntityManager.Instantiate then adding a Parent component to it once built.
The prototype is built like so:
EntityManager entityManager = // ...
Material material = // This is currently using the standard URP "Lit" material
entityManager.AddComponentData(entity, new LocalTransform { Scale = 1 });
entityManager.AddComponent<WorldTransform>(entity);
entityManager.AddComponent<LocalToWorld>(entity);
RenderMeshUtility.AddComponents
entityManager,
entity,
new RenderMeshDescription(ShadowCastingMode.ShadowsOnly),
new RenderMeshArray(new Material[] { material }, new Mesh[0]),
new MaterialMeshInfo { Mesh = 0, Material = -1 });
// plus my custom components, too
From my understanding by reading through the scripts, MaterialMeshInfo’s Mesh/Material properties can be positive for a batched mesh’s ID, or negative to index the shared RenderMeshArray. Since they all share a material, it can be in the RenderMeshArray, but I’ll be updating the mesh at runtime and each will have a different mesh (plus don’t want structural changes for doing so), so that’s just going to be zero for now.
After this method executes, I can see all my tiles in the hierarchy window correctly:


(The appropriate WorldRenderBounds is also correct, per the tile’s transform)
I can also inspect the resulting mesh to find it looks correct when viewed in the inspector’s little viewport. So, all that appears to have worked:

(It’s a very simple mesh for now, but will get more complicated once this is working)
Yet, despite that, nothing is rendered in the scene: it is in fact completely empty. I’ve been at this for quite some time and just cannot figure out what the missing piece is; what am I doing wrong?
Unity Info
Unity Editor 2022.2.7f1
Universal Rendering Pipeline 14.0.6
Unity.Entities 1.0.0-pre.47
Unity.Entities.Rendering 1.0.0-pre.44