Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

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:
    146
    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,592
    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,647
    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.
     
    Esteban-Gallardo likes 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.         }
     
    GuiVio, CheMBurN, tommox86 and 3 others like this.
  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