Scene Management

Hello and thanks for taking the time to answer these questions!

I’d like to learn a bit more about some approaches to scene management. Often times I’ll want to have multiple scenes with different combinations of systems running i.e. Scene 1 runs systems A, B, C; Scene 2 runs systems X, Y, Z; Scene 3 runs systems B, X, Q.

Getting them to update at different times is no problem with RequireForUpdate, but often times I still want to use the other system lifecycle functions for setup, initialization, cleanup, etc.

Is the best approach typically to just do my own system management for my custom systems (e.g. have a script that creates/destroys systems based off the scene) or should I be thinking about the problem in another way?

Also, what would be the best way to just do a simple reload on a scene? In the past I’ve just nuked then recreated the World so all the proper initialization systems run and entities get recreated, but wondering if there is a better way.

Thank you!
-Johnny

1 Like

Howdy JohnnyTurbo!

I’m assuming systems here are associated with gameplay elements that can have some sort of authoring data placed in the scene? That is

  • Scene 1 has Mushrooms, Platforms, Stars
  • Scene 2 has Turtles, Pipes, Bullets
  • Scene 3 has Platforms, Pipes, Flowers

Would you mind going into a little more detail about how you intend to use the system lifecycle functions and what uncertainty you’re having? I’m not quite sure I’m clear.

I am using multiple worlds and only adding the systems I need; in order to separate my graphics and physics.

Thanks for the response @jivalenzuela
Mostly this would be for things like a generation system that runs when I load a new level or if I have a system that caches a singleton entity at the beginning of a scene so it can have that for the update loop. When launching just a single scene at a time, everything works as intended as all the OnCreate methods get called as do the systems that update once and disable themselves.

However, if I load into a new scene, those systems could already be running thus the OnCreate wouldn’t be called, or systems that disabled themselves would remain disabled. Easy enough to manually recreate or reenable the system, but this could become a bit of a mess as the amount of scenes, systems, and combinations of the two increase.

Does it make sense to have one world per scene?

Hey Johnny,

Jonas here :slight_smile: (from the twitch stream we did together)
I think (like you alluded) it could make things simpler if you look at the problem through another lens.

When thinking about systems I find it simplest to think of them as something that would do OnCreate at the start of the game, OnDestroy at the end of the game & OnUpdate on every frame inbetween.
(this is not always true, but works well as a mental model)

So when you need to do Initialization on entities you can use components or missing components to query for all entities that need initialization done on them.
Example: For every entity with X Component, add Y Component & Remove/Disable X Component.
Example: For every entity without Z Component, add Z Component
Example: For every entity with Q Component, add Entity to NativeList from MySystem & then remove Q Component.
There’s also a neat trick if you’d like to do something right after each subscene section load: Inside of a BakingSystem you can create an entity, add the correct SceneSection component to it & then add your own Component A to it.
Then in your game in ‘InitSceneSectionSystem’ you can just RequireForUpdate Component A & in the Update do anything with Component A or the SceneSection & then disable the entity.

When you need to do Cleanup on entities you can use ICleanupComponent which allows you to do some cleanup after something destroyed the entity.
In some cases you might want to do something before the entities from a scene get destroyed. This is quite easy to achieve by adding some custom scene unloading component instead of straight removing the RequestSceneLoaded component from the SceneSection.

I hope this is relevant or at least a bit useful. Wasn’t sure if I actually understood the question 100% hah.

To answer your second question:
You can load a scene or scenesection by adding the RequestSceneLoaded to the correct scene or scenesection entity. You can even make these scene entities yourself afaik.
To unload them you just remove the RequestSceneLoaded from that same entity.
So to reload a scene you’d remove the component, then check some data (depends on your use case) to see if the scene is unloaded & then add it again afterwards.
There’s also the SceneSystem that you can use, but I prefer working with the componentdata.

2 Likes

Hey @Jonas_DM great to hear from you and hope you’ve been doing well!

Thanks for the suggestion these all seem like good options to play around with. I would definitely like to experiment with the SceneSection as I’ve never done anything with that yet.

I know your game used subscenes quite heavily and that there are a lot of powerful things you can do with them, so I’d like to do more than just the basics with them, and these seem like awesome things to test out.

All the best and hope to see you at GDC again next year :wink:

1 Like

I’m currently trying to wrap my head around scene management in ecs. Figured I’d post here rather than make a new thread. Having two scene management systems is breaking by brain.

  1. how does my spawning system know which subscene to put instantiated entities in? Systems don’t seem to be associated with any scene (and from the comments above sounds like I should think of them independent of scenes). I guess its because the prefab was set in an authoring component that lives in the subscene (which seems like only a loose association)
  2. I tried creating an entity from code only, it goes into the top level of the hierarchy, under no subscene. Is there a way to put it in a subscene?
  3. when I want to change scenes using the old scene manager, should I first unload my subscenes and clean up any non-subscene parented entities myself, then run the old scene manager?
  4. since systems are always active - to detect a scene change (using the old scene manager) in ECS, I suppose I’d have a ‘newScene’ tag component on an entity in a new scene, do something in a system.update once, then remove the component?

Thank you

This then results in the prefab being baked in the subscene as a prefab belonging to the subscene. And consequently, it receives the SceneTag shared component associated with that subscene. Note: “SceneTag” is a misleading name, because the component actually contains data.

The SceneTag component is one of the requirements. There might be more, but I don’t remember. My use case was ensuring the instantiated prefab was kept alive when the subscene unloaded, so I removed the SceneTag.

Subscenes are managed by Subscene MonoBehaviours. The MonoBehaviour will automatically close the subscne on scene change when it is destroyed. You’ll still need to do something about entities that were created procedurally.

That’s one way to do it. I keep what is effectively a singleton and have a scene management system that handles switching scenes and reports scene state to that singleton. It reports the new scene name, the previous scene name, and a bool specifying if this is the first frame of the new scene.

2 Likes

Putting a dynamically created entity into a loaded subscene is indeed possible (Like Latios mentioned).
But it needs both the SceneTag & SceneSection SharedComponents as far as I’m aware.

1 Like