Esempio n. 1
0
        internal EntityManager(World world)
        {
            TypeManager.Initialize();

            m_World = world;

            m_ComponentJobSafetyManager =
                (ComponentJobSafetyManager *)UnsafeUtility.Malloc(sizeof(ComponentJobSafetyManager), 64,
                                                                  Allocator.Persistent);
            m_ComponentJobSafetyManager->OnCreate();

            m_EntityComponentStore  = Entities.EntityComponentStore.Create(world.SequenceNumber << 32);
            m_ManagedComponentStore = new ManagedComponentStore();
            m_EntityGroupManager    = new EntityGroupManager(m_ComponentJobSafetyManager);

            m_ExclusiveEntityTransaction = new ExclusiveEntityTransaction(EntityGroupManager,
                                                                          m_ManagedComponentStore, EntityComponentStore);

            m_UniversalQuery = CreateEntityQuery(
                new EntityQueryDesc
            {
                Options = EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabled
            }
                );
        }
Esempio n. 2
0
        public static void SetChunkCount(Chunk *chunk, int newCount,
                                         EntityComponentStore *entityComponentStore,
                                         ManagedComponentStore managedComponentStore)
        {
            Assert.AreNotEqual(newCount, chunk->Count);
            Assert.IsFalse(chunk->Locked);
            Assert.IsTrue(!chunk->LockedEntityOrder || newCount == 0);

            // Chunk released to empty chunk pool
            if (newCount == 0)
            {
                ReleaseChunk(chunk, entityComponentStore, managedComponentStore);
                return;
            }

            var capacity = chunk->Capacity;

            // Chunk is now full
            if (newCount == capacity)
            {
                // this chunk no longer has empty slots, so it shouldn't be in the empty slot list.
                chunk->Archetype->EmptySlotTrackingRemoveChunk(chunk);
            }
            // Chunk is no longer full
            else if (chunk->Count == capacity)
            {
                Assert.IsTrue(newCount < chunk->Count);
                chunk->Archetype->EmptySlotTrackingAddChunk(chunk);
            }

            chunk->Count = newCount;
            chunk->Archetype->Chunks.SetChunkEntityCount(chunk->ListIndex, newCount);
        }
        public unsafe NativeArray <int> MoveAllSharedComponents(ManagedComponentStore srcManagedComponents,
                                                                Allocator allocator)
        {
            var remap = new NativeArray <int>(srcManagedComponents.GetSharedComponentCount(), allocator);

            remap[0] = 0;

            for (int srcIndex = 1; srcIndex < remap.Length; ++srcIndex)
            {
                var srcData = srcManagedComponents.m_SharedComponentData[srcIndex];
                if (srcData == null)
                {
                    continue;
                }

                var typeIndex = srcManagedComponents.m_SharedComponentType[srcIndex];

                var hashCode = TypeManager.GetHashCode(srcData, typeIndex);
                var dstIndex = InsertSharedComponentAssumeNonDefaultMove(typeIndex, hashCode, srcData);

                m_SharedComponentRefCount[dstIndex] += srcManagedComponents.m_SharedComponentRefCount[srcIndex] - 1;

                remap[srcIndex] = dstIndex;
            }

            srcManagedComponents.m_HashLookup.Clear();
            srcManagedComponents.m_SharedComponentVersion.ResizeUninitialized(1);
            srcManagedComponents.m_SharedComponentRefCount.ResizeUninitialized(1);
            srcManagedComponents.m_SharedComponentType.ResizeUninitialized(1);
            srcManagedComponents.m_SharedComponentData.Clear();
            srcManagedComponents.m_SharedComponentData.Add(null);
            srcManagedComponents.m_FreeListIndex = -1;

            return(remap);
        }
        public NativeArray <int> MoveAllSharedComponents(ManagedComponentStore srcManagedComponents, Allocator allocator)
        {
            var remap = new NativeArray <int>(srcManagedComponents.GetSharedComponentCount(), allocator);

            remap[0] = 0;

            var srcInfos = srcManagedComponents.SharedComponentInfoPtr;

            for (int srcIndex = 1; srcIndex < remap.Length; ++srcIndex)
            {
                var srcData = srcManagedComponents.m_SharedComponentData[srcIndex];
                if (srcData == null)
                {
                    continue;
                }

                var typeIndex = srcInfos[srcIndex].ComponentType;
                var hashCode  = srcInfos[srcIndex].HashCode;
                var dstIndex  = InsertSharedComponentAssumeNonDefaultMove(typeIndex, hashCode, srcData);

                SharedComponentInfoPtr[dstIndex].RefCount += srcInfos[srcIndex].RefCount - 1;

                remap[srcIndex] = dstIndex;
            }

            srcManagedComponents.ResetSharedComponentData();

            return(remap);
        }
        /// <summary>
        /// Adds a component to each of the chunks identified by a EntityQuery and set the component values.
        /// </summary>
        /// <remarks>
        /// This function finds all chunks whose archetype satisfies the EntityQuery and adds the specified
        /// component to them.
        ///
        /// A chunk component is common to all entities in a chunk. You can access a chunk <see cref="IComponentData"/>
        /// instance through either the chunk itself or through an entity stored in that chunk.
        ///
        /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
        /// currently running Jobs to complete before adding the component and no additional Jobs can start before
        /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not
        /// be able to make use of the processing power of all available cores.
        /// </remarks>
        /// <param name="entityQuery">The EntityQuery identifying the chunks to modify.</param>
        /// <param name="componentData">The data to set.</param>
        /// <typeparam name="T">The type of component, which must implement IComponentData.</typeparam>
        public void AddChunkComponentData <T>(EntityQuery entityQuery, T componentData) where T : struct, IComponentData
        {
            using (var chunks = entityQuery.CreateArchetypeChunkArray(Allocator.TempJob))
            {
                if (chunks.Length == 0)
                {
                    return;
                }
                BeforeStructuralChange();
                var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

                EntityComponentStore->AssertCanAddChunkComponent(chunks, ComponentType.ChunkComponent <T>());

                var type      = ComponentType.ReadWrite <T>();
                var chunkType = ComponentType.FromTypeIndex(TypeManager.MakeChunkComponentTypeIndex(type.TypeIndex));

                using (var entityBatchList = EntityComponentStore->CreateEntityBatchList(chunks))
                {
                    EntityComponentStore->AddComponentFromMainThread(entityBatchList, chunkType, 0);
                    EntityComponentStore->SetChunkComponent <T>(entityBatchList, componentData);
                }

                var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
                EntityQueryManager.AddAdditionalArchetypes(changedArchetypes);
                ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            }
        }
        internal void AddComponent(UnsafeMatchingArchetypePtrList archetypeList, EntityQueryFilter filter, ComponentType componentType)
        {
            var jobHandle = new JobHandle();

            //@TODO: Missing EntityQuery.SyncFilter
            using (var chunks = ComponentChunkIterator.CreateArchetypeChunkArray(archetypeList, Allocator.TempJob, out jobHandle, ref filter))
            {
                jobHandle.Complete();
                if (chunks.Length == 0)
                {
                    return;
                }

                BeforeStructuralChange();
                var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking();

                EntityComponentStore->AssertCanAddComponent(chunks, componentType);

                using (var entityBatchList = m_EntityComponentStore->CreateEntityBatchList(chunks))
                {
                    EntityComponentStore->AddComponentFromMainThread(entityBatchList, componentType, 0);
                }

                var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges);
                EntityQueryManager.AddAdditionalArchetypes(changedArchetypes);
                ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            }
        }
