dima dima - 8 days ago 4x
C# Question

Unity game manager. Script works only one time

I'm making simple game manager. I have a script, which will be accessible from all scenes in the game. And I need to check values of it's variables after loading new scene. But my code works only one time after starting simulation and object with this script exists in all scenes. What is wrong? Why it doesn't whork after loading a new scene?


In every Unity project you must have A PRELOAD SCENE.

It is very confusing that Unity does not have a preload scene "built-in". (They will add it in the future.)

To repeat, you literally MUST have a preload scene.

It's just that simple.

This is the SINGLE GREATEST MISUNDERSTANDING for new programmers trying Unity!

I want to emphasize this is ridiculously easy: there's nothing to it. The fact that you see many incredibly complex, ridiculous, posts about constructing quasi-"singletons" and other bizarre approaches to this non-issue, is really just one of the weirdest things in the game industry. It's just this easy - one click - let's walk through it in detail including handy tips.

Step 1.

Make a scene named "preload". It must be scene 0 in Build Manager.

enter image description here

Step 2.

In the "preload" scene simply have an empty GameObject called say "_app". Simply put DontDestroyOnLoad on '_app'.


This is the only place in the whole project you use DontDestroyOnLoad.

It really is that simple.

enter image description here

(In that image example, the developers have made a trivial DDOL script. Put it on the "__app" object. This is much more sensible that "including the DDOL line somewhere in one of your other scripts".)

Step 3

You must, and can only, put your "general" behaviors ... things like sound effects, scoring, etc ... on "_app".

It's just that simple.

(In the image example above, notice say "Iap" (in app purchase) and so on. All of the "general needed behaviors" like sound effects and so on, are right there on that object.)

To repeat. Regarding your "general" behaviors. (Sound effects, scoring, etc.) These CAN ONLY GO on a game object in the preload scene.

This is not optional: there is no other alternative.

You're done.

It is honestly that simple.

Honest: it's just that easy. There is literally nothing to it!

Many engineers coming from other genres take forever to realize it is this simple, because it is so simple and easy it "can't be true". To repeat - the whole problem is that (bizarrely) Unity just plain forgot to "build-in" a preload scene. So for that reason, you simply have to click to add one (adding DDOL to it).

Now during development:

Always start your game from Preload scene.

It's that incredibly simple.

(Note. Your app will almost certainly have "early" scenes. For example "splash screen" or a "menu". You can not use "splash" or "menu" as the preload scene. You have to literally have a preload scene. The preload scene will then load your splash-scene, menu-scene, or whatever you wish.

You then have the problem of, quite simply, finding say "SoundEffects" or "GameManager" from any script in any of your scenes.

Fortunately it is dead easy, it is one line of code.

It is a non-issue:

Sound sound = Object.FindObjectOfType<Sound>();
Game game = Object.FindObjectOfType<Game>();

Do that in Awake for any script that needs it.

It's honestly that simple. That's all there is to it.

Sound sound = Object.FindObjectOfType<Sound>();

Tremendous confusion arises because of the 100s of absolutely wrong code examples seen online. Also, new Unity engineers "cannot believe" it is this easy!

It really is this easy - honest!

It's totally bizarre that Unity forgot to add a built-in "preload scene" - somewhere to attach your systems like SoundEffects, GameManager, etc. It's just one of those weird thing about Unity. So, the first thing you do in any Unity project is just click once to make a preload scene.

DylanB asks: During development it's quite annoying that you have to click to the preload scene every time before you click "Play". Can this be automated

Sure, every team has a different way to do this. Here's a trivial example:

// this should run absolutely first; use script execution order to do so.
// (of course normally never, ever use the script execution order feature,
// this is an unusual case - just for development.)
public class DevPreload:MonoBehaviour
 void Awake()
  GameObject check = GameObject.Find("__app");
  if (check==null)
   { UnityEngine.SceneManagement.SceneManager.LoadScene("_preload"); }

But don't forget, "what else can you do?" Games have to start from a preload scene. What else can you do, other than go to the preload scene, to start the game? You may as well ask "it's annoying launching Unity to run Unity - how to avoid launching Unity?" Games simply, of course, absolutely have to start from a preload scene - how else could it be? So sure, you have to "click to the preload scene before you click Play" when working in Unity - how else could it be?