Search Unity

Restart ecs simulation?

Discussion in 'Entity Component System' started by Bas-Smit, Sep 24, 2019.

  1. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274
    Is there an easy way to complete restart an ecs simulation? I tried variations on the following without success...

    World.Active.EntityManager.DestroyEntity(World.Active.EntityManager.GetAllEntities());
    World.Active.Dispose();
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single);


    Thanks, Bas
     
    shotoutgames and NotaNaN like this.
  2. swejk

    swejk

    Joined:
    Dec 22, 2013
    Posts:
    20
    I am using DefaultWorldInitialization to do this for me. You still need to dispose old world and scenes.
    Code (CSharp):
    1.    
    2. World.Active.Dispose();
    3. SceneManager.LoadScene("Intro", LoadSceneMode.Single);
    4. DefaultWorldInitialization.Initialize("Default World", false);
    5.  
     
    NotaNaN likes this.
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    I recently blueprinted a full scene management framework so I won't be using this code much longer. I don't keep state in systems, so I don't actually dispose the world and create a new one.
    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine.SceneManagement;
    3.  
    4. namespace Latios
    5. {
    6.     internal struct LatiosSceneChangeDummyTag : IComponentData { }
    7.  
    8.     [AlwaysUpdateSystem]
    9.     internal class DestroyEntitiesSceneChangeSystem : SubSystem
    10.     {
    11.         private EntityQuery destroyQuery = null;
    12.  
    13.         protected override void OnCreate()
    14.         {
    15.             EntityQueryDesc desc = new EntityQueryDesc
    16.             {
    17.                 All = new ComponentType[]
    18.                 {
    19.                     typeof(LatiosSceneChangeDummyTag)
    20.                 },
    21.                 None = new ComponentType[]
    22.                 {
    23.                     typeof(SingletonTag),
    24.                     typeof(DontDestroyOnSceneChangeTag)
    25.                 }
    26.             };
    27.             destroyQuery                = GetEntityQuery(desc);
    28.             SceneManager.sceneUnloaded += RealUpdateOnSceneChange;
    29.         }
    30.  
    31.         protected override void OnUpdate()
    32.         {}
    33.  
    34.         private void RealUpdateOnSceneChange(Scene unloaded)
    35.         {
    36.             if (unloaded.isSubScene)
    37.                 return;
    38.  
    39.             //Why are add and remove inconsistent?
    40.             EntityManager.AddComponent(EntityManager.UniversalQuery, typeof(LatiosSceneChangeDummyTag));
    41.             EntityManager.DestroyEntity(destroyQuery);
    42.             EntityManager.RemoveComponent<LatiosSceneChangeDummyTag>(EntityManager.UniversalQuery);
    43.         }
    44.     }
    45. }
     
    NotaNaN and Bas-Smit like this.
  4. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274

    Thanks, this works for me, I just use
    World.DisposeAllWorlds();
    to get rid of our streaming worlds
     
  5. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    302
    I'm trying to destroy all my worlds without the restart.

    Just calling
    World.DisposeAllWorlds();
    gives me this error (and a similar one for PresentationSystemGroup):

    Does anyone know how to unregister the system groups from the ScriptBehaviourUpdateOrder or a better way to achieve the goal of destroying the worlds? I don't want to change scene, I just want to destroy the worlds and that's it.

    Code (CSharp):
    1. InvalidOperationException: Unity.Entities.SimulationSystemGroup has already been destroyed. It may not be used anymore.
    2. Unity.Entities.ComponentSystemBase.CheckExists () (at Library/PackageCache/com.unity.entities@0.1.1-preview/Unity.Entities/ComponentSystem.cs:323)
    3. Unity.Entities.ComponentSystemBase.ShouldRunSystem () (at Library/PackageCache/com.unity.entities@0.1.1-preview/Unity.Entities/ComponentSystem.cs:339)
    4. Unity.Entities.ComponentSystem.InternalUpdate () (at Library/PackageCache/com.unity.entities@0.1.1-preview/Unity.Entities/ComponentSystem.cs:783)
    5. Unity.Entities.ComponentSystemBase.Update () (at Library/PackageCache/com.unity.entities@0.1.1-preview/Unity.Entities/ComponentSystem.cs:284)
    6. Unity.Entities.ScriptBehaviourUpdateOrder+DummyDelegateWrapper.TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.1.1-preview/Unity.Entities/ScriptBehaviourUpdateOrder.cs:144)
     
  6. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274
    By destroying your world you mean destroy all entities?

    EntityManager.DestroyEntity(EntityManager.GetAllEntities());


    removing systems:

    ComponentSystemGroup.RemoveSystemFromUpdateList(ComponentSystemBase sys)


    Find your system to remove:

    World.GetExistingSystem(typeof(system))
     
  7. jdtec

    jdtec

    Joined:
    Oct 25, 2017
    Posts:
    302
    Yes, but also all systems and whatever other world data there might be.

    I found a way to make it work. I call:

    World.DisposeAllWorlds ();
    DefaultWorldInitialization.Initialize ("Default World", false);


    As has been suggested, however, I also needed to call it from a coroutine that waits until the end of the frame.