Singleton (888036)

I have a LevelManager script

public static LevelManager Instance {get;; private set;}
public GameObject[ ] Levels;

I need to access it in other scenes but its not finding it but I’m not getting any errors
LevelManager.Instance.Levels[currentLevel]

How do I access the LevelManager.Instance in scripts that are in different scenes?

You’re a bit “off” on the singleton concept with the above… looks more like a resource cache or locator… check some tutorials, or here are two super-simple examples for game manager-esque constructs:

ULTRA-simple static solution to a GameManager:

OR for a more-complex “lives as a MonoBehaviour” solution…

Simple Singleton (UnitySingleton):

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

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

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.

And if you really insist on barebones C# singleton, here’s a Highlander:

What is this then? Thats what my code is.

https://gamedevbeginner.com/singletons-in-unity-the-right-way/#:~:text=Generally speaking, a singleton in,or to other game systems.

It most probably is singleton. However, you didn’t post enough code to see if it is working as it should. Usually, you create a new instance when accessing it when the instance is null. But assigning the instance in awake can be easier in some situations and would be OK if you don’t ship the code.

If you have the instance in the first scene, but it is lost after loading a new scene, you need to make sure that it survives scene loading like this: DontDestroyOnLoad(this.gameObject);
Note that this code compiles only if called from within a MonoBehaviour. Note that this works only if the game object is at the root level of a scene (AFAIK).

[code=CSharp]using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class LevelManager: MonoBehavior
{
  public static LevelManager Instance {get; private set;}
public Button[]  levels;

private void Awake()
{
    // If there is an instance, and it's not me, delete myself.
  
    if (Instance != null && Instance != this)
    {
        Destroy(this);
    }
    else
    {
        Instance = this;
    }

DontDestroyOnLoad(this.gameObject);
}


}

How do access the levels array in a script thats in another scene?

Your “Level Manager” doesn’t manage level data. Instead it holds references to buttons which most probably do not exist after switching scenes…

Instance is probably not null (if the script was attached to any loaded game object) but all the buttons are “null”.

That’s not a thing… scripts only ARE in the scene, otherwise they don’t exist.

If you just need an on-demand loader / locator for this list of GameObjects, you could use something like a ScriptableObject.

This is the one I use to organize my groups / collections of prefabs:

https://gist.github.com/kurtdekker/68b3fd9d4202888b4afc17b32eed6790

Here is my collection of small green trees in Jetpack Kurt:
8285391--1085913--Screen Shot 2022-07-16 at 4.03.36 PM.png

Yes all the buttons are null when this LevelManager is put into a new scene. So your saying there is no way to access the level buttons in a different scene?

I need access to the buttons so I can “cross off” the ones the player has already completed and not allow them to re-select those levels again. I havn’t looked at scriptable object yet.

Things in another scene that is not loaded essentially do not exist.

Is that other scene loaded? If so, then a singleton pattern to locate it like you have above will work just fine.

If you want a bunch of buttons to be available across a bunch of scenes, you could put those buttons into their own scene and additively load them.

This is something else entirely and involves load/save properties. DO NOT combine the presentation of what the save state is (eg, what levels are done / not done) with the actual state stored, which is a simple load/save artifact.

Load/Save steps:

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

An excellent discussion of loading/saving in Unity3D by Xarbrough:

https://discussions.unity.com/t/870022/6

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

If you want to use PlayerPrefs to save your game, it’s always better to use a JSON-based wrapper such as this one I forked from a fellow named Brett M Johnson on github:

https://gist.github.com/kurtdekker/7db0500da01c3eb2a7ac8040198ce7f6

Do not use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide


Additive scene loading is one possible solution:

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

My level select has a lot of UI and buttons, if I do the additive loading won’t all the UI elements also go into the new scenes?