示例#1
0
        public unsafe void EntityManagerPatcher_ApplyChanges_CreateSharedComponent()
        {
            const int count = 3;

            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuids = stackalloc EntityGuid[count]
                    {
                        CreateEntityGuid(),
                        CreateEntityGuid(),
                        CreateEntityGuid()
                    };

                    for (var i = 0; i != count; i++)
                    {
                        var entity = SrcEntityManager.CreateEntity();
                        SrcEntityManager.AddComponentData(entity, entityGuids[i]);
                        SrcEntityManager.AddSharedComponentData(entity, new EcsTestSharedComp {
                            value = i * 2
                        });
                    }

                    PushChanges(differ, patcher);

                    for (var i = 0; i != count; i++)
                    {
                        var sharedData = GetSharedComponentData <EcsTestSharedComp>(DstEntityManager, entityGuids[i]);
                        Assert.AreEqual(i * 2, sharedData.value);
                    }
                }
        }
示例#2
0
        public void EntityManagerPatcher_ApplyChanges_EntityPatchWithMissingValueDoesNotThrow()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid0 = CreateEntityGuid();
                    var entity0     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity0, entityGuid0);

                    var entityGuid1 = CreateEntityGuid();
                    var entity1     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity1, entityGuid1);

                    PushChanges(differ, patcher);

                    // Create a component with an entity reference
                    SrcEntityManager.AddComponentData(entity1, new EcsTestDataEntity {
                        value1 = entity0
                    });

                    using (var changes = differ.GetChanges(EntityManagerDifferOptions.IncludeForwardChangeSet, Allocator.TempJob))
                    {
                        var forward = changes.ForwardChangeSet;

                        Assert.That(forward.EntityPatches.Length, Is.EqualTo(1));

                        // Destroy the entity the patch references
                        SrcEntityManager.DestroyEntity(entity0);

                        Assert.DoesNotThrow(() => { patcher.ApplyChangeSet(forward); });
                    }
                }
        }
示例#3
0
        public void EntityManagerPatcher_ApplyChanges_EntityPatchWithAmbiguousTargetDoesNotThrow()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid0 = CreateEntityGuid();
                    var entity0     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity0, entityGuid0);

                    var entityGuid1 = CreateEntityGuid();
                    var entity1     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity1, entityGuid1);

                    PushChanges(differ, patcher);

                    // Create a patch
                    SrcEntityManager.AddComponentData(entity1, new EcsTestDataEntity {
                        value1 = entity0
                    });

                    using (var changes = differ.GetChanges(EntityManagerDifferOptions.IncludeForwardChangeSet, Allocator.TempJob))
                    {
                        var forward = changes.ForwardChangeSet;

                        Assert.That(forward.EntityPatches.Length, Is.EqualTo(1));

                        // Create a new entity in the dst world with the same ID the patch target.
                        var dstEntity0 = DstEntityManager.CreateEntity();
                        DstEntityManager.AddComponentData(dstEntity0, entityGuid1);

                        Assert.DoesNotThrow(() => { patcher.ApplyChangeSet(forward); });
                    }
                }
        }
示例#4
0
        public void EntityManagerPatcher_ApplyChanges_AddComponent()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid = CreateEntityGuid();
                    var entity     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity, entityGuid);
                    SrcEntityManager.AddComponentData(entity, new EcsTestData {
                        value = 9
                    });

                    PushChanges(differ, patcher);

                    // Add a component in the source world.
                    SrcEntityManager.AddComponentData(entity, new EcsTestData2(10));

                    // Mutate the dst world
                    SetComponentData(DstEntityManager, entityGuid, new EcsTestData(-1));

                    PushChanges(differ, patcher);

                    // Both changes should be present in the output
                    Assert.AreEqual(10, GetComponentData <EcsTestData2>(DstEntityManager, entityGuid).value0);
                    Assert.AreEqual(-1, GetComponentData <EcsTestData>(DstEntityManager, entityGuid).value);
                }
        }
示例#5
0
        public void EntityManagerPatcher_ApplyChanges_RemapEntityReferences()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    // Create extra entity to make sure test doesn't accidentally succeed with no remapping
                    SrcEntityManager.CreateEntity();

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

                    var e0 = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestDataEntity));
                    var e1 = SrcEntityManager.CreateEntity(typeof(EntityGuid), typeof(EcsTestDataEntity));

                    SrcEntityManager.SetComponentData(e0, entityGuid0);
                    SrcEntityManager.SetComponentData(e1, entityGuid1);

                    SrcEntityManager.SetComponentData(e0, new EcsTestDataEntity {
                        value1 = e1
                    });
                    SrcEntityManager.SetComponentData(e1, new EcsTestDataEntity {
                        value1 = e0
                    });

                    PushChanges(differ, patcher);

                    Assert.AreEqual(GetEntity(DstEntityManager, entityGuid1), GetComponentData <EcsTestDataEntity>(DstEntityManager, entityGuid0).value1);
                    Assert.AreEqual(GetEntity(DstEntityManager, entityGuid0), GetComponentData <EcsTestDataEntity>(DstEntityManager, entityGuid1).value1);
                }
        }
