#Change shared component without causing structural change

1 messages · Page 1 of 1 (latest)

livid chasm
#

I have an ArchetypeChunk containing 4096 entities storing 64 bits each, that are grouped spatially by a shared component (int3). As such, each unique shared component has 32 associated chunks.

Let's say I don't want to create another 4096 entities for a different part of the world, but rather re-use those original 4096 entities; Is it possible to change all of their respective chunks' shared component data without causing a structural change?

devout pollen
#

EntityManager.SetSharedComponent(EntityQuery, C)
might save you here

livid chasm
#

You're certain this changes the values per chunk and not per entity?

#

I'll try it once my code is ready for such a change

devout pollen
#

the entityquery overrides can usually handle setting per chunk

#

and looking at source this doesn't seem to be an exception

livid chasm
#

Sweet, thanks

devout pollen
#
            if (useEnabledMask == 0)
            {
                // All entities in the chunk are enabled; set the value en masse
                ChunkDataUtility.SetSharedComponentDataIndex(chunk, chunkArchetype,
                    archetypeChunkFilter.SharedComponentValues, componentType.TypeIndex);
            }```
as long as the query doesn't have a enable in the query
#

it sets the chunks index directly

#
        public static void SetSharedComponentDataIndex(ChunkIndex chunk, Archetype* archetype, in SharedComponentValues sharedComponentValues, TypeIndex typeIndex)
        {
            var entityComponentStore = archetype->EntityComponentStore;
            entityComponentStore->Move(chunk, archetype, sharedComponentValues);

            Assert.AreEqual((ulong)archetype, (ulong)entityComponentStore->GetArchetype(chunk)); // chunk should still be in the same archetype
            var indexInTypeArray = GetIndexInTypeArray(archetype, typeIndex);
            var globalSystemVersion = entityComponentStore->GlobalSystemVersion;
            archetype->Chunks.SetChangeVersion(indexInTypeArray, chunk.ListIndex, globalSystemVersion);
        }```
#

the "Move" does a check to see if old/new archetype is compatible and kind of early outs

            if (ChunkDataUtility.AreLayoutCompatible(srcArchetype, archetypeChunkFilter.Archetype))
            {
                fixed(int* sharedComponentValues = archetypeChunkFilter.SharedComponentValues)
                {
                    ChunkDataUtility.ChangeArchetypeInPlace(srcArchetype, srcChunk, archetypeChunkFilter.Archetype, sharedComponentValues);
                }
                return;
            }```
#

but there is still a bunch of overhead in here

#

you could /maybe/ write a faster version of this and directly just update the shared component yourself
I might work, but it'd require some low level internal access

nova berry
#

We could theoretically expose something like ArchetypeChunk.SetSharedComponentValue<T>(value), as the value is shared by the whole chunk. This operation would affect all entities in the chunk, ignoring any enableable components; that might be confusing, but not inconsistent. Enableable components only affect whether entities match queries; it doesn't prevent their values from being modified by e.g. SetComponentData(). I'll make an internal ticket for the feature request.