Restart ecs simulation?

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
2 Likes

I am using DefaultWorldInitialization to do this for me. You still need to dispose old world and scenes.

World.Active.Dispose(); 
SceneManager.LoadScene("Intro", LoadSceneMode.Single);
DefaultWorldInitialization.Initialize("Default World", false);
1 Like

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.

using Unity.Entities;
using UnityEngine.SceneManagement;

namespace Latios
{
    internal struct LatiosSceneChangeDummyTag : IComponentData { }

    [AlwaysUpdateSystem]
    internal class DestroyEntitiesSceneChangeSystem : SubSystem
    {
        private EntityQuery destroyQuery = null;

        protected override void OnCreate()
        {
            EntityQueryDesc desc = new EntityQueryDesc
            {
                All = new ComponentType[]
                {
                    typeof(LatiosSceneChangeDummyTag)
                },
                None = new ComponentType[]
                {
                    typeof(SingletonTag),
                    typeof(DontDestroyOnSceneChangeTag)
                }
            };
            destroyQuery                = GetEntityQuery(desc);
            SceneManager.sceneUnloaded += RealUpdateOnSceneChange;
        }

        protected override void OnUpdate()
        {}

        private void RealUpdateOnSceneChange(Scene unloaded)
        {
            if (unloaded.isSubScene)
                return;

            //Why are add and remove inconsistent?
            EntityManager.AddComponent(EntityManager.UniversalQuery, typeof(LatiosSceneChangeDummyTag));
            EntityManager.DestroyEntity(destroyQuery);
            EntityManager.RemoveComponent<LatiosSceneChangeDummyTag>(EntityManager.UniversalQuery);
        }
    }
}
2 Likes

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

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.

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

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

Yes, but also all systems and whatever other world data there might be.

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

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.