예제 #1
0
        public void EntityDiffer_GetChanges_BlobAssets_SetBuffer_MultipleEntities()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var blobAssetReferences = new NativeArray <BlobAssetReference <int> >(100, Allocator.Temp);

                for (var i = 0; i < blobAssetReferences.Length; i++)
                {
                    blobAssetReferences[i] = BlobAssetReference <int> .Create(i);
                }

                for (var i = 0; i < blobAssetReferences.Length; i += 4)
                {
                    var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid));

                    SrcEntityManager.SetComponentData(entity, CreateEntityGuid());

                    var buffer = SrcEntityManager.AddBuffer <EcsTestDataBlobAssetElement>(entity);

                    buffer.Add(new EcsTestDataBlobAssetElement {
                        blobElement = blobAssetReferences[i + 0]
                    });
                    buffer.Add(new EcsTestDataBlobAssetElement {
                        blobElement = blobAssetReferences[i + 1]
                    });
                    buffer.Add(new EcsTestDataBlobAssetElement {
                        blobElement = blobAssetReferences[i + 2]
                    });
                    buffer.Add(new EcsTestDataBlobAssetElement {
                        blobElement = blobAssetReferences[i + 3]
                    });
                }

                try
                {
                    using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                    {
                        Assert.IsTrue(changes.HasForwardChangeSet);
                        var forward = changes.ForwardChangeSet;
                        Assert.That(forward.CreatedBlobAssets.Length, Is.EqualTo(100));
                        Assert.That(forward.BlobAssetReferenceChanges.Length, Is.EqualTo(100));
                        Assert.That(forward.BlobAssetData.Length, Is.EqualTo(sizeof(int) * 100));
                    }
                }
                finally
                {
                    for (var i = 0; i < blobAssetReferences.Length; i++)
                    {
                        blobAssetReferences[i].Dispose();
                    }

                    blobAssetReferences.Dispose();
                }
            }
        }
예제 #2
0
        public void EntityDiffer_GetChanges_CreateEntityAndSetComponentData_WithoutFastForward_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestData), typeof(EcsTestManagedComponent));

                SrcEntityManager.SetComponentData(entity, CreateEntityGuid());
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });

                const EntityManagerDifferOptions options = EntityManagerDifferOptions.IncludeForwardChangeSet |
                                                           EntityManagerDifferOptions.IncludeReverseChangeSet;

                using (var changes = differ.GetChanges(options, Allocator.Temp))
                {
                    // ForwardChanges defines all operations needed to go from the shadow state to the current state.
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(0, changes.ForwardChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(1, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(3, changes.ForwardChangeSet.AddComponents.Length);
                    Assert.AreEqual(2, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetManagedComponents.Length);

                    // ReverseChanges defines all operations needed to go from the current state back to the last shadow state. (i.e. Undo)
                    Assert.IsTrue(changes.HasReverseChangeSet);
                    Assert.AreEqual(1, changes.ReverseChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.CreatedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.AddComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetManagedComponents.Length);
                }

                // Since we did not fast forward the inner shadow world. We should be able to generate the exact same changes again.
                using (var changes = differ.GetChanges(options, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(0, changes.ForwardChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(1, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(3, changes.ForwardChangeSet.AddComponents.Length);
                    Assert.AreEqual(2, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetManagedComponents.Length);

                    Assert.IsTrue(changes.HasReverseChangeSet);
                    Assert.AreEqual(1, changes.ReverseChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.CreatedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.AddComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetManagedComponents.Length);
                }
            }
        }
예제 #3
0
 public void EntityPatcher_ApplyChanges_CreateEntityWithDisabledComponent()
 {
     using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
     {
         var entityGuid = CreateEntityGuid();
         var entity     = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(Disabled));
         SrcEntityManager.SetComponentData(entity, entityGuid);
         PushChanges(differ, DstEntityManager);
         Assert.IsTrue(HasComponent <Disabled>(DstEntityManager, entityGuid));
     }
 }
        //@TODO: Test class based components (Currently doesn't work)
        //@TODO: Test number of created / destroyed chunk counts to be what is expected (for perf)
        //@TODO: Handle chunk component versions. It seems likely that they can currently go out of sync between two worlds so systems might not pick up a change. (Currently doesn't work)
        //@TODO: Test for blob data (Manually tested)
        //@TODO: Test that Copy&Replace doesn't modify, add or remove system state components. But also don't change chunk layout. (Currently doesn't work)

        unsafe void CreateTestData(out Entity entity, out Entity metaEntity, int value, int componentChunkValue)
        {
            entity = SrcEntityManager.CreateEntity();
            SrcEntityManager.AddComponentData(entity, new EcsTestData(value));
            SrcEntityManager.AddSharedComponentData(entity, new EcsTestSharedComp(6));
            SrcEntityManager.AddChunkComponentData(SrcEntityManager.UniversalQuery, new EcsTestData2(7));

            metaEntity = SrcEntityManager.GetChunk(entity).m_Chunk->metaChunkEntity;

            Assert.AreEqual(7, SrcEntityManager.GetComponentData <EcsTestData2>(metaEntity).value0);
        }
예제 #5
0
 public void EntityManagerPatcher_ApplyChanges_CreateEntityWithPrefabComponent()
 {
     using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
         using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
         {
             var entityGuid = CreateEntityGuid();
             var entity     = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(Prefab));
             SrcEntityManager.SetComponentData(entity, entityGuid);
             PushChanges(differ, patcher);
             Assert.IsTrue(HasComponent <Prefab>(DstEntityManager, entityGuid));
         }
 }
예제 #6
0
        public void EntityPatcher_ApplyChanges_LinkedEntityGroups_CombineTwoGroups()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var rootEntityGuid  = CreateEntityGuid();
                var childEntityGuid = CreateEntityGuid();

                var srcChildEntity = SrcEntityManager.CreateEntity(typeof(EcsTestDataEntity), typeof(LinkedEntityGroup));
                var srcRootEntity  = SrcEntityManager.CreateEntity(typeof(EcsTestDataEntity), typeof(LinkedEntityGroup));

                SrcEntityManager.AddComponentData(srcRootEntity, rootEntityGuid);
                SrcEntityManager.AddComponentData(srcChildEntity, childEntityGuid);

                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcRootEntity).Add(srcRootEntity);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcChildEntity).Add(srcChildEntity);

                // verify that we have two different groups in the output
                PushChanges(differ, DstEntityManager);

                var dstRootEntity  = GetEntity(DstEntityManager, rootEntityGuid);
                var dstChildEntity = GetEntity(DstEntityManager, childEntityGuid);

                {
                    var dstLinkedEntityGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootEntity);
                    Assert.AreEqual(dstLinkedEntityGroup.Length, 1);
                    Assert.AreEqual(dstLinkedEntityGroup[0].Value, dstRootEntity);
                }

                {
                    var dstLinkedEntityGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstChildEntity);
                    Assert.AreEqual(dstLinkedEntityGroup.Length, 1);
                    Assert.AreEqual(dstLinkedEntityGroup[0].Value, dstChildEntity);
                }

                // now combine the two groups and verify that they are the same
                SrcEntityManager.RemoveComponent <LinkedEntityGroup>(srcChildEntity);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcRootEntity).Add(srcChildEntity);

                PushChanges(differ, DstEntityManager);

                {
                    var dstLinkedEntityGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootEntity);
                    Assert.AreEqual(dstLinkedEntityGroup.Length, 2);
                    Assert.AreEqual(dstLinkedEntityGroup[0].Value, dstRootEntity);
                    Assert.AreEqual(dstLinkedEntityGroup[1].Value, dstChildEntity);
                }
            }
        }