示例#6
0
        public void EntityManagerPatcher_ApplyChanges_CreateDynamicBuffer([Values(1, 100)] int bufferLength)
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid = CreateEntityGuid();
                    var entity     = SrcEntityManager.CreateEntity();

                    SrcEntityManager.AddComponentData(entity, entityGuid);
                    var buffer = SrcEntityManager.AddBuffer <EcsIntElement>(entity);

                    for (var i = 0; i < bufferLength; ++i)
                    {
                        buffer.Add(new EcsIntElement {
                            Value = i
                        });
                    }

                    PushChanges(differ, patcher);

                    var dstEntity = GetEntity(DstEntityManager, entityGuid);
                    var dstBuffer = DstEntityManager.GetBuffer <EcsIntElement>(dstEntity);

                    Assert.AreEqual(bufferLength, dstBuffer.Length);
                    for (var i = 0; i != dstBuffer.Length; i++)
                    {
                        Assert.AreEqual(i, dstBuffer[i].Value);
                    }
                }
        }
示例#7
0
        public void EntityManagerPatcher_ApplyChanges_ChangeSharedComponent()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid = CreateEntityGuid();
                    var entity     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity, entityGuid);
                    SrcEntityManager.AddComponent <EcsTestSharedComp>(entity);

                    PushChanges(differ, patcher);
                    var dstEntity = GetEntity(DstEntityManager, entityGuid);
                    Assert.AreEqual(0, DstEntityManager.GetSharedComponentDataIndex <EcsTestSharedComp>(dstEntity));
                    Assert.AreEqual(0, DstEntityManager.GetSharedComponentData <EcsTestSharedComp>(dstEntity).value);

                    SrcEntityManager.SetSharedComponentData(entity, new EcsTestSharedComp {
                        value = 2
                    });
                    PushChanges(differ, patcher);
                    Assert.AreEqual(2, DstEntityManager.GetSharedComponentData <EcsTestSharedComp>(dstEntity).value);

                    SrcEntityManager.SetSharedComponentData(entity, new EcsTestSharedComp {
                        value = 3
                    });
                    PushChanges(differ, patcher);
                    Assert.AreEqual(3, DstEntityManager.GetSharedComponentData <EcsTestSharedComp>(dstEntity).value);

                    SrcEntityManager.SetSharedComponentData(entity, new EcsTestSharedComp {
                        value = 0
                    });
                    PushChanges(differ, patcher);
                    Assert.AreEqual(0, DstEntityManager.GetSharedComponentDataIndex <EcsTestSharedComp>(dstEntity));
                    Assert.AreEqual(0, DstEntityManager.GetSharedComponentData <EcsTestSharedComp>(dstEntity).value);
                }
        }
