Hello,
I came across the same problem recently. Also came to the same conclusion to use additive scenes in first sight. Mainly because I’ve seen that in companies.
Though I don’t really use an “entry point”, mainly because I want to be able to launch every scene in dev. Not having to launch it from the splash each time I want to check something.
So I think it’s not the only solution to manage this and wanted to discuss about it.
Taking my thought and a bit of GPT I have 3-4 solutions:
1. BasicScene
Use a basic scene that contains only the DontDestroyOnLoad centralized elements
This solution is the one I’m using now. Basically my structure is:
- Splash
- Basic Scene
- Lobby
- Scene1
- Scene2
- …
Splash is independant, it’s intend to load the BasicScene + Lobby, then BasicScene kill itself after having initialized all DontDestroyOnLoad components (because Unity is not happy with inconsistent lights settings). So well you can consider it as the “entry point”.
If I’m in dev mode, I can load independantly for exemple BasicScene + Scene1.
My hierarchy looks like that:
BasicScene
- GameManager => DontDestroy
- Network
- … all important stuff
- Players => DontDestroy
- Player1 (onthefly)
- Player2 (onthefly)
Lobby / Scene1 / Scene2 / …
- World
- … all your worlds prefabs
- Lobby (Pure context code)
Though I have some problems with the reference right now on game start. Need to ensure the BasicScene is loading first. Also seen a comment saying something around “If it’s common, don’t put in a scene” here Could the order of scene loading in the editor be made deterministic?
Well I am also using static .Instance for the GameManager and it seemed to work in another project so I have to double check. Imo, this solution make sens matters of infrastructure but it is really? More in a multi-dev way as if I load a scene I expect it to be full autonomous as a dev.
2. Initializer + Prefabs
Pointed by GPT as the “best” solution. Basically you put an “Initializer” script in a “Initializer” GameObject with two prefabs as reference (which is your important stuff, here is “GameManager” and “Players”). You put this in every of your scene and check if the prefabs have been initialized in the hierarchy or not.
So basically:
Lobby / …
- Initializer
- => ref GameManager prefab
- => ref Players prefab
- World
- Lobby
then
- GameManager
- Players
- World
- Lobby
I didn’t test it so I don’t know if some problems would get along but it seems to make sens for me. Probably need to AutoKill Initializer so you don’t stack 24 Initializer in your root. This is a bit redundant.
3. AutoKill
Basically I just though about adding something like a script AutoKiller in the GameManager and Players. It’s a bit the same as solution 2 but you don’t necessarly need to create prefabs.
If it find in the hierarchy a same name / same tagged / or same script, it destroy itself in the load. Something like:
public class Autokill : MonoBehaviour {
void Start {
// Or check for a specific tag in hierarchy
if (transform.root.GetComponentsInChildren<GameManager>() > 0){
Destroy(gameobject);
}
}
}
(This could be a bit more generalized to use a referenced class in inspector or a tag)
Be careful using gameobject name comparison because it is error prone.
Probably a bit redundant as solution 2.
Well in any way, the main point is to avoid having doubles and useless reinitialization. And well errors…
Still searching for the best solution among 1. and 2.
Now about the author @JanZagar question on menu, Imo, (especially if we keep solution 1. with additive scenes) I think it depends on the menu. 3 exemples:
- Introduction Menu : If it’s just a scene to load UI as a “hub”, or a functionality only in this scene, (for me it’s the lobby scene that contains a menu to connect to a server), I think it make sens to put it in the scene itself => Menu = One associated scene
- Option/Exit Menu : Goes in the “Players” (holders of each Player instance) if you want to have one menu for everyone. Or in the “Player” if you want to be able to pause independantly on local multiplayer
- Inventory Menu : Goes in the “Player” prefab (especially if you have local multi with new input system)