Search Unity

Assert exceptions while using EntityManager.CopyAndReplaceEntitiesFrom

Discussion in 'Data Oriented Technology Stack' started by bvance, Sep 13, 2019.

  1. bvance

    bvance

    Joined:
    Oct 25, 2012
    Posts:
    2
    So, what I'm attempting to do with the ECS is use a 'multiple worlds' approach, where each World represents one 'puzzle game state'! Generally I have two worlds active at once: one actual 'Prime State' that represents the current configuration of game pieces, and one 'prospective state' that I use to visualize the results of trying this or that move in the UI.

    It's often necessary to revert the 'prospective' state such that it's identical to the prime state, and I figured that with DOTS, one valid way to do this would essentially be:

    1. utilize EntityManager's 'CopyAndReplaceEntitiesFrom ' method to clone the prime state into a new temporary world
    2. empty the majority of entities present in the 'prospective state', which is the one we're trying to revert (there are, however, some presentation-specific components I intend to persist!)
    3. utilize EntityManager's 'MoveEntitiesFrom' method to transfer the cloned entities into the prospective state
    4. dispose the temporary clone

    This approach appears to work perfectly! EXCEPT that after making various seemingly-valid alterations to the prime state, the 'CopyAndReplaceEntitiesFrom' method starts failing (every time!) due to a particular assert located on this line within that method:

    Code (CSharp):
    1. Unity.Entities.EntityComponentStore.AssertSameEntities(srcEntityManager.EntityComponentStore, EntityComponentStore);
    Below you can find the code snippet wherein I attempt to achieve this operation:

    Code (CSharp):
    1. using (var clone = new World(other.world.Name + "_clone_temp_" + test))
    2. {
    3.     ++test;
    4.     try
    5.     {
    6.         clone.EntityManager.CopyAndReplaceEntitiesFrom(other.world.EntityManager);
    7.     }
    8.     catch (AssertionException e)
    9.     {
    10.         Debug.LogWarning(e);
    11.     }
    12.  
    13.     // a temporary sort of hack to deal with what should happen automatically (system components not migrating across worlds!)
    14.     clone.EntityManager.RemoveComponent<RxBoardRefSystemComponent>(clone.EntityManager.UniversalQuery);
    15.     clone.EntityManager.RemoveComponent<RxHeroRefSystemComponent>(clone.EntityManager.UniversalQuery);
    16.     clone.EntityManager.RemoveComponent<RxTeamRefSystemComponent>(clone.EntityManager.UniversalQuery);
    17.     clone.EntityManager.RemoveComponent<RxCardRefSystemComponent>(clone.EntityManager.UniversalQuery);
    18.     clone.EntityManager.RemoveComponent<RxPlayRefSystemComponent>(clone.EntityManager.UniversalQuery);
    19.  
    20.     var descClone = new EntityQueryDesc()
    21.     {
    22.         None = new ComponentType[]
    23.         {
    24.             typeof(RxBoardSharedComponent),
    25.             typeof(RxHeroSharedComponent),
    26.             typeof(RxCardSharedComponent),
    27.             typeof(RxTeamSharedComponent),
    28.             typeof(RxRecordedPlaySharedComponent)
    29.         }
    30.     };
    31.  
    32.     using (var toDestroy = world.EntityManager.CreateEntityQuery(descClone).ToEntityArray(Allocator.TempJob))
    33.     {
    34.         world.EntityManager.DestroyEntity(toDestroy);
    35.     }
    36.  
    37.     using (var remap = clone.EntityManager.CreateEntityRemapArray(Allocator.TempJob))
    38.     {
    39.         var qClone = clone.EntityManager.CreateEntityQuery(descClone);
    40.  
    41.         world.EntityManager.MoveEntitiesFrom(clone.EntityManager, qClone, remap);
    42.     }
    43. }
    As you can see, I have thrown a try/catch around there to test out, an it appears that there is not any actual problem with the resultant clone (at least so far as I can tell); using this try/catch I can keep right on playing with no apparent defects! So I'm not certain whether the assert is erroneous, or if I've made some subtle mistake (in this code, or elsewhere in the project!)

    I did spend about a day poking around trying to isolate what specific thing was causing this, but after many hours of poking it seemed like almost any modification to the prime world would do it. (It was one of those frustrating debugs where I'd comment out things until I narrowed it to one apparent cause, but then later discover that practically every combination of commented/uncommented systems would trigger the same assert failure across a huge range of different cases).

    Can anybody offer any insight on this? I know the unity folks will likely want a bug report, and I'll generate one if requested! But of course, preparing the project for doing the issue report does take some time, so I'd like to get confirmation at least that it's not some known/already fixed/will fix issue first. (I'm also quite new to ECS design and concepts, so I'd welcome any experts taking time to explain to me if/why this is totally the wrong approach, or anything like that! hehe)
     
    Last edited: Sep 13, 2019
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,667
    CopyAndReplaceEntitiesFrom basically stops working the moment you Destroy an entity.

    I think it was designed to copy entities from a secondary temporary world to a primary world, not the other way around.

    A couple of examples being game object conversion and procedural generation - create a new world, procedural generate something, copy back into main world and delete the secondary world


    Improvements definitely need to be made on this though. For now I would not be wasting my time trying to get multi worlds working at the moment the way you want to.
     
  3. bvance

    bvance

    Joined:
    Oct 25, 2012
    Posts:
    2
    Well, even if I AM using just one world, I'd need to break those entities into multiple 'game boards' and write procedures for cloning one of them on demand. I was looking around for a way to essentially 'duplicate every entity except ones possessing [component x]', but I had trouble locating any kind of convenient method for 'duplicating' entities, or chunks, or really anything of that sort! Thus, I would also be interested in hearing how folks would go about 'cloning' large swathes of ecs data (that have interconnected entity references I need to update!)

    This CopyAndReplaceEntitiesFrom method fails its asserts but... actually succeeds at its task! And it seems like the Entity references in particular would be quite difficult f or me to remap 'by hand' (e.g. using some giant clone method that looks for particular archetypes and traverses the whole data structure...)
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,671
    There is a bug in the code that validates that the copy happened correctly.
    You can simply disable the assert in the package for the time being until we make the next release.
     
    bvance likes this.