Search Unity

Resolved Reset ECS world and jobs to start fresh again

Discussion in 'Entity Component System' started by Esteban-Gallardo, Nov 21, 2022.

  1. Esteban-Gallardo

    Esteban-Gallardo

    Joined:
    Feb 19, 2013
    Posts:
    47
    I'm trying to develop a physics based destruction mini-game and I've been stuck for a couple of days when I'm trying to reload the whole scene to start fresh again.

    Here is the video of what happens:



    I'm using several system using jobs to detect collision like this:

    Code (CSharp):
    1. [System.Serializable]
    2.     public partial class CollisioWallToActorDetectionSystem : SystemBase
    3.     {
    4.         private StepPhysicsWorld stepPhysicsWorld;
    5.         private EndSimulationEntityCommandBufferSystem commandBufferSystem;
    6.  
    7.         protected override void OnCreate()
    8.         {
    9.             stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    10.             commandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    11.         }
    12.  
    13.         protected override void OnUpdate()
    14.         {
    15.             var jobHandle = Dependency;
    16.             Dependency.Complete();
    17.  
    18.             var applicationJob = new ApplicationWallToRagdollJob
    19.             {
    20.                 actorCollider = GetComponentDataFromEntity<RagdollComponent>(),
    21.                 wallCollider = GetComponentDataFromEntity<WallColliderData>()
    22.             };
    23.  
    24.             Dependency = applicationJob.Schedule(stepPhysicsWorld.Simulation, Dependency);
    25.                commandBufferSystem.AddJobHandleForProducer(Dependency);
    26.         }
    27.  
    28.         [BurstCompile]
    29.         private struct ApplicationWallToRagdollJob : ICollisionEventsJob
    30.         {
    31.             public ComponentDataFromEntity<RagdollComponent> actorCollider;
    32.             public ComponentDataFromEntity<WallColliderData> wallCollider;          
    33.  
    34.             public void Execute(CollisionEvent triggerEvent)
    35.             {
    36.                 if (wallCollider.HasComponent(triggerEvent.EntityA))
    37.                 {
    38.                     if (actorCollider.HasComponent(triggerEvent.EntityB))
    39.                     {
    40.                         WallColliderData wall = wallCollider[triggerEvent.EntityA];
    41.                         wall.Destroy = true;
    42.                         wallCollider[triggerEvent.EntityA] = wall;
    43.                     }
    44.                 }
    45.  
    46.                 if (wallCollider.HasComponent(triggerEvent.EntityB))
    47.                 {
    48.                     if (actorCollider.HasComponent(triggerEvent.EntityA))
    49.                     {
    50.                         WallColliderData wall = wallCollider[triggerEvent.EntityB];
    51.                         wall.Destroy = true;
    52.                         wallCollider[triggerEvent.EntityB] = wall;
    53.                     }
    54.                 }
    55.             }
    56.         }
    57.     }
    So, what should I do to start clean? I've tried the few things I've found on Internet unsuccessfully and I've run out of options.
     
  2. msfredb7

    msfredb7

    Joined:
    Nov 1, 2012
    Posts:
    163
    I've had issues myself in the past with clearing a world and reusing it. It looked like a use case Unity had not tested properly. I did not find a solution, but here's the workaround I use:

    Create a brand new world and dispose of the previous one
    . This brings a couple of challenges because you have to rebind the world to the player loop, but at least it works.
     
    Esteban-Gallardo likes this.
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,770
    If you destroy all entities besides prefabs, and reinstantiate them again, tha should solve the problem.
     
    Esteban-Gallardo likes this.
  4. Esteban-Gallardo

    Esteban-Gallardo

    Joined:
    Feb 19, 2013
    Posts:
    47
    Thanks a lot!! It worked. The code looks like this to reset. I don't even need to reload the scene in order to start fresh:

    Code (CSharp):
    1.         public void DestroyAllEntities()
    2.         {
    3.             World.DefaultGameObjectInjectionWorld.EntityManager.DestroyEntity(World.DefaultGameObjectInjectionWorld.EntityManager.UniversalQuery);
    4.             World.DisposeAllWorlds();
    5.             DefaultWorldInitialization.Initialize("Base World", false);
    6.             ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop(World.DefaultGameObjectInjectionWorld);
    7.         }
    8.  
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    World.DefaultGameObjectInjectionWorld.EntityManager.DestroyEntity(World.DefaultGameObjectInjectionWorld.EntityManager.UniversalQuery);

    You don't need this, you're disposing world so it'll clean up by itself. This will just slow it down.
     
    nicloay and Esteban-Gallardo like this.
  6. Esteban-Gallardo

    Esteban-Gallardo

    Joined:
    Feb 19, 2013
    Posts:
    47
    For the future programmers who look into reseting the ECS system this is the final solution that work for me at the moment I'm posting:

    Code (CSharp):
    1.         public void CleanAndRestartECS()
    2.         {
    3.             var defaultWorld = World.DefaultGameObjectInjectionWorld;
    4.             defaultWorld.EntityManager.CompleteAllJobs();
    5.             foreach (var system in defaultWorld.Systems)
    6.             {
    7.                 system.Enabled = false;
    8.             }
    9.             defaultWorld.Dispose();
    10.             DefaultWorldInitialization.Initialize("Default World", false);
    11.             if (!ScriptBehaviourUpdateOrder.IsWorldInCurrentPlayerLoop(World.DefaultGameObjectInjectionWorld))
    12.             {
    13.                 ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop(World.DefaultGameObjectInjectionWorld);
    14.             }  
    15.             SceneManager.LoadScene("Game", LoadSceneMode.Single);
    16.         }
     
  7. Malja88

    Malja88

    Joined:
    May 30, 2022
    Posts:
    2
    But how You destroy entities with certain tag? Like I don't need to destroy some entities after restarting scene