예제 #7
0
        public void EntityPatcher_ApplyChanges_CreateEntityWithTestData_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestData), typeof(EcsTestManagedComponent));

                var entityGuid = CreateEntityGuid();

                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });

                PushChanges(differ, DstEntityManager);

                Assert.AreEqual(1, DstEntityManager.Debug.EntityCount);
                Assert.AreEqual(9, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
                Assert.AreEqual("SomeString", GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).value);
                Assert.IsNull(GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).nullField);

                // Mutate some component data.
                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 10
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeOtherString"
                });

                PushChanges(differ, DstEntityManager);

                Assert.AreEqual(1, DstEntityManager.Debug.EntityCount);
                Assert.AreEqual(10, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
                Assert.AreEqual("SomeOtherString", GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).value);
                Assert.IsNull(GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).nullField);

                // Destroy the entity
                SrcEntityManager.DestroyEntity(entity);

                PushChanges(differ, DstEntityManager);

                Assert.AreEqual(0, DstEntityManager.Debug.EntityCount);
            }
        }
예제 #8
0
        public void EntityDiffer_GetChanges_CreateEntityAndSetComponentData_WithFastForward_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestData), typeof(EcsTestManagedComponent));

                var entityGuid = CreateEntityGuid();

                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });

                const EntityManagerDifferOptions options = EntityManagerDifferOptions.IncludeForwardChangeSet |
                                                           EntityManagerDifferOptions.IncludeReverseChangeSet |
                                                           EntityManagerDifferOptions.FastForwardShadowWorld;

                using (var changes = differ.GetChanges(options, Allocator.Temp))
                {
                    // Forward changes is all changes needed to go from the shadow state to the current state.
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(0, changes.ForwardChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(1, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(3, changes.ForwardChangeSet.AddComponents.Length);
                    Assert.AreEqual(2, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetManagedComponents.Length);

                    // Reverse changes is all changes needed to go from the current state back to the last shadow state. (i.e. Undo)
                    Assert.IsTrue(changes.HasReverseChangeSet);
                    Assert.AreEqual(1, changes.ReverseChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.CreatedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.AddComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.SetManagedComponents.Length);
                }

                // The inner shadow world was updated during the last call which means no new changes should be found.
                using (var changes = differ.GetChanges(options, Allocator.Temp))
                {
                    Assert.IsFalse(changes.AnyChanges);
                }
            }
        }