Esempio n. 7
0
        public static void CreateChunks(Archetype *archetype, ArchetypeChunk *chunks, int entityCount,
                                        EntityComponentStore *entityComponentStore,
                                        ManagedComponentStore managedComponentStore)
        {
            int *sharedComponentValues = stackalloc int[archetype->NumSharedComponents];

            UnsafeUtility.MemClear(sharedComponentValues, archetype->NumSharedComponents * sizeof(int));

            Chunk *lastChunk  = null;
            int    chunkIndex = 0;

            while (entityCount != 0)
            {
                var chunk = GetCleanChunk(archetype, sharedComponentValues,
                                          entityComponentStore, managedComponentStore);
                int allocatedIndex;

                var allocatedCount = AllocateIntoChunk(chunk, entityCount, out allocatedIndex,
                                                       entityComponentStore, managedComponentStore);

                entityComponentStore->AllocateEntities(archetype, chunk, allocatedIndex, allocatedCount, null);
                ChunkDataUtility.InitializeComponents(chunk, allocatedIndex, allocatedCount);
                chunk->SetAllChangeVersions(entityComponentStore->GlobalSystemVersion);
                chunks[chunkIndex] = new ArchetypeChunk(chunk, entityComponentStore);
                lastChunk          = chunk;

                entityCount -= allocatedCount;
                chunkIndex++;
            }

            entityComponentStore->IncrementComponentTypeOrderVersion(archetype);
        }
 /// <summary>
 /// Creates a set of entities of the specified archetype.
 /// </summary>
 /// <remarks>Fills the [NativeArray](https://docs.unity3d.com/ScriptReference/Unity.Collections.NativeArray_1.html)
 /// object assigned to the `entities` parameter with the Entity objects of the created entities. Each entity
 /// has the components specified by the <see cref="EntityArchetype"/> object assigned
 /// to the `archetype` parameter. The EntityManager adds these entities to the <see cref="World"/> entity list. Use the
 /// Entity objects in the array for further processing, such as setting the component values.</remarks>
 /// <param name="archetype">The archetype defining the structure for the new entities.</param>
 /// <param name="entities">An array to hold the Entity objects needed to access the new entities.
 /// The length of the array determines how many entities are created.</param>
 public void CreateEntity(EntityArchetype archetype, NativeArray <Entity> entities)
 {
     BeforeStructuralChange();
     EntityComponentStore->CreateEntities(archetype.Archetype, (Entity *)entities.GetUnsafePtr(),
                                          entities.Length);
     ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
 }
 internal void InstantiateInternal(Entity srcEntity, Entity *outputEntities, int count)
 {
     BeforeStructuralChange();
     EntityComponentStore->AssertEntitiesExist(&srcEntity, 1);
     EntityComponentStore->InstantiateEntities(srcEntity, outputEntities, count);
     ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
 }
        // ----------------------------------------------------------------------------------------------------------
        // INTERNAL
        // ----------------------------------------------------------------------------------------------------------

        internal void DestroyEntityInternal(Entity *entities, int count)
        {
            BeforeStructuralChange();
            EntityComponentStore->AssertCanDestroy(entities, count);
            EntityComponentStore->DestroyEntities(entities, count);
            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
        }
