Chunk Utilization with two shared component data

This is either a bug or me not understanding how ShaderComponentData works yet, even if I read https://gametorrahod.com/everything-about-isharedcomponentdata/ multiple times.

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:

4485415--413020--upload_2019-4-30_13-40-42.png

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.

Show your code for more info. SCD works as expected, we use it for grouping, without any problems.

Have you tried to use it with a render mesh? I’ll create a basic example and post it later today

Of course. And all works as expected.
Here fast sample - 2 chunks with 4 entities per chunk, which use same RenderMesh but different MySharedComponentData:
4488406--413467--upload_2019-5-1_9-51-17.png

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));
        }
    }

4488406--413473--upload_2019-5-1_9-57-27.png

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:
4488406--413470--upload_2019-5-1_9-54-38.png

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.

4 Likes

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.

When class based components will available?

Huh, I didn’t know that about SharedComponentData. Makes sense.