예제 #9
0
        public void EntityPatcher_ApplyChanges_DebugNames(string srcName)
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity, entityGuid);
                SrcEntityManager.SetName(entity, srcName);

                PushChanges(differ, DstEntityManager);

                var dstEntity = GetEntity(DstEntityManager, entityGuid);
                var dstName   = DstEntityManager.GetName(dstEntity);

                Assert.AreEqual(srcName, dstName);
            }
        }
예제 #10
0
        public void EntityManagerPatcher_ApplyChanges_WithChunkData()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var    guid   = CreateEntityGuid();
                    var    entity = SrcEntityManager.CreateEntity();
                    Entity dstRootEntity;
                    // Chunk component is added but no values are copied
                    // Because chunks are generally caches and thus must be rebuildable automatically.
                    // They are also likely a totally different set of chunks.
                    // Diff & Patch is generally working against entities not on chunk level
                    {
                        SrcEntityManager.AddComponentData(entity, guid);
                        SrcEntityManager.AddComponentData(entity, new EcsTestData(1));
                        SrcEntityManager.AddChunkComponentData <EcsTestData2>(entity);
                        SrcEntityManager.SetChunkComponentData(SrcEntityManager.GetChunk(entity), new EcsTestData2(3));

                        PushChanges(differ, patcher);

                        dstRootEntity = GetEntity(DstEntityManager, guid);
                        Assert.AreEqual(1, DstEntityManager.GetComponentData <EcsTestData>(dstRootEntity).value);
                        Assert.IsTrue(DstEntityManager.HasChunkComponent <EcsTestData2>(dstRootEntity));
                        Assert.AreEqual(0, DstEntityManager.GetChunkComponentData <EcsTestData2>(dstRootEntity).value0);
                        Assert.AreEqual(1, DstEntityManager.CreateEntityQuery(typeof(ChunkHeader)).CalculateEntityCount());
                    }

                    // Changing Chunk component creates no diff
                    {
                        SrcEntityManager.SetChunkComponentData(SrcEntityManager.GetChunk(entity), new EcsTestData2(7));
                        using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                        {
                            Assert.IsFalse(changes.AnyChanges);
                        }
                    }

                    // Removing chunk component, removes chunk component again
                    {
                        SrcEntityManager.RemoveChunkComponent <EcsTestData2>(entity);
                        PushChanges(differ, patcher);
                        Assert.IsFalse(DstEntityManager.HasChunkComponent <EcsTestData2>(dstRootEntity));
                        Assert.AreEqual(0, DstEntityManager.CreateEntityQuery(typeof(ChunkHeader)).CalculateEntityCount());
                    }
                }
        }
예제 #11
0
        public void EntityDiffer_GetChanges_BlobAssets_SetComponent_Null()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestDataBlobAssetRef));
                SrcEntityManager.SetComponentData(entity, CreateEntityGuid());

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    var forward = changes.ForwardChangeSet;
                    Assert.That(forward.BlobAssetReferenceChanges.Length, Is.EqualTo(1));
                    Assert.That(forward.BlobAssetReferenceChanges[0].Value, Is.EqualTo(0));
                    Assert.That(forward.CreatedBlobAssets.Length, Is.EqualTo(0));
                    Assert.That(forward.BlobAssetData.Length, Is.EqualTo(0));
                }
            }
        }
예제 #12
0
        public void EntityPatcher_ApplyChanges_BlobAssets_CreateEntityWithBlobAssetReference()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var blobAssetReference = BlobAssetReference <int> .Create(11);

                var entity     = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestDataBlobAssetRef));
                var entityGuid = CreateEntityGuid();

                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestDataBlobAssetRef {
                    value = blobAssetReference
                });

                PushChanges(differ, DstEntityManager);

                Assert.AreEqual(1, DstEntityManager.Debug.EntityCount);
                Assert.AreEqual(11, GetComponentData <EcsTestDataBlobAssetRef>(DstEntityManager, entityGuid).value.Value);
            }
        }