Esempio n. 11
0
        public static void CreateEntities(Archetype *archetype, Entity *entities, int count,
                                          EntityComponentStore *entityComponentStore,
                                          ManagedComponentStore managedComponentStore)
        {
            var sharedComponentValues = stackalloc int[archetype->NumSharedComponents];

            UnsafeUtility.MemClear(sharedComponentValues, archetype->NumSharedComponents * sizeof(int));

            while (count != 0)
            {
                var chunk = GetChunkWithEmptySlots(archetype, sharedComponentValues,
                                                   entityComponentStore, managedComponentStore);

                int allocatedIndex;
                var allocatedCount = AllocateIntoChunk(chunk, count, out allocatedIndex,
                                                       entityComponentStore, managedComponentStore);
                entityComponentStore->AllocateEntities(archetype, chunk, allocatedIndex, allocatedCount, entities);
                ChunkDataUtility.InitializeComponents(chunk, allocatedIndex, allocatedCount);
                chunk->SetAllChangeVersions(entityComponentStore->GlobalSystemVersion);
                entities += allocatedCount;
                count    -= allocatedCount;
            }

            entityComponentStore->IncrementComponentTypeOrderVersion(archetype);
        }
        internal object GetManagedObject(ManagedComponentStore managedComponentStore, int typeIndexInQuery, int entityInChunkIndex)
        {
            var indexInArchetype      = CurrentMatchingArchetype->IndexInArchetype[typeIndexInQuery];
            var managedComponentArray = (int *)ChunkDataUtility.GetComponentDataRW(CurrentChunk, 0, indexInArchetype, CurrentArchetype->EntityComponentStore->GlobalSystemVersion);

            return(managedComponentStore.GetManagedComponent(managedComponentArray[entityInChunkIndex]));
        }
        public static void CopyManagedObjects(
            ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcStartIndex,
            ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstStartIndex, int count)
        {
            var srcI = 0;
            var dstI = 0;

            while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount)
            {
                if (srcArch->Types[srcI] < dstArch->Types[dstI])
                {
                    ++srcI;
                }
                else if (srcArch->Types[srcI] > dstArch->Types[dstI])
                {
                    ++dstI;
                }
                else
                {
                    if (srcArch->ManagedArrayOffset[srcI] >= 0)
                    {
                        for (var i = 0; i < count; ++i)
                        {
                            var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i);
                            dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, obj);
                        }
                    }

                    ++srcI;
                    ++dstI;
                }
            }
        }
        internal object GetSharedComponentData(Entity entity, int typeIndex)
        {
            EntityComponentStore->AssertEntityHasComponent(entity, typeIndex);

            var sharedComponentIndex = EntityComponentStore->GetSharedComponentDataIndex(entity, typeIndex);

            return(ManagedComponentStore.GetSharedComponentDataBoxed(sharedComponentIndex, typeIndex));
        }
        public T GetComponentObject <T>(Entity entity, ComponentType componentType)
        {
            EntityComponentStore->AssertEntityHasComponent(entity, componentType.TypeIndex);

            var entityInChunk = EntityComponentStore->GetEntityInChunk(entity);

            return((T)ManagedComponentStore.GetManagedObject(entityInChunk.Chunk, componentType, entityInChunk.IndexInChunk));
        }
