Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

It makes playtesting easier and lets you separate out the player from the transitions, which is valuable once you have a complex class.

When I'm testing a level, I drop the Player prefab there, and that's fine. But if I compile the game with it there, and I load into that level from somewhere else in the game, there will suddenly be two Player objects. So I'd either have to make a bunch of logic for figuring out which Player is the duplicate one and deleting it before any of the Awake() hooks get called to register inventory and UI and whatnot, or go through every level (aside from the first one) and disable the Player object in it.

I also can't put it in the main menu, because if I stop mid-level and go back to the main menu, there will be two Players there, so I'd need a scene with only the Player object that will immediately load the main menu and take the Player with it.

There are other advantages, but that was the big one.

(1 edit) (+1)

Ah yes. I completely forgot about playtesting! Especially if you have many, many levels. Scriptable objects do make everything easier anyways. Thanks for the reply! 😁

You can solve this problem quite easily with a "launch" scene. 

Put all your DontDestroyOnLoad objects (and singletons) in that launch scene. To enter playmode in a specific scene, you would have a component (or editor script) that additively loads the launch scene content when entering playmode. Any timing issues need to be relaxed by invoking events (Action, Func) that interested components register with.

If a DontDestroyOnLoad object needs to reset its state, eg when changing scenes, you hook into SceneManager.sceneLoaded or similar events and perform your task. And then signal a "ready" event.

In your case you've also had dependent code in GlobalController's Awake. This has to be refactored. It's never a good idea to call other components from Awake, that needs to be deferred to Start or OnEnable. In Awake you should only ever get, find or create references but not accessing/calling them to avoid these initialization order issues.

Since you have a class called "GlobalController" you could as well rename it to "EverythingEverywhereAllAtOnce" and it'll still carry the same meaning. If you value tradition, suffix it with "Controller" or "Manager" or similarly broad, thus meaningless, nouns. ;)

Meaning: this class has no clearly defined purpose and thus it came to do all the things in Awake that it shouldn't have.