예제 #13
0
        public void EntityManagerDiffer_GetChanges_DuplicateEntityGuidThrows()
        {
            using (var tracker = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();

                var entity0 = SrcEntityManager.CreateEntity(typeof(EntityGuid));
                var entity1 = SrcEntityManager.CreateEntity(typeof(EntityGuid));

                SrcEntityManager.SetComponentData(entity0, entityGuid);
                SrcEntityManager.SetComponentData(entity1, entityGuid);

                Assert.Throws <DuplicateEntityGuidException>(() =>
                {
                    using (tracker.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                    {
                    }
                });
            }
        }
    public void PatchWithObjectReferenceResolving()
    {
        var material = AssetDatabase.LoadAssetAtPath <Material>("Packages/com.unity.entities/Unity.Scenes.Hybrid.Tests/Test.mat");

        using (var differ = new EntityManagerDiffer(SrcWorld.EntityManager, Allocator.TempJob))
        {
            var entityGuid = CreateEntityGuid();

            var entity = SrcEntityManager.CreateEntity();
            SrcEntityManager.AddComponentData(entity, entityGuid);
            SrcEntityManager.AddSharedComponentData(entity, new ComponentWithObjectRef {
                Material = material
            });
            SrcEntityManager.AddComponentData(entity, new EcsTestData(5));

            var options = EntityManagerDifferOptions.IncludeForwardChangeSet | EntityManagerDifferOptions.FastForwardShadowWorld;

            using (var changes = differ.GetChanges(options, Allocator.TempJob))
            {
                var srcChange = new LiveLinkChangeSet
                {
                    Changes   = changes.ForwardChangeSet,
                    SceneName = "Boing",
                    UnloadAllPreviousEntities = true,
                    SceneGUID = new Unity.Entities.Hash128(),
                    FramesToRetainBlobAssets = 1
                };

                var changeSet = SerializeAndDeserialize(srcChange);
                AssertChangeSetsAreEqual(srcChange, changeSet);

                EntityPatcher.ApplyChangeSet(DstEntityManager, changeSet.Changes);

                changeSet.Dispose();
            }

            var dstMaterial = GetSharedComponentData <ComponentWithObjectRef>(DstEntityManager, entityGuid).Material;
            Assert.AreEqual(material, dstMaterial);
            Assert.AreEqual(5, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
        }
    }
예제 #15
0
        public void EntityPatcher_ApplyChanges_AddComponent_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity, entityGuid);
                SrcEntityManager.AddComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.AddComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });

                PushChanges(differ, DstEntityManager);

                // Add a component in the source world.
                SrcEntityManager.AddComponentData(entity, new EcsTestData2(10));
                SrcEntityManager.AddComponentData(entity, new EcsTestManagedComponent2()
                {
                    value = "SomeOtherString"
                });

                // Mutate the dst world
                SetComponentData(DstEntityManager, entityGuid, new EcsTestData(-1));
                SetManagedComponentData(DstEntityManager, entityGuid, new EcsTestManagedComponent()
                {
                    value = "YetAnotherString"
                });

                PushChanges(differ, DstEntityManager);

                // Both changes should be present in the output
                Assert.AreEqual(10, GetComponentData <EcsTestData2>(DstEntityManager, entityGuid).value0);
                Assert.AreEqual(-1, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
                Assert.AreEqual("SomeOtherString", GetManagedComponentData <EcsTestManagedComponent2>(DstEntityManager, entityGuid).value);
                Assert.IsNull(GetManagedComponentData <EcsTestManagedComponent2>(DstEntityManager, entityGuid).nullField);
                Assert.AreEqual("YetAnotherString", GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).value);
                Assert.IsNull(GetManagedComponentData <EcsTestManagedComponent>(DstEntityManager, entityGuid).nullField);
            }
        }
예제 #16
0
        public void EntityDiffer_GetChanges_CreateEntityAndSetSharedComponentData_IncrementalChanges()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestSharedComp));

                SrcEntityManager.SetComponentData(entity, CreateEntityGuid());
                SrcEntityManager.SetSharedComponentData(entity, new EcsTestSharedComp {
                    value = 2
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(1, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(2, changes.ForwardChangeSet.AddComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetSharedComponents.Length);
                }
            }
        }
예제 #17
0
        public void EntityDiffer_GetChanges_DuplicateEntityGuidThrows()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                void GetChanges()
                {
                    using (differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp)) { }
                }

                var entityGuid0 = CreateEntityGuid();
                var entityGuid1 = CreateEntityGuid();
                var entityGuid2 = CreateEntityGuid();
                var entityGuid3 = CreateEntityGuid();

                var entity0 = SrcEntityManager.CreateEntity(typeof(EntityGuid));
                var entity1 = SrcEntityManager.CreateEntity(typeof(EntityGuid));
                var entity2 = SrcEntityManager.CreateEntity(typeof(EntityGuid));
                var entity3 = SrcEntityManager.CreateEntity(typeof(EntityGuid));

                SrcEntityManager.SetComponentData(entity0, entityGuid0);
                SrcEntityManager.SetComponentData(entity1, entityGuid1);
                SrcEntityManager.SetComponentData(entity2, entityGuid2);
                SrcEntityManager.SetComponentData(entity3, entityGuid3);

                Assert.DoesNotThrow(GetChanges);

                SrcEntityManager.SetComponentData(entity1, entityGuid0);
                SrcEntityManager.SetComponentData(entity2, entityGuid0);
                SrcEntityManager.SetComponentData(entity3, entityGuid0);

                var dup0 = Assert.Throws <DuplicateEntityGuidException>(GetChanges).DuplicateEntityGuids;
                Assert.That(dup0, Is.EquivalentTo(new[] { new DuplicateEntityGuid(entityGuid0, 3) }));

                SrcEntityManager.SetComponentData(entity0, entityGuid1);
                SrcEntityManager.SetComponentData(entity3, entityGuid1);

                var dup1 = Assert.Throws <DuplicateEntityGuidException>(GetChanges).DuplicateEntityGuids;
                Assert.That(dup1, Is.EquivalentTo(new[] { new DuplicateEntityGuid(entityGuid0, 1), new DuplicateEntityGuid(entityGuid1, 1) }));
            }
        }