Esempio n. 16
0
        public void CreateChunk(EntityArchetype archetype, NativeArray <ArchetypeChunk> chunks, int entityCount)
        {
            Unity.Entities.EntityComponentStore.AssertValidArchetype(EntityComponentStore, archetype);
            BeforeStructuralChange();

            EntityComponentStore->CreateChunks(archetype.Archetype, (ArchetypeChunk *)chunks.GetUnsafePtr(), chunks.Length, entityCount);
            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
        }
Esempio n. 17
0
        public void CreateChunk(EntityArchetype archetype, NativeArray <ArchetypeChunk> chunks, int entityCount)
        {
            BeforeStructuralChange();

            EntityComponentStore->CreateChunks(archetype.Archetype, (ArchetypeChunk *)chunks.GetUnsafePtr(),
                                               entityCount);
            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
        }
Esempio n. 18
0
 public static void DestroyMetaChunkEntity(Entity entity,
                                           EntityComponentStore *entityComponentStore,
                                           ManagedComponentStore managedComponentStore)
 {
     EntityManagerChangeArchetypeUtility.RemoveComponent(entity, ComponentType.ReadWrite <ChunkHeader>(),
                                                         entityComponentStore, managedComponentStore);
     DestroyEntities(&entity, 1, entityComponentStore, managedComponentStore);
 }
        internal object GetManagedComponentDataAsObject(Entity entity, ComponentType componentType)
        {
            EntityComponentStore->AssertEntityHasComponent(entity, componentType.TypeIndex);

            var entityInChunk = EntityComponentStore->GetEntityInChunk(entity);

            return(ManagedComponentStore.GetManagedObject(entityInChunk.Chunk, componentType, entityInChunk.IndexInChunk));
        }
Esempio n. 20
0
 internal EntityQuery(EntityQueryData *queryData, ComponentJobSafetyManager *safetyManager, EntityComponentStore *entityComponentStore, ManagedComponentStore managedComponentStore)
 {
     m_QueryData             = queryData;
     m_Filter                = default(EntityQueryFilter);
     m_SafetyManager         = safetyManager;
     m_EntityComponentStore  = entityComponentStore;
     m_ManagedComponentStore = managedComponentStore;
 }
        // ----------------------------------------------------------------------------------------------------------
        // PUBLIC
        // ----------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Creates an entity having the specified archetype.
        /// </summary>
        /// <remarks>
        /// The EntityManager creates the entity in the first available chunk with the matching archetype that has
        /// enough space.
        ///
        /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
        /// currently running Jobs to complete before creating the entity and no additional Jobs can start before
        /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not
        /// be able to make use of the processing power of all available cores.
        /// </remarks>
        /// <param name="archetype">The archetype for the new entity.</param>
        /// <returns>The Entity object that you can use to access the entity.</returns>
        public Entity CreateEntity(EntityArchetype archetype)
        {
            Entity entity;

            BeforeStructuralChange();
            EntityComponentStore->CreateEntities(archetype.Archetype, &entity, 1);
            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            return(entity);
        }