示例#8
0
        public void EntityManagerPatcher_ApplyChanges_NewEntityIsReplicatedIntoExistingPrefabInstances([Values(1, 10)] int instanceCount)
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var rootEntityGuid  = CreateEntityGuid();
                    var childEntityGuid = CreateEntityGuid();

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

                    SrcEntityManager.AddComponentData(srcRootEntity, rootEntityGuid);
                    SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcRootEntity).Add(srcRootEntity);

                    PushChanges(differ, patcher);

                    var dstRootEntity = GetEntity(DstEntityManager, rootEntityGuid);

                    // Instantiate root in dst world
                    var dstRootInstances = new Entity[instanceCount];
                    for (var i = 0; i != dstRootInstances.Length; i++)
                    {
                        var dstRootInstance = DstEntityManager.Instantiate(dstRootEntity);
                        dstRootInstances[i] = dstRootInstance;
                        Assert.AreEqual(1, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance).Length);
                        Assert.AreEqual(dstRootInstance, DstEntityManager.GetBuffer <LinkedEntityGroup>(dstRootInstance)[0].Value);
                    }

                    // Add a new entity into the prefab
                    var srcChildEntity = SrcEntityManager.CreateEntity(typeof(EcsTestDataEntity), typeof(Prefab));
                    SrcEntityManager.AddComponentData(srcChildEntity, childEntityGuid);
                    SrcEntityManager.GetBuffer <LinkedEntityGroup>(srcRootEntity).Add(srcChildEntity);

                    SrcEntityManager.SetComponentData(srcRootEntity, new EcsTestDataEntity {
                        value1 = srcChildEntity
                    });
                    SrcEntityManager.SetComponentData(srcChildEntity, new EcsTestDataEntity {
                        value1 = srcRootEntity
                    });

                    PushChanges(differ, patcher);

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

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

                        Assert.IsTrue(DstEntityManager.HasComponent <Prefab>(dstRootEntity));
                        Assert.IsFalse(DstEntityManager.HasComponent <Prefab>(dstRootInstance));
                        Assert.IsFalse(DstEntityManager.HasComponent <Prefab>(dstChildInstance));

                        Assert.AreEqual(dstRootInstance, DstEntityManager.GetComponentData <EcsTestDataEntity>(dstChildInstance).value1);
                        Assert.AreEqual(dstChildInstance, DstEntityManager.GetComponentData <EcsTestDataEntity>(dstRootInstance).value1);
                    }
                }
        }
 public LiveLinkScene(World destinationWorld, LiveLinkMode mode)
 {
     DestinationWorld        = destinationWorld;
     ConvertedWorld          = new World("Clean Entity Conversion World");
     LiveLinkDiffer          = new EntityManagerDiffer(ConvertedWorld, Allocator.Persistent);
     LiveLinkPatcher         = new EntityManagerPatcher(destinationWorld, Allocator.Persistent);
     _RequestCleanConversion = true;
     _LiveLinkMode           = mode;
 }
示例#10
0
        public void EntityManagerPatcher_ApplyChanges_NoChanges()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    PushChanges(differ, patcher);

                    Assert.AreEqual(0, DstEntityManager.Debug.EntityCount);
                }
        }
示例#11
0
 public void EntityManagerPatcher_ApplyChanges_CreateEntityWithDisabledComponent()
 {
     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(Disabled));
             SrcEntityManager.SetComponentData(entity, entityGuid);
             PushChanges(differ, patcher);
             Assert.IsTrue(HasComponent <Disabled>(DstEntityManager, entityGuid));
         }
 }
示例#12
0
        /// <summary>
        /// Pushes forward changes from the tracker to the applier.
        /// </summary>
        protected static void PushChanges(EntityManagerDiffer differ, EntityManagerPatcher patcher, bool fastForward = true)
        {
            var options = EntityManagerDifferOptions.IncludeForwardChangeSet;

            if (fastForward)
            {
                options |= EntityManagerDifferOptions.FastForwardShadowWorld;
            }

            using (var changes = differ.GetChanges(options, Allocator.TempJob))
            {
                patcher.ApplyChangeSet(changes.ForwardChangeSet);
            }
        }
示例#13
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());
                    }
                }
        }
示例#14
0
        public void EntityManagerPatcher_ApplyChanges_DebugNames(string srcName)
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, Allocator.TempJob))
                {
                    var entityGuid = CreateEntityGuid();
                    var entity     = SrcEntityManager.CreateEntity();
                    SrcEntityManager.AddComponentData(entity, entityGuid);
                    SrcEntityManager.SetName(entity, srcName);

                    PushChanges(differ, patcher);

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

                    Assert.AreEqual(srcName, dstName);
                }
        }
示例#15
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);
                }
        }
示例#16
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);
                }
        }
示例#17
0
        public void EntityManagerPatcher_ApplyChanges_UnidentifiedEntityReferenceBecomesNull()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, 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, patcher);

                    // Missing entity has no entityGuid, so the reference becomes null.
                    Assert.AreEqual(Entity.Null, GetComponentData <EcsTestDataEntity>(DstEntityManager, entityGuid).value1);
                }
        }
示例#18
0
        public void EntityManagerPatcher_ApplyChanges_RemoveComponent()
        {
            using (var differ = new EntityManagerDiffer(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, 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, patcher);

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

                    PushChanges(differ, patcher);

                    Assert.IsFalse(HasComponent <EcsTestData>(DstEntityManager, entityGuid));
                    Assert.AreEqual(-1, GetComponentData <EcsTestData2>(DstEntityManager, entityGuid).value0);
                }
        }
        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(SrcWorld, Allocator.TempJob))
                using (var patcher = new EntityManagerPatcher(DstWorld, 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, patcher);

                    using (var changes = differ.GetChanges(options, Allocator.TempJob))
                    {
                        patcher.ApplyChangeSet(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, patcher);

                    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, patcher);

                    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, patcher);

                    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, patcher);

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