예제 #18
0
        public void EntityDiffer_AddingZeroSizeComponentToWholeChunk()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                for (int i = 0; i != 10; i++)
                {
                    var entityGuid = CreateEntityGuid();
                    var entity     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity, entityGuid);
                }

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp)) {}

                SrcEntityManager.AddSharedComponentData(SrcEntityManager.UniversalQuery, new SharedData1(9));

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.AnyChanges);
                    Assert.AreEqual(10, changes.ForwardChangeSet.AddComponents.Length);
                }
            }
        }
        public void CopyEntitiesToOtherWorld()
        {
            CreateTestData(out var entity0, 5);
            CreateTestData(out var entity1, 6);

            SrcEntityManager.AddComponentData(entity0, new EcsTestManagedDataEntity("0", entity1));
            SrcEntityManager.AddComponentData(entity1, new Disabled());
            SrcEntityManager.AddComponentData(entity1, new Prefab());

            SrcEntityManager.AddChunkComponentData(SrcEntityManager.UniversalQuery, new EcsTestData2(7));

            using (var srcEntities = new NativeArray <Entity>(new[] { entity0, entity1 }, Allocator.Temp))
                using (var dstEntities = new NativeArray <Entity>(2, Allocator.Temp))
                {
                    // create extra entities to ensure entity id's aren't the same by accident
                    DstEntityManager.CreateEntity();

                    DstEntityManager.CopyEntitiesFrom(SrcEntityManager, srcEntities, dstEntities);

                    TestValues(dstEntities[0], 5, 0);
                    Assert.AreEqual(dstEntities[1], DstEntityManager.GetComponentData <EcsTestManagedDataEntity>(dstEntities[0]).value1);
                    Assert.AreEqual("0", DstEntityManager.GetComponentData <EcsTestManagedDataEntity>(dstEntities[0]).value0);
                    Assert.IsFalse(DstEntityManager.HasComponent <EcsTestManagedDataEntity>(dstEntities[1]));

                    // Prefab & Disabled tag is kept in the clone - this is a copy not instantiate semantic
                    Assert.IsFalse(DstEntityManager.HasComponent <Disabled>(dstEntities[0]));
                    Assert.IsFalse(DstEntityManager.HasComponent <Prefab>(dstEntities[0]));
                    Assert.IsTrue(DstEntityManager.HasComponent <Disabled>(dstEntities[1]));
                    Assert.IsTrue(DstEntityManager.HasComponent <Prefab>(dstEntities[1]));

                    TestValues(dstEntities[1], 6, 0);
                }

            Assert.AreEqual(2, SrcEntityManager.UniversalQuery.CalculateEntityCount());
            Assert.AreEqual(3, DstEntityManager.UniversalQuery.CalculateEntityCount());

            SrcEntityManager.Debug.CheckInternalConsistency();
            DstEntityManager.Debug.CheckInternalConsistency();
        }
예제 #20
0
        public void EntityManagerPatcher_ApplyChanges_CreateEntityWithTestData()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestData));

                    var entityGuid = CreateEntityGuid();

                    SrcEntityManager.SetComponentData(entity, entityGuid);
                    SrcEntityManager.SetComponentData(entity, new EcsTestData {
                        value = 9
                    });

                    PushChanges(differ, patcher);

                    Assert.AreEqual(1, DstEntityManager.Debug.EntityCount);
                    Assert.AreEqual(9, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);

                    // Mutate some component data.
                    SrcEntityManager.SetComponentData(entity, entityGuid);
                    SrcEntityManager.SetComponentData(entity, new EcsTestData {
                        value = 10
                    });

                    PushChanges(differ, patcher);

                    Assert.AreEqual(1, DstEntityManager.Debug.EntityCount);
                    Assert.AreEqual(10, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);

                    // Destroy the entity
                    SrcEntityManager.DestroyEntity(entity);

                    PushChanges(differ, patcher);

                    Assert.AreEqual(0, DstEntityManager.Debug.EntityCount);
                }
        }
예제 #21
0
        public void EntityPatcher_ApplyChanges_UnidentifiedEntityReferenceBecomesNull()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                // Create extra entity to make sure test doesn't accidentally succeed with no remapping
                SrcEntityManager.CreateEntity();

                // Create a standalone entity with no entityGuid. This means the change tracking should NOT resolve it.
                var missing = SrcEntityManager.CreateEntity();

                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity, entityGuid);
                SrcEntityManager.AddComponentData(entity, new EcsTestDataEntity {
                    value1 = missing
                });

                PushChanges(differ, DstEntityManager);

                // Missing entity has no entityGuid, so the reference becomes null.
                Assert.AreEqual(Entity.Null, GetComponentData <EcsTestDataEntity>(DstEntityManager, entityGuid).value1);
            }
        }