Esempio n. 22
0
        public Entity CreateEntity()
        {
            BeforeStructuralChange();
            Entity entity;

            EntityComponentStore->CreateEntities(m_EntityDataAccess.GetEntityOnlyArchetype().Archetype, &entity, 1);
            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
            return(entity);
        }
Esempio n. 23
0
        internal void DestroyChunkForDiffing(Chunk *chunk)
        {
            chunk->Archetype->EntityCount -= chunk->Count;
            EntityComponentStore->FreeEntities(chunk);

            EntityComponentStore->SetChunkCountKeepMetaChunk(chunk, 0);

            ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker);
        }
        static void ConstructChunk(Archetype *archetype, Chunk *chunk,
                                   SharedComponentValues sharedComponentValues,
                                   EntityComponentStore *entityComponentStore,
                                   ManagedComponentStore managedComponentStore,
                                   EntityGroupManager entityGroupManager)
        {
            chunk->Archetype       = archetype;
            chunk->Count           = 0;
            chunk->Capacity        = archetype->ChunkCapacity;
            chunk->SequenceNumber  = entityComponentStore->AssignSequenceNumber(chunk);
            chunk->metaChunkEntity = Entity.Null;

            var numSharedComponents = archetype->NumSharedComponents;

            if (numSharedComponents > 0)
            {
                for (var i = 0; i < archetype->NumSharedComponents; ++i)
                {
                    var sharedComponentIndex = sharedComponentValues[i];
                    managedComponentStore.AddReference(sharedComponentIndex);
                }
            }

            archetype->AddToChunkList(chunk, sharedComponentValues, entityComponentStore->GlobalSystemVersion);

            Assert.IsTrue(archetype->Chunks.Count != 0);

            // Chunk can't be locked at at construction time
            archetype->EmptySlotTrackingAddChunk(chunk);

            if (numSharedComponents == 0)
            {
                Assert.IsTrue(archetype->ChunksWithEmptySlots.Count != 0);
            }
            else
            {
                Assert.IsTrue(archetype->FreeChunksBySharedComponents.TryGet(chunk->SharedComponentValues,
                                                                             archetype->NumSharedComponents) != null);
            }

            if (archetype->NumManagedArrays > 0)
            {
                chunk->ManagedArrayIndex =
                    managedComponentStore.AllocateManagedArrayStorage(archetype->NumManagedArrays * chunk->Capacity);
            }
            else
            {
                chunk->ManagedArrayIndex = -1;
            }

            chunk->Flags = 0;

            if (archetype->MetaChunkArchetype != null)
            {
                CreateMetaEntityForChunk(chunk, entityComponentStore, managedComponentStore, entityGroupManager);
            }
        }
        private static PackedSharedComponentDataChange[] GetChangedSharedComponents(
            PackedCollection <EntityGuid> packedEntityCollection,
            PackedCollection <ComponentTypeHash> packedStableTypeHashCollection,
            NativeList <DeferredPackedSharedComponentDataChange> changes,
            ManagedComponentStore beforeManagedComponentStore,
            ManagedComponentStore afterManagedComponentStore)
        {
            if (changes.Length == 0)
            {
                return(s_EmptySetSharedComponentDiff);
            }

            var result = new List <PackedSharedComponentDataChange>();

            for (var i = 0; i < changes.Length; i++)
            {
                var change = changes[i];

                object afterValue = null;

                if (change.AfterSharedComponentIndex != 0)
                {
                    afterValue = afterManagedComponentStore.GetSharedComponentDataBoxed(change.AfterSharedComponentIndex, change.TypeIndex);
                }

                if (change.BeforeSharedComponentIndex > -1 && change.AfterSharedComponentIndex != 0)
                {
                    var beforeValue = beforeManagedComponentStore.GetSharedComponentDataBoxed(change.BeforeSharedComponentIndex, change.TypeIndex);

                    if (TypeManager.Equals(beforeValue, afterValue, change.TypeIndex))
                    {
                        continue;
                    }
                }

                var packedEntityIndex = packedEntityCollection.GetOrAdd(change.EntityGuid);
                var packedTypeIndex   = packedStableTypeHashCollection.GetOrAdd(new ComponentTypeHash
                {
                    StableTypeHash = TypeManager.GetTypeInfo(change.TypeIndex).StableTypeHash
                });

                var packedComponent = new PackedComponent
                {
                    PackedEntityIndex = packedEntityIndex,
                    PackedTypeIndex   = packedTypeIndex
                };

                result.Add(new PackedSharedComponentDataChange
                {
                    Component        = packedComponent,
                    BoxedSharedValue = afterValue
                });
            }

            return(result.ToArray());
        }
