I’m trying to figure out the best or recommended way to handle scene transitions when using entities, particularly when it comes to cleaning up instantiated entities that don’t belong to a subscene.
Suppose for instance that I have two scenes - a main menu, and the game - and that I want to transition back and forth between them.
In mono-behavior land we’d simply use SceneManager.LoadScene(“Game”) to go from the menu to the game, and vice versa to get back. Then we just have to be wise about when we call it and handling all of the OnDisable and OnDestroy events.
In entities land extra work is involved, as changing scenes doesn’t automatically destroy all entities due to them belonging to Worlds rather than to a scene. Subscenes partly address the issue via SceneSystem.UnloadScene, but this will only destroy the entities which belonged to that subscene - not any additional entities which were instantiated during gameplay.
This means that we need to have a separate process for removing any of these instantiated entities when we unload the scene. EntityManager.DestroyAndResetAllEntities() and World.Dispose() look like they have some potential, but I’m not clear on when and how they should be used, or even if they should be used for this purpose - for instance using them within system updates seems to be a bad idea (or not possible in the case of World.Dispose()).
I guess my questions are:
- What are the best or at least some good ways of cleaning up instantiated entities when unloading a scene?
- Is there a particular time in a frame when this should or shouldn’t be done - e.g. should it be within a specific system group, does it matter which command buffer we use, are there times where we can outright call a catch all function like EntityManager.DestroyAndResetAllEntities()?
- Should this be done with a dedicated system (e.g. a “Delete all entities” system which queries and destroys all entities, perhaps based on a tag or the presence of a singleton), or are there built in functions better suited to the task?
- What about scenarios where we want to keep some entities around regardless of the scene - aka something akin to DontDestroyOnLoad?
My hope is that there’s a simple and elegant way to handle it that will work for 99% of scenarios. The ideal scenario would be something that can be encapsulated in a single method, a sort of “World.Unload()” for lack of a better term.
I suspect doing it with a system at a certain time in the frame (the end? the beginning?) is the “right way”, but it’s a bit confronting that this will likely mean waiting one or more frames and polling for completion before moving on to the next scene, which adds complexity.