예제 #22
0
        public void EntityPatcher_ApplyChanges_RemoveComponent()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity, entityGuid);
                SrcEntityManager.AddComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.AddComponentData(entity, new EcsTestData2(7));

                PushChanges(differ, DstEntityManager);

                SrcEntityManager.RemoveComponent <EcsTestData>(entity);
                SetComponentData(DstEntityManager, entityGuid, new EcsTestData2(-1));

                PushChanges(differ, DstEntityManager);

                Assert.IsFalse(HasComponent <EcsTestData>(DstEntityManager, entityGuid));
                Assert.AreEqual(-1, GetComponentData <EcsTestData2>(DstEntityManager, entityGuid).value0);
            }
        }
예제 #23
0
        public void EntityManagerPatcher_ApplyChanges_ChangeAppliesToAllPrefabInstances([Values] bool prefabTag)
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    // Create a prefab in the source world.
                    var entityGuid = CreateEntityGuid();
                    var prefab     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(prefab, entityGuid);
                    SrcEntityManager.AddComponentData(prefab, new EcsTestData());

                    if (prefabTag)
                    {
                        SrcEntityManager.AddComponentData(prefab, new Prefab());
                    }

                    // Sync to the dst world. At this point the dst world will have a single entity.
                    PushChanges(differ, patcher);

                    var dstPrefab = GetEntity(DstEntityManager, entityGuid);

                    // Spawn some more instances of this thing in the dst world.
                    var dstInstance0 = DstEntityManager.Instantiate(dstPrefab);
                    var dstInstance1 = DstEntityManager.Instantiate(dstPrefab);

                    // Mutate the original prefab in the src world.
                    SrcEntityManager.SetComponentData(prefab, new EcsTestData(10));

                    // Sync to the dst world.
                    PushChanges(differ, patcher);

                    // The changes should be propagated to all instances.
                    Assert.AreEqual(10, DstEntityManager.GetComponentData <EcsTestData>(dstPrefab).value);
                    Assert.AreEqual(10, DstEntityManager.GetComponentData <EcsTestData>(dstInstance0).value);
                    Assert.AreEqual(10, DstEntityManager.GetComponentData <EcsTestData>(dstInstance1).value);
                }
        }
예제 #24
0
        public void EntityPatcher_ApplyChanges_RemoveComponent_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity();
                SrcEntityManager.AddComponentData(entity, entityGuid);
                SrcEntityManager.AddComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.AddComponentData(entity, new EcsTestData2(7));
                SrcEntityManager.AddComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });
                SrcEntityManager.AddComponentData(entity, new EcsTestManagedComponent2 {
                    value = "SomeOtherString"
                });

                PushChanges(differ, DstEntityManager);

                SrcEntityManager.RemoveComponent <EcsTestData>(entity);
                SrcEntityManager.RemoveComponent <EcsTestManagedComponent>(entity);
                SetComponentData(DstEntityManager, entityGuid, new EcsTestData2(-1));
                SetManagedComponentData(DstEntityManager, entityGuid, new EcsTestManagedComponent2()
                {
                    value = "YetAnotherString"
                });

                PushChanges(differ, DstEntityManager);

                Assert.IsFalse(HasComponent <EcsTestData>(DstEntityManager, entityGuid));
                Assert.IsFalse(HasManagedComponent <EcsTestManagedComponent>(DstEntityManager, entityGuid));
                Assert.AreEqual(-1, GetComponentData <EcsTestData2>(DstEntityManager, entityGuid).value0);
                Assert.AreEqual("YetAnotherString", GetManagedComponentData <EcsTestManagedComponent2>(DstEntityManager, entityGuid).value);
                Assert.IsNull(GetManagedComponentData <EcsTestManagedComponent2>(DstEntityManager, entityGuid).nullField);
            }
        }