Esempio n. 26
0
        /// <summary>
        /// This method will handle the cloning of Hybrid Components (if any) during the batched instantiation of an Entity
        /// </summary>
        /// <param name="obj">The Hybrid Component. We don't know for sure it's a component to clone or to reference, this method is also about detecting this use case and the return value will give us the info</param>
        /// <param name="srcStore">Source Managed Store of the entity to instantiate</param>
        /// <param name="dstArch">Destination archetype of the entity to instantiate</param>
        /// <param name="dstStore">Destination Managed Store that will own the instances we create</param>
        /// <param name="dstManagedArrayIndex">Index of the Hybrid Component associated with <paramref name="obj"/></param>
        /// <param name="dstChunkCapacity">Chunk capacity</param>
        /// <param name="srcEntity">Entity to instantiate</param>
        /// <param name="dstEntities">Array containing all the entities instantiated</param>
        /// <param name="dstTypeIndex">Destination type index</param>
        /// <param name="dstBaseIndex">Destination base index</param>
        /// <param name="gameObjectInstances">An array that will contain all the cloned Game Object companion. This method will fill this array at the first call for a Hybrid Component to clone and will be used for subsequent ones</param>
        /// <returns><c>true</c> if the <paramref name="obj"/> was meant to be cloned, <c>false</c> if it is meant to be referenced</returns>
        static bool InstantiateHybridComponentDelegate(object obj, ManagedComponentStore srcStore,
                                                       Archetype *dstArch, ManagedComponentStore dstStore, int dstManagedArrayIndex, int dstChunkCapacity,
                                                       Entity srcEntity, NativeArray <Entity> dstEntities, int dstTypeIndex, int dstBaseIndex, ref object[] gameObjectInstances)
        {
            // For now, it only makes sense to support a conversion that happens in the same world
            // If whenever that changes, this assert will warn us it's not supported
            Assert.AreEqual(srcStore, dstStore, "Companion GameObject instancing assumes the src and dst EntityManager are the same, are you instancing across worlds?");

            // This method is only about cloning Hybrid Components: if it's not a component we have nothing to do
            var unityComponent = obj as UnityEngine.Component;

            if (unityComponent == null)
            {
                return(false);
            }

            // This method is only about cloning Hybrid Components: if there's no Companion Link it means there's nothing to clone
            // This can still be a valid use case, the entity might be storing references to external Hybrid Components (e.g. first stage of conversion)
            var companionLink = unityComponent.gameObject.GetComponent <CompanionLink>();

            if (companionLink == null)
            {
                return(false);
            }

            // The instantiation works in two phases:
            //  1) The first call on this method will clone the GameObject that owns the Hybrid Components for each instance we have to create and make it a Companion Game Object by attaching a CompanionLink component to it
            //  2) The first and all other calls will add the Hybrid Managed Component we cloned to the entity

            // 1) We know it's the first call if the array is null, it means we have to clone the GameObject for dstEntities.Length times and make it a Companion Game Object by adding a CompanionLink to it
            //    Cloning the Game Object will also clone its components, which is exactly what we're looking for.
            //    Note that we are relaxed with the content of the Game Object we clone: it may contains more than we need regarding the association with the Entity, but that's what we want,
            //      if the user adds Components to the Game Object that are not used by the entity: so be it, the user will still have these components in the instantiated Game Objects
            if (gameObjectInstances == null)
            {
                gameObjectInstances = new object[dstEntities.Length];

                for (int i = 0; i < dstEntities.Length; ++i)
                {
                    var instance = GameObject.Instantiate(unityComponent.gameObject);
                    instance.name = CompanionLink.GenerateCompanionName(dstEntities[i]);

                    gameObjectInstances[i] = instance;
                    instance.hideFlags    |= HideFlags.HideInHierarchy;
                }
            }

            // For each instance we create, we add the cloned Hybrid Component to the entity
            for (int i = 0; i < dstEntities.Length; i++)
            {
                var componentInInstance = ((GameObject)gameObjectInstances[i]).GetComponent(obj.GetType());
                dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstTypeIndex, dstBaseIndex + i, componentInInstance);
            }

            return(true);
        }
        public static void InstantiateEntities(Entity srcEntity, Entity *outputEntities, int instanceCount,
                                               EntityComponentStore *entityComponentStore,
                                               ManagedComponentStore managedComponentStore,
                                               EntityGroupManager entityGroupManager)
        {
            var linkedType = TypeManager.GetTypeIndex <LinkedEntityGroup>();

            if (entityComponentStore->HasComponent(srcEntity, linkedType))
            {
                var header      = (BufferHeader *)entityComponentStore->GetComponentDataWithTypeRO(srcEntity, linkedType);
                var entityPtr   = (Entity *)BufferHeader.GetElementPointer(header);
                var entityCount = header->Length;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (entityCount == 0 || entityPtr[0] != srcEntity)
                {
                    throw new ArgumentException("LinkedEntityGroup[0] must always be the Entity itself.");
                }
                for (int i = 0; i < entityCount; i++)
                {
                    if (!entityComponentStore->Exists(entityPtr[i]))
                    {
                        throw new ArgumentException(
                                  "The srcEntity's LinkedEntityGroup references an entity that is invalid. (Entity at index {i} on the LinkedEntityGroup.)");
                    }

                    var archetype = entityComponentStore->GetArchetype(entityPtr[i]);
                    if (archetype->InstantiableArchetype == null)
                    {
                        throw new ArgumentException(
                                  "The srcEntity's LinkedEntityGroup references an entity that has already been destroyed. (Entity at index {i} on the LinkedEntityGroup. Only system state components are left on the entity)");
                    }
                }
#endif
                InstantiateEntitiesGroup(entityPtr, entityCount, outputEntities, instanceCount,
                                         entityComponentStore, managedComponentStore, entityGroupManager);
            }
            else
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (!entityComponentStore->Exists(srcEntity))
                {
                    throw new ArgumentException("srcEntity is not a valid entity");
                }

                var srcArchetype = entityComponentStore->GetArchetype(srcEntity);
                if (srcArchetype->InstantiableArchetype == null)
                {
                    throw new ArgumentException(
                              "srcEntity is not instantiable because it has already been destroyed. (Only system state components are left on it)");
                }
#endif
                InstantiateEntitiesOne(srcEntity, outputEntities, instanceCount, null, 0,
                                       entityComponentStore, managedComponentStore, entityGroupManager);
            }
        }
