I know there’s a couple of threads on this issue, I’ve searched through them, but I just don’t seem to find a clear answer.
I need to spawn 1000s of particles every frame which live for a short time. The particles use RenderMesh for drawing, but the problem is that since RenderMesh is an ISharedComponentData that has references to managed objects (Mesh and Material), you can’t set them in a burst compiled job. I can add all other components blazingly fast through a burst compiled ForEach job and concurrent EntityCommandBuffer. But, I need to have a separate system that only adds RenderMeshes, and it’s a ComponentSystem that is incredibly slow.
I can probably think of doing some kind of pooling instead (actually off the top of my head since pooling will require looping through N entities I also fear it could be a bottleneck), or reinventing the Hybrid Renderer, which I don’t want to do since Hybrid Renderer is already there…
So, is there some way to efficiently set RenderMeshes I’m not aware of, or perhaps an unsafe way?
You could probably use the batch api’s to set the data on all entities matching an EntityQuery at once. Not sure if I’m doing this right (I’m using other peoples questions as a way of exploring/learning ECS myself as I’m not currently working on a project with it myself.
For example:
public class BatchSpawn : SystemBase {
private struct SpawnComponent : IComponentData {
}
EntityArchetype spawnedArchetype;
EntityQuery initializeQuery;
// Start is called before the first frame update
protected override void OnCreate() {
spawnedArchetype = EntityManager.CreateArchetype(typeof(RenderMesh), typeof(SpawnComponent));
initializeQuery = EntityManager.CreateEntityQuery(typeof(RenderMesh), typeof(SpawnComponent));
}
protected override void OnUpdate() {
if (!Input.GetKeyDown(KeyCode.Space)) {
return;
}
var entities = new NativeArray<Entity>(1000, Allocator.TempJob);
EntityManager.CreateEntity(spawnedArchetype, entities);
EntityManager.SetSharedComponentData(initializeQuery, new RenderMesh() {
mesh = ...
material = ...
});
EntityManager.RemoveComponent<SpawnComponent>(initializeQuery);
entities.Dispose();
}
}
My solution was to create an prefab entity, and use instantiate method to spawn the actual entities. So no need for extra SetSharedComponentData(which is also how unity did it in various demos)