예제 #25
0
        public unsafe void EntityDiffer_GetChanges_BlobAssets_SetComponent()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var blobAssetReference0 = BlobAssetReference <int> .Create(10);

                var entity = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestDataBlobAssetRef));

                SrcEntityManager.SetComponentData(entity, CreateEntityGuid());
                SrcEntityManager.SetComponentData(entity, new EcsTestDataBlobAssetRef
                {
                    value = blobAssetReference0
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    var forward = changes.ForwardChangeSet;

                    Assert.That(forward.CreatedBlobAssets.Length, Is.EqualTo(1));
                    Assert.That(forward.DestroyedBlobAssets.Length, Is.EqualTo(0));

                    Assert.That(forward.BlobAssetReferenceChanges.Length, Is.EqualTo(1));
                    Assert.That(forward.BlobAssetReferenceChanges[0].Value, Is.EqualTo(forward.CreatedBlobAssets[0].Hash));

                    Assert.That(forward.BlobAssetData.Length, Is.EqualTo(sizeof(int)));
                    Assert.That(*(int *)forward.BlobAssetData.GetUnsafePtr(), Is.EqualTo(10));
                }

                blobAssetReference0.Dispose();

                var blobAssetReference1 = BlobAssetReference <int> .Create(20);

                SrcEntityManager.SetComponentData(entity, new EcsTestDataBlobAssetRef
                {
                    value = blobAssetReference1
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);

                    var forward = changes.ForwardChangeSet;
                    Assert.That(forward.CreatedBlobAssets.Length, Is.EqualTo(1));
                    Assert.That(forward.BlobAssetReferenceChanges.Length, Is.EqualTo(1));
                    Assert.That(forward.BlobAssetData.Length, Is.EqualTo(sizeof(int)));
                    Assert.That(*(int *)forward.BlobAssetData.GetUnsafePtr(), Is.EqualTo(20));
                    Assert.That(forward.BlobAssetReferenceChanges[0].Value, Is.EqualTo(forward.CreatedBlobAssets[0].Hash));

                    Assert.IsTrue(changes.HasReverseChangeSet);

                    var reverse = changes.ReverseChangeSet;
                    Assert.That(reverse.CreatedBlobAssets.Length, Is.EqualTo(1));
                    Assert.That(reverse.BlobAssetReferenceChanges.Length, Is.EqualTo(1));
                    Assert.That(reverse.BlobAssetData.Length, Is.EqualTo(sizeof(int)));
                    Assert.That(*(int *)reverse.BlobAssetData.GetUnsafePtr(), Is.EqualTo(10));
                    Assert.That(reverse.BlobAssetReferenceChanges[0].Value, Is.EqualTo(reverse.CreatedBlobAssets[0].Hash));
                }

                blobAssetReference1.Dispose();
            }
        }
