Returning to main menu scene with persisting game objects

I have a project I’m close to completing with four separate scenes - three levels and a main menu (index 0). My main menu, pause menu and door controller (loads specified scene on trigger) are all working nicely, but I have one hitch - the ‘main menu’ button in my pause menu is giving me hell.

Currently I’m using scene management build index to return to scene 0 on click, but I’m getting an ungodly amount of null ref exceptions thanks to the game objects which persist between scenes after the main menu.

Some of these objects are instantiated when scene 1 is loaded from the main menu, others exist in scene 1 and use DontDestroyOnLoad & gameObject array to ensure no more than one instance exists in a scene at a time (ex countdown timer). I’m aware this isn’t the greatest practice.

What would be the best/most efficient way to disable these persistent objects when the pause menu on click logic is called? I’ve tried setting an array of game objects to disabled (SetActive(false)), but even though these components are inactive the code attached to them is still throwing null ref errors.

I’m (foolishly) not using object pooling to control instantiated/persistent objects and unfortunately I don’t have enough time before my deadline to start. Short of sticking disabled instances of these persistent game objects in my menu scene how can I tackle this?

I’ll add any relevant pre-existing code if necessary in a few hours, but I’d mostly just like a logic walkthrough/workaround.

There is nothing wrong with this practice but you need to get the lifetimes / lifecycles correct.

One solution may be to break your scene into multiple scenes all additively loaded, and then only unload SOME of the scenes. Here’s some notes on that concept:

https://discussions.unity.com/t/820920/2
https://discussions.unity.com/t/820920/4

https://discussions.unity.com/t/824447/2

A multi-scene loader thingy:

https://pastebin.com/Vecczt5Q

My typical Scene Loader:

https://gist.github.com/kurtdekker/862da3bc22ee13aff61a7606ece6fdd3

Other notes on additive scene loading:

https://discussions.unity.com/t/805654/2

Timing of scene loading:

https://discussions.unity.com/t/813922/2

Also, if something exists only in one scene, DO NOT MAKE A PREFAB out of it. It’s a waste of time and needlessly splits your work between two files, the prefab and the scene, leading to many possible errors and edge cases.

Two similar examples of checking if everything is ready to go:

https://discussions.unity.com/t/840487/10

https://discussions.unity.com/t/851480/4

As for the nullrefs, those are always fixed the same exact way:

How to fix a NullReferenceException error

https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

Steps to success:

  • Identify what is null
  • Identify why it is null
  • Fix that

As for the lifetimes / lifecycles, my policy is to NEVER put something in a scene if it is expected to last more than the lifetime of the scene. Instead, I use this construct:

Simple Singleton (UnitySingleton):

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

public void DestroyThyself()
{
   Destroy(gameObject);
   Instance = null;    // because destroy doesn't happen until end of frame
}

There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

1 Like