Esempio n. 28
0
        public T GetComponentObject <T>(Entity entity, ComponentType componentType)
        {
            EntityComponentStore->AssertEntityHasComponent(entity, componentType.TypeIndex);

            Chunk *chunk;
            int    chunkIndex;

            EntityComponentStore->GetChunk(entity, out chunk, out chunkIndex);
            return((T)ManagedComponentStore.GetManagedObject(chunk, componentType, chunkIndex));
        }
Esempio n. 29
0
        internal void SetComponentObject(Entity entity, ComponentType componentType, object componentObject)
        {
            EntityComponentStore->AssertEntityHasComponent(entity, componentType.TypeIndex);

            Chunk *chunk;
            int    chunkIndex;

            EntityComponentStore->GetChunk(entity, out chunk, out chunkIndex);
            ManagedComponentStore.SetManagedObject(chunk, componentType, chunkIndex, componentObject);
        }
Esempio n. 30
0
        public static void DestroyChunkForDiffing(Chunk *chunk,
                                                  EntityComponentStore *entityComponentStore,
                                                  ManagedComponentStore managedComponentStore)
        {
            chunk->Archetype->EntityCount -= chunk->Count;
            entityComponentStore->FreeEntities(chunk);

            EntityManagerCreateDestroyEntitiesUtility.SetChunkCount(chunk, 0,
                                                                    entityComponentStore, managedComponentStore);
        }