I use a SharedComponentData with just an integer to group entities. This works well as long as there aren’t other SCDs in the PREFAB of the entity (it’s the same if I add the sharedcomponent data in the instance, but I put it in the prefab to be even more safe!)
check this image:
in the first case, I have 1 chunk for each entity instance, although the custom shared component data is the same (instances of the same prefab)!
in all the other cases, where a RenderMesh is not present (no other shared components) it works as expected. I have a chunk for each SharedComponentData permutation (hence each prefab) and N instances in it.
In the top case I should have had 1 chunk with 23 entities, like in the cases below where I am using instead 3 separate values of the SCD (hence 3 chunks).
Note: each prefab has different meshes, but instances of the same prefab share the same mesh of course.
Bug or misunderstanding (which means I cannot use the SCD to group entities)?
please let me know what you think about it, as I need to understand if using SCD to group entities is a feasible strategy. Because of this inconsistency, I cannot currently use the most optimal code.
Of course. And all works as expected.
Here fast sample - 2 chunks with 4 entities per chunk, which use same RenderMesh but different MySharedComponentData:
protected override void OnCreate()
{
query = GetEntityQuery(typeof(MyComponentData), typeof(RenderMesh), typeof(MySharedComponentData));
prefab = EntityManager.CreateEntity(typeof(MyComponentData), typeof(RenderMesh), typeof(MySharedComponentData), typeof(Prefab));
var rm = new RenderMesh()
{
mesh = new Mesh(),
material = new Material(Shader.Find("Standard"))
};
var mySCD1 = new MySharedComponentData()
{
Val = new SomeRefType()
};
var mySCD2 = new MySharedComponentData()
{
Val = new SomeRefType()
};
for (int i = 0; i < 8; i++)
{
var e = EntityManager.Instantiate(prefab);
EntityManager.SetComponentData(e, new MyComponentData());
EntityManager.SetSharedComponentData(e, rm);
EntityManager.SetSharedComponentData(e, (i > 3 ? mySCD1: mySCD2));
}
}
or I can split to 4 chunks with 2 entities in chunk (2 RM 2 MySCD)
protected override void OnCreate()
{
query = GetEntityQuery(typeof(MyComponentData), typeof(RenderMesh), typeof(MySharedComponentData));
prefab = EntityManager.CreateEntity(typeof(MyComponentData), typeof(RenderMesh), typeof(MySharedComponentData), typeof(Prefab));
var rm1 = new RenderMesh()
{
mesh = new Mesh(),
material = new Material(Shader.Find("Standard"))
};
var rm2 = new RenderMesh()
{
mesh = new Mesh(),
material = new Material(Shader.Find("Standard"))
};
var mySCD1 = new MySharedComponentData()
{
Val = new SomeRefType()
};
var mySCD2 = new MySharedComponentData()
{
Val = new SomeRefType()
};
for (int i = 0; i < 8; i++)
{
var e = EntityManager.Instantiate(prefab);
EntityManager.SetComponentData(e, new MyComponentData());
EntityManager.SetSharedComponentData(e, (i % 2 == 0 ? rm1: rm2));
EntityManager.SetSharedComponentData(e, (i > 3 ? mySCD1: mySCD2));
}
}
Your case only can be if your SCD (not matter your own or RenderMesh) has different references. For example I just create new RM every time in loop:
As a general rule SharedComponentData should be used for forcing chunking / grouping of entities together.
The use case is not for storing data. In the case of RenderMesh we use it because it’s common to have similar renderers in a scene and pre-batching them together gives big speedups when rendering.
The unfortunate part is that right now SharedComponentData is also the only thing that can store & serialize an object reference. Something we want to fix by introducing class based components that can hold any managed data type.
Hello @Joachim_Ante_1 once I understood the mechanism behind the SCD I naturally started to use them for grouping and nothing else. IT works as long as they are not mixed with RenderMeshes. However according @eizenhorn this is not the case, so I will make a simple project later to debug and in case share here.