예제 #26
0
        public void EntityDiffer_GetChanges_CreateEntityAndSetComponentData_IncrementalChanges_ManagedComponents()
        {
            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                var entityGuid = CreateEntityGuid();
                var entity     = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestData), typeof(EcsTestManagedComponent));

                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 9
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeString"
                });

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.AnyChanges);
                }

                // Mutate some component data.
                SrcEntityManager.SetComponentData(entity, entityGuid);
                SrcEntityManager.SetComponentData(entity, new EcsTestData {
                    value = 10
                });
                SrcEntityManager.SetComponentData(entity, new EcsTestManagedComponent {
                    value = "SomeOtherString"
                });

                // The entityGuid value is the same so it should not be picked up during change tracking.
                // We should only see the two data changes.
                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    // The ForwardChangeSet will contain a set value 10 and set value "SomeString"
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(0, changes.ForwardChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ForwardChangeSet.SetManagedComponents.Length);
                    Assert.AreEqual(0, changes.ForwardChangeSet.AddComponents.Length);

                    // The ReverseChangeSet will contain a set value 9 and set value "SomeOtherString"
                    Assert.IsTrue(changes.HasReverseChangeSet);
                    Assert.AreEqual(0, changes.ReverseChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ReverseChangeSet.CreatedEntityCount);
                    Assert.AreEqual(1, changes.ReverseChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ReverseChangeSet.SetManagedComponents.Length);
                    Assert.AreEqual(0, changes.ReverseChangeSet.AddComponents.Length);
                }

                SrcEntityManager.DestroyEntity(entity);

                using (var changes = differ.GetChanges(EntityManagerDifferOptions.Default, Allocator.Temp))
                {
                    Assert.IsTrue(changes.HasForwardChangeSet);
                    Assert.AreEqual(1, changes.ForwardChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(0, changes.ForwardChangeSet.CreatedEntityCount);
                    Assert.AreEqual(0, changes.ForwardChangeSet.SetComponents.Length);
                    Assert.AreEqual(0, changes.ForwardChangeSet.SetManagedComponents.Length);
                    Assert.AreEqual(0, changes.ForwardChangeSet.RemoveComponents.Length);

                    // In this case the ReverseChangeSet should describe how to get this entity back in it's entirety
                    Assert.IsTrue(changes.HasReverseChangeSet);
                    Assert.AreEqual(0, changes.ReverseChangeSet.DestroyedEntityCount);
                    Assert.AreEqual(1, changes.ReverseChangeSet.CreatedEntityCount);
                    Assert.AreEqual(3, changes.ReverseChangeSet.AddComponents.Length);
                    Assert.AreEqual(2, changes.ReverseChangeSet.SetComponents.Length);
                    Assert.AreEqual(1, changes.ReverseChangeSet.SetManagedComponents.Length);
                }
            }
        }
 void CreateTestData(out Entity entity, int value)
 {
     entity = SrcEntityManager.CreateEntity();
     SrcEntityManager.AddComponentData(entity, new EcsTestData(value));
     SrcEntityManager.AddSharedComponentData(entity, new EcsTestSharedComp(6));
 }
        public void UndoRedoPrefabInstancesWithRelationship()
        {
            const int instanceCount       = 10;
            var       srcPrefabRootGuid   = CreateEntityGuid();
            var       srcPrefabLevel0Guid = CreateEntityGuid();
            var       prefabLevel1Guid    = CreateEntityGuid();

            const EntityManagerDifferOptions options = EntityManagerDifferOptions.IncludeForwardChangeSet |
                                                       EntityManagerDifferOptions.FastForwardShadowWorld;

            using (var differ = new EntityManagerDiffer(SrcEntityManager, Allocator.TempJob))
            {
                // Create Root Prefab entity with a Guid component
                var srcPrefabRoot = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab), typeof(LinkedEntityGroup));
                SrcEntityManager.AddComponentData(srcPrefabRoot, srcPrefabRootGuid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcPrefabRoot);

                PushChanges(differ, DstEntityManager);

                using (var changes = differ.GetChanges(options, Allocator.TempJob))
                {
                    EntityPatcher.ApplyChangeSet(DstEntityManager, changes.ForwardChangeSet);
                }

                // Instantiate root prefab in dst world 10 times
                var dstPrefabRoot    = GetEntity(DstEntityManager, srcPrefabRootGuid);
                var dstInstanceRoots = new Entity[instanceCount];
                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstInstanceRoot = DstEntityManager.Instantiate(dstPrefabRoot);
                    dstInstanceRoots[i] = dstInstanceRoot;
                    Assert.AreEqual(1, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot).Length);
                    Assert.AreEqual(dstInstanceRoot, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot)[0].Value);
                }

                // Add level 0 entity to the prefab
                var srcLevel0Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel0Prefab, srcPrefabLevel0Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel0Prefab);

                SrcEntityManager.SetComponentData(srcPrefabRoot, new HierarchyComponent {
                    Parent = Entity.Null, Child = srcLevel0Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = Entity.Null
                });

                // Synchronize worlds, we now should have 10 instances in the world along with a level0 for each
                // and hierarchy matching the relationships create
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstInstanceRoot   = dstInstanceRoots[i];
                    var dstInstanceGroup  = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstInstanceRoot);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;

                    Assert.AreEqual(2, dstInstanceGroup.Length);
                    Assert.AreEqual(dstInstanceRoot, dstInstanceGroup[0].Value);
                    Assert.AreEqual(dstInstanceLevel0, dstInstanceGroup[1].Value);

                    var hierarchyLevel0 = DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0);
                    var hierarchyRoot   = DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceRoot);

                    Assert.AreEqual(dstInstanceRoot, hierarchyLevel0.Parent);
                    Assert.AreEqual(dstInstanceLevel0, hierarchyRoot.Child);
                }

                // Add level 1 entity to the prefab
                var srcLevel1Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel1Prefab, prefabLevel1Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel1Prefab);

                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = srcLevel1Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel1Prefab, new HierarchyComponent {
                    Parent = srcLevel0Prefab, Child = Entity.Null
                });

                // Synchronize worlds, we now should have 10 instances of level 1 linked to their matching level 0
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(3, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;
                    var dstInstanceLevel1 = dstInstanceGroup[2].Value;

                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Parent);
                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Child);
                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                }

                // Remove level 1 entity from the prefab
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).RemoveAt(2);
                SrcEntityManager.DestroyEntity(srcLevel1Prefab);

                // Fix the hierarchy of level 0 to remove the link to level 1
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = Entity.Null
                });

                // Synchronize worlds, destination world should no longer have instances of level 1
                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(2, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel1 = dstInstanceGroup[1].Value;

                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                    Assert.AreEqual(Entity.Null, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Child);
                }

                // Add again level 1 as a Child of level 0
                srcLevel1Prefab = SrcEntityManager.CreateEntity(typeof(HierarchyComponent), typeof(Prefab));
                SrcEntityManager.AddComponentData(srcLevel1Prefab, prefabLevel1Guid);
                SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcPrefabRoot).Add(srcLevel1Prefab);
                SrcEntityManager.SetComponentData(srcLevel0Prefab, new HierarchyComponent {
                    Parent = srcPrefabRoot, Child = srcLevel1Prefab
                });
                SrcEntityManager.SetComponentData(srcLevel1Prefab, new HierarchyComponent {
                    Parent = srcLevel0Prefab, Child = Entity.Null
                });

                PushChanges(differ, DstEntityManager);

                for (var i = 0; i != dstInstanceRoots.Length; i++)
                {
                    var dstRootInstance = dstInstanceRoots[i];

                    var dstInstanceGroup = DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance);
                    Assert.AreEqual(3, dstInstanceGroup.Length);
                    Assert.AreEqual(dstRootInstance, dstInstanceGroup[0].Value);
                    var dstInstanceLevel0 = dstInstanceGroup[1].Value;
                    var dstInstanceLevel1 = dstInstanceGroup[2].Value;

                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstRootInstance).Child);
                    Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Parent);
                    Assert.AreEqual(dstInstanceLevel1, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel0).Child);
                    Assert.AreEqual(dstInstanceLevel0, DstEntityManager.GetComponentData <HierarchyComponent>(dstInstanceLevel1).Parent);
                }
            }
        }