Best way to use Singletons in unity [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am wondering which is the right way to use singleton instance: when I create a singleton Class called "Manager" and it contains an int variable called "value" and I have a another class called "A"...
//singleton class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Manager : MonoBehaviour {
public static Manager Instance{ set; get;}
public int value;
private void Awake () {
if (Instance == null) {
Instance = this;
DontDestroyOnLoad (this.gameObject);
} else {
Destroy (gameObject);
}
}
}
So inside my A class I can make a instance of the singleton like this:
// example pseudo code
public class A
{
// First
// using as a global variable
Manager manager;
//------------------------------------
Public void tstOne(){
// First
// using that global variable
manager.Instance.value = 0;
// Second
// or this way
Manager.Instance.value = 0;
}
Public void tstTwo(){
// First
// using that global variabl
manager.Instance.value = 1;
// Second
// or this way
Manager.Instance.value = 1;
}
}
So my problem is - should I create A global instance and then use that instance like in first one or should I use the second example?
Are they both are same in terms of memory consumption and efficiency?
Or is there another way to use singletons?

I confirm Ruzihm answer (and I also agree with derHugo comment, I personally prefer SO and reference them where required. Much cleaner than Singleton or DI direct approach).
To be specific accessing the instance member manager.Instance.value is slower and also requires further memory allocation on the heap so it hurts both memory usage and speed performance. (Very small performance issues, but still.)
There's also further room of improvement on the singleton, especially if you do not require it to derive from MonoBehaviour.
You can:
Make sure it is build also if you forget to add it in the scene
Make it thread safe (not required by unity, usually)
Implement it lazily (means you create it only when you need it)
Also, as a general rule is better to seal the singleton class for improved performance (again really slight improvement when you use virtual methods)
This would be the implementation (considering you use the Manager as helper instance and YourManagerMono if you require monobehaviour logic:
public class YourManagerMono : MonoBehaviour
{
}
public sealed class Manager
{
private static readonly Manager instance = new Manager();
//use a gameobject to relate it in the scene
private YourManagerMono monoManager;
public static Manager Instance => instance;
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Manager() {}
private Manager()
{
//find or create a manager
monoManager = GameObject.FindWithTag("Manager").GetComponent<YourManagerMono>();
if (monoManager == null)
{
monoManager = new GameObject().AddComponent<YourManagerMono>();
monoManager.gameObject.tag = "Manager";
Object.DontDestroyOnLoad(monoManager.gameObject);
}
}
}
A great article about singleton implementation for C# by Jon Skeet (I used implementation 4).
EDIT:
Again I agree with derHugo (in the new comment on this answer). My example is used to show an interesting prospective and to offer as much performance as I can, but if you just require a Monobehaviour with just point 1 and 3 you may go ahead with a generic implementation of singleton from Unify Community (just remember to set the end class as sealed to help the compiler).

Instance is a static field so you should get your references to the singleton with Manager.Instance.
Manager.Instance is a globally accessible instance because it's public static. There's no such thing as a global variable in C#.
Accessing a static field directly by the class name is definitely better than making a second instance as a field in A and then accessing the static instance using it.

For Singletons that you want to exist in one scene only, I use:
public class SceneSingleton<T> : MonoBehaviour
where T : SceneSingleton<T>
{
static T s_instance = null;
public static T Instance
{
get
{
if (s_instance == null)
{
s_instance = Object.FindObjectOfType<T>();
}
return s_instance;
}
}
}
And then inherit your class from it, like this:
public class MyManager : SceneSingleton<MyManager>
If you need your singleton to stay alive between all scenes, try to use this:
public class GlobalSingleton<T> : MonoBehaviour
where T : GlobalSingleton<T>
{
static T s_instance = null;
public static T Instance
{
get
{
if (s_instance == null)
{
GameObject prefab = Resources.Load(typeof(T).Name) as GameObject;
if (prefab == null || prefab.GetComponent<T>() == null)
{
Debug.LogError("Prefab for game manager " + typeof(T).Name + " is not found");
}
else
{
GameObject gameManagers = GameObject.Find("GameManagers");
if (gameManagers == null)
{
gameManagers = new GameObject("GameManagers");
DontDestroyOnLoad(gameManagers);
}
GameObject gameObject = Instantiate(prefab);
gameObject.transform.parent = gameManagers.transform;
s_instance = gameObject.GetComponent<T>();
s_instance.Init();
}
}
return s_instance;
}
}
protected virtual void Init()
{ }
}

Related

Trying to change BattleState globally

Hi I'm a completely new to coding and am trying to create a card game. I've watched some tutorials and tried to take things into my own hands but cant seem to figure out something. I currently have a BattleState set up;
public enum BattleState { START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST }
and would like it so when i change the BattleState with a script, it changes it for every other script that references this BattleState. Sorry for the bad wording. Coding is rough :/
You can use interfaces, create an interface such as IBattleStateChanger and have a method on it
interface IBattleStateChanger{
void ChangeBattleState(YourClass.BattleState state);
}
Then on every script you want the value to change implement this interface as
ClassExample : IBattleStateChanger {}
This will then force you to create a method in the script to change the state
After that, whenever you want to change the value globally on the scripts where you implemented this interface, you can do a foreach loop finding each type of this interface such as
BattleState newState = BattleState.START;
foreach (var obj in FindObjectsOfType<IBattleStateChanger>){
obj.SetBattleState(newState);
}
You could use a static event and attach listeners/callbacks to it like e.g.
public enum BattleState
{
START, PLAYERMAINPHASE, PLAYERBATTLEPHASE, PLAYERENCORESTEP, ENEMYTURN, WON, LOST
}
public static class BattleStateMgr
{
private static BattleState _state;
public static BattleState State => _state;
public static event System.Action<BattleState> OnStateChange;
public static ChangeState(BattleState s)
{
_state = s;
OnStateChange?.Invoke(_state);
}
}
public class OtherScript : MonoBehaviour
{
private void Awake()
{
BattleStateMgr.OnStateChagne += OnBattleStateChange;
}
private void OnDestroy()
{
BattleStateMgr.OnStateChagne -= OnBattleStateChange;
}
private void OnBattleStateChange(BatlleState newState)
{
Debug.Log($"Changed Battle State to{newState}", this);
}
}
I believe you are confused about the scope of your variable. Each script you place an instance of the enum Battlestate, is a local version of that enum. If you want the reference to be global, you will need to have a central point where all scripts can grab this reference.
public class BattleManager : MonoBehaviour
{
private BattleState battleState;
// setter / getters
public BattleState GetBattleState(){return battleState; }
public void SetBattleState(BattleState state){ battleState = state; }
}
You are going to want to make a single script that holds the only reference to your enum Battlestate, then have your other scripts reference the variable.
public class OtherScript : MonoBehaviour
{
// assign this reference in the inspector
[SerializeField] private BattleManager bm = null;
private void YourFunction()
{
if(bm.GetBattleState() == BattleState.randomStateHere)
{
// run logic here
}
}
}
There are a number of ways to go about doing this, but the easiest would most likely be by declaring the variable static.
public class BattleManager : MonoBehaviour
{
private static BattleState battleState;
// setter / getters
public static BattleState GetBattleState(){return battleState; }
public static void SetBattleState(BattleState state){ battleState = state; }
}
public class OtherScript : MonoBehaviour
{
private void YourFunction()
{
if(BattleManager.GetBattleState() == BattleState.randomStateHere)
{
// run logic here
}
}
}
I do not know how many scripts you need to access this variable, but if it is only a handful, I would instead assign references to the script that holds the enum to each of the scripts that need it. I would avoid simply using static as it is the easy approach but creates what is called a code smell. The reason for this is OOP (object-oriented programming) by design should generally not have mutable global variables.
If you have a single instance of an object that manages all of your battle activity and a lot of scripts need to access it, you can look into the Singleton pattern. As you are new to programming, I would not implement this pattern until you understand the time and place to properly use it. You can also completely avoid using it by properly assigning the references you need in the inspector or by using a Object.FindObjectOfType in either Start or Awake.

How should you initialize constant data that needs parameters from another part of the code?

I don't think I explained my question very well in the title, so I'll do my best to do it here.
I have an abstract class called Song, a class that extends it MidiSongand then I have a SongCreator interface and a MidiSongCreatorclass that implements it. I would like to have a way to store lots of SongCreators so I can call their Create method but the problem is, since the SongCreators will each be a MidiSongCreator I am wondering how I should initialize each MidiSongCreator since it takes a MIDIPlayer and other things to help initialize it which doesn't have a static reference to it. Should I create a static class that holds lots of SongCreators? Should I not make the SongList class static?
What is looks like:
public abstract class Song{
public IList<Playable> notes { get; private set; }
public SongPlayData Start(){
// calls onStartEvent
return CreateSongData();
}
protected abstract SongPlayData CreateSongData();
public bool Update(SongPlayData songData, float songTime,List<SongPlayer> players) { // note that the players list is a list of people who are playing this game (this is a rhythm game) (doesn't have anything to do with MIDIPlayer
}
public void End(){
//calls end event
}
}
public class MidiSong : Song { // this is the class that needs the MIDIPlayer parameter
public MIDIPlayer midiPlayer;
protected MidiSong(MIDIPlayer player){
this.midiPlayer = player;
}
protected override SongPlayData CreateSongData() {
return new MidiSongData(midiPlayer);
}
}
public interface SongCreator<out T> where T : Song {
T Create();
}
public class MidiSongCreator : SongCreator<MidiSong>, IListenerObject { // this is the class that I need to store lots of instances of. the midiPlayer will probably be the same every time
private MIDIPlayer player;
public MidiSongCreator(MIDIPlayer player) {
this.player = player;
Init();
}
private void Init() {
player.midiListener.listener = this;
//
}
private void Clear() { // resets all the data so we can create another Song if we need to (even without entering stuff in)
if(player.midiListener.listener == this) {
player.midiListener.listener = null;
}
}
public MidiSong Create() {
MidiSong r = new MidiSong(player);
// I'm still going to implement calls to other methods from midiPlayer
Clear();
return r;
}
public void OnLoad(MidiFile file) {
// does stuff to load midi file (deals with individual events)
}
}
public class MasterSong : MonoBehaviour { // this should initialize last btw (It's in the Script Execution Order)
public MIDIPlayer midiPlayer;
public Song song;
public SongPlayData playData;
// Use this for initialization
void Start() {
// this is where I'd like to reference a SongCreator and call it's create method and Start the song
//for instance:
song = SongList.SONG_NAME.Create();
playData = song.Start();
}
void Update() {
}
}
It's a RhythmGame made with unity, but I didn't add the unity tag because I feel that this is more of a C#/design thing.
Also note, that I have my classes much more organized that just one file with all these.
I'm looking for ways to improve on the design that I have.
This is a design problem, domain design!
I suggest don't write code yet. Create a class diagram, with pen and paper, don't need to use tools in the beginning.
Try to determine entities - classes, interfaces etc - and the relationship among them. Just use boxes and arrow, don't need to put details yet. With boxes and arrows, you will be able to have a picture of your domain much more clearly. Keep refining and changing it, still at this high level, without details, until you are satisfied.
Then, step by step, refine it by adding details/properties such attributes and methods. This may cause to change the diagram from the first step.
I intentionally did not refer to specifics of you questions like the classes and interfaces you mentioned. Since, there is not enough information to comment on that. Secondly, and more importantly, you should start at high level of design and once that is done, then do coding based on your design.

List.Count Raises Null Reference Exception [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I'm creating a 2D spaceship game in Unity. I have an object titled "Player" with this script attached to it. In the script, I have this class representing the player's ship:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList;
void Start()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
And this class (within the same script) representing a weapon:
public class Weapon
{
//properties here
}
Now, when I try to reference weaponsList to get List.Count using this code (from a different script), it throws a NullReferenceException, saying Object reference not set to an instance of an object:
Ship ship = GameObject.Find("Player").GetComponent<Ship>();
if (ship.weaponsList.Count >=2)
{
//do stuff
}
But any other property of ship i try to access works just fine. Can someone help? If you need additional context or code, please let me know and I'll make the necessary edits.
EDIT: The start method is special to Unity and is always called by default when the script initializes.
To avoid this error Add constructor to your class
public class Ship : MonoBehaviour
{
public Ship()
{
weaponsList = new List<Weapon>();
}
public List<Weapon> weaponsList;
void Start()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
Your weaponsList is null if Start() isn't called ... or it becomes null at some point. Change the public variable to become a public property to deny external callers to change the internal list:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList { get; private set; }
public Ship()
{
weaponsList = new List<Weapon>();
}
...
}
This will likely create compiler errors in other parts of your application. These errors are probably the reason why weaponsList becomes null.
In terms of better coding practice some more suggestions to change the property to this:
public IList<IWeapon> Weapons { get; private set; }
Change the List to an interface.
Change the Weapon to an IWeapon.
Use Pascal notation (Weapons, not weapons).
Avoid types in names: Weapons, not WeaponsList (that it is a list is obvious)
Ship does not contain weapons list.
You can avoid the exception with
Ship ship = GameObject.Find("Player").GetComponent<Ship>();
if (ship != null && ship.weaponsList != null && ship.weaponsList.Count >=2)
{
//do stuff
}
¿Is the method Start() been call?
Instead of putting the initialization of the weapons list in the void Start() put it in the constructor of the object. Then when the ship is created, the weapons list will always be initialized with a zero count. A constructor should always put the object in question into a valid state so it can be used. Sometimes, programmers create Init() or Start() methods to defer expensive logic until a method actually needs it, but in this case I would definitely put that initialization in the constructor.
The list is constructed when Start() is called. If Start() is not called before the list is accessed, your error will appear. My guess is that you are trying to access the list before Start() is called.
You should consider building a constructor for the Ship class and placing the initialization code there:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList;
public Ship()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
This constructor will be called as soon as objects of the class are created, and you won't have to call a method explicitly to get the object's properties constructed.

Getting null errors even though Im using the variable

I'm trying to learn MonoGame and I'm trying to do basic stuff and I've figured most of it out on my own but I'm getting a null pointer and I'm not sure why. I'm trying to get MainMenuScene to just draw a texture but in SceneManager currentScene keeps giving me null pointers and I have no idea why. Ill post my SceneManager code but the rest will be on github. Its not much code so it shouldnt take long if you'd look over it. I'm super confused and I'm not sure what to google to try to figure it out myself.
https://github.com/eatmykhack/MonoGame.git
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tutorial.Scenes;
class SceneManager
{
private static SceneManager instance = new SceneManager();
Scene currentScene, newScene;
Dictionary<string, Scene> sceneDirectory =new Dictionary<string, Scene>();
public static SceneManager getInstance()
{
return instance;
}
public static Scene getCurrentScene()
{
return instance.currentScene;
}
public static void changeScene(Scene scene)
{
}
public static void addScene(string sceneName)
{
instance.newScene = instance.sceneDirectory[sceneName];
}
public void update() { currentScene.Update(); }
public void draw(SpriteBatch spriteBatch) { currentScene.Draw(spriteBatch); }
public void Initialize()
{
instance.sceneDirectory["MainMenuScene"] = new MainMenuScene();
instance.currentScene = instance.sceneDirectory["MainMenuScene"];
}
public void LoadContent(ContentManager content)
{
instance.currentScene.LoadContent(content);
}
public void UnloadContent()
{
instance.currentScene.UnloadContent();
}
}
you've declared Scene as an abstract class, so you can't just use it as you're doing: Scene currentScene, newScene. (See this reference for more details on abstract classes).
Either make scene a non-abstract class type or create another class that inherits from your abstract class, looking at your code it would be something like:
public class myScene : Scene
{
public override void Update()
{
//do something
}
// etc.
}
You are getting a NullReferenceException because you are mixing static and instance fields in your code:
There are several problems:
Your SceneManager has a public constructor, but its instance method all access the same static (singleton) instance.
Your SceneManager.Draw method does not access the static instance.
Your Game class instantiates a separate ScreenManager instance, meaning the singleton is initialized, but the Games instance isn't. This is allowed because of 1.
There are several ways of fixing this:
The Preferred way: remove the static stuff from SceneManager. Your game is going to have a single instance in the Game class anyway, and you can simply pass the instance along to any scenes. A no brainer.
However, if you want to keep this class a singleton, you need to change a couple of things. People usually want this because they are too lazy to pass the SceneManager along to each scene instance. So, singletons are bad, you won't be able to unit test anything, but I believe most indie game developers don't care too much about unit testing and would be happiest if everything was static and accessible from anywhere.
Make the constructor private, so that no other class (like Game) can instantiate it. If anyone wants to access the instance, they should do it through the getInstance() method. Which, btw, might better be a property instead:
public class SceneManager
{
// private constructor means other classes cannot instantiate this
private SceneManager() { }
private static readonly SceneManager _instance = new SceneManager();
public static SceneManager Instance
{
get { return _instance; }
}
}
If you now try to pull this off in your Game class:
var sceneManager = new SceneManager();
your compiler will tell you it's not going to work that way.
Your SceneManager should only have a single static method/property: getInstance() or the Instance property like shown above. All other methods should be instance methods of that one-and-only instance, and not access the instance field at all. They are accessing that instance anyway. It is a bad idea to have instance methods access static fields:
This is wrong:
public void Initialize()
{
var mainScene = = new MainMenuScene();
instance.sceneDirectory["MainMenuScene"] = mainScene;
instance.currentScene = mainScene;
}
But this is fine (and the this keyword is redundant, of course):
public void Initialize()
{
var mainScene = = new MainMenuScene();
this.sceneDirectory["MainMenuScene"] = mainScene;
this.currentScene = mainScene;
}
Because you're going to use it like this anyway:
// you're basically doing the same thing, but
// it's immediately clear what's going on, and there
// is no room for errors:
var manager = SceneManager.Instance;
manager.Initialize();
The simplest way to ensure you're doing it right it to remove all references to instance inside the SceneManager class.

Unity singleton manager classes

In Unity, whats a good way to create a singleton game manager that can be accessed everywhere as a global class with static variables that will spit the same constant values to every class that pulls those values? And what would be the way to implement it in Unity? Do I have to attach it to a GameObject? Can it just be there in a folder without being in the scene visually?
Like always: it depends. I use singletons of both kinds, components attached to GameObject and standalone classes not derived from MonoBehaviour. IMO the overall question is how are instances bound to the lifcycle of scenes, game objects, ... And not to forget sometimes it is more convenient to have a component especially referencing other MonoBehaviour objects is easier and safer.
There are classes that just need to provide some values like for example a config class that needs to load settings from persistence layer when called. I design theese classes as simple singletons.
On the other hand some objects need to know when a scene is started i.e. Start is called or have to perform actions in Update or other methods. Then I implement them as component and attach them to a game object that survives loading new scenes.
I designed component based singletons (type 2) with two parts: a persistent GameObject called Main, which holds all components and a flat singleton (type 1) called MainComponentManager for managing it. Some demo code:
public class MainComponentManger {
private static MainComponentManger instance;
public static void CreateInstance () {
if (instance == null) {
instance = new MainComponentManger ();
GameObject go = GameObject.Find ("Main");
if (go == null) {
go = new GameObject ("Main");
instance.main = go;
// important: make game object persistent:
Object.DontDestroyOnLoad (go);
}
// trigger instantiation of other singletons
Component c = MenuManager.SharedInstance;
// ...
}
}
GameObject main;
public static MainComponentManger SharedInstance {
get {
if (instance == null) {
CreateInstance ();
}
return instance;
}
}
public static T AddMainComponent <T> () where T : UnityEngine.Component {
T t = SharedInstance.main.GetComponent<T> ();
if (t != null) {
return t;
}
return SharedInstance.main.AddComponent <T> ();
}
Now other singletons that want to register as Main component just look like:
public class AudioManager : MonoBehaviour {
private static AudioManager instance = null;
public static AudioManager SharedInstance {
get {
if (instance == null) {
instance = MainComponentManger.AddMainComponent<AudioManager> ();
}
return instance;
}
}
If this class is just for accessing global variables then you don't really need a singleton pattern for this, or use a GameObject.
Simply create a class with public static members.
public class Globals
{
public static int mStatic1 = 0;
public static float mStatic2 = 0.0f;
// ....etc
}
The other solutions are fine but overkill if all you need is global access to variables.
Engineers who are new to Unity often don't notice that
you can't have a "singleton" in an ECS system.
It is meaningless.
All you have in Unity is GameObjects, at, XYZ positions. They can have components attached.
It would be like trying to have "a singleton" or "inheritance" in .... Photoshop or Microsoft Word.
Photoshop file - pixels at XY positions
Text editor file - letters at X positions
Unity file - GameObjects at XYZ positions
It is "just that simple".
So, in a game you will have "general" behaviors where there is only "one" of the thing. (So obviously there is only "one sound effects engine" , "one screen", "one scoring system" and so on.) A normal programmer would think of those as "singletons", but Unity just has nothing to do with singletons and no connection to singletons.
So if you have "a tank" or "a tree" of course it's normal you may have dozens of those things. But "the sound effects engine" or "the networking system" are "general, only-one-of-them" systems.
Hence, trivially, in Unity "the sound effects engine" or "the networking system" very simply sits on a game object, and, you (obviously) just have the one of them.
Those "general, only-one-of-them" items just sit on the preload scene.
You absolutely have to have a preload scene anyway, in every Unity project.
(Simple how-to: https://stackoverflow.com/a/35891919/294884 )
In the future Unity will include a "built-in preload scene" - when that day comes this will finally never be discussed again!
(Note - some of the languages you use to compile Components for Unity of course have OO concepts; but Unity itself has no connection to OO at all. Unity is like photoshop. You have "game objects" each at a certain 3D position.)
(Note - in the early days of Unity you'd see attempts at making code, say c#, which creates a game object on the fly, attempts to keep the game object unique, and "attaches itself" to the game object as a component. Apart from being completely bizarre/pointless, just FWIW it's theoretically not possible to ensure uniqueness (actually not even within a single frame). Again, it's moot because in Unity general behaviors just go on the preload scene.)
I wrote a singleton class that makes easy to create singleton objects. Its is a MonoBehaviour script, so you can use the Coroutines. Its based on this Unity Wiki article, and I will add option to create it from Prefab later.
So you don't need to write the Singleton codes. Just download this Singleton.cs Base Class, add it to your project, and create your singleton extending it:
public class MySingleton : Singleton<MySingleton> {
protected MySingleton () {} // Protect the constructor!
public string globalVar;
void Awake () {
Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID());
}
}
Now your MySingleton class is a singleton, and you can call it by Instance:
MySingleton.Instance.globalVar = "A";
Debug.Log ("globalVar: " + MySingleton.Instance.globalVar);
Here is a complete tutorial: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/
This is the setup I have created.
First create this script:
MonoBehaviourUtility.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
static public class MonoBehaviourUtility
{
static public T GetManager<T>( ref T manager ) where T : MonoBehaviour
{
if (manager == null)
{
manager = (T)GameObject.FindObjectOfType( typeof( T ) );
if (manager == null)
{
GameObject gameObject = new GameObject( typeof( T ).ToString() );
manager = (T)gameObject.AddComponent( typeof( T ) );
}
}
return manager;
}
}
Then in any class you want to be a singleton do this:
public class ExampleManager : MonoBehaviour
{
static public ExampleManager sharedManager
{
get
{
return MonoBehaviourUtility.GetManager<ExampleManager>( ref _sharedManager );
}
}
static private ExampleManager _sharedManager;
}
One way to do it is to make a scene just to initialize your game manager like this:
public class GameManager : MonoBehaviour {
static GameManager instance;
//other codes
void Awake() {
DontDestroyOnLoad(transform.gameObject);
instance = this;
}
//other codes
}
That's it, that's all you need to do. And then immediately after initializing the game manager, load the next scene and never come back to this scene again.
Have a look at this tutorial:
https://youtu.be/64uOVmQ5R1k?list=WL
Edit:
Changed GameManager static instance; to static GameManager instance;
Instead of creating one singleton for each class. I would suggest you to create a generic class for singleton. i use to follow this method which make my life very easy.
For More detail visit here
Or
Create Unity C# class in unity and use following code
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
Here is a simple code taken from Unity Tutorial. for better understanding open the link
using System.Collections.Generic; //Allows us to use Lists.
public class GameManager : MonoBehaviour
{
public static GameManager instance = null; //Static instance of GameManager which allows it to be accessed by any other script.
private BoardManager boardScript; //Store a reference to our BoardManager which will set up the level.
private int level = 3; //Current level number, expressed in game as "Day 1".
//Awake is always called before any Start functions
void Awake()
{
//Check if instance already exists
if (instance == null)
//if not, set instance to this
instance = this;
//If instance already exists and it's not this:
else if (instance != this)
//Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
Destroy(gameObject);
//Sets this to not be destroyed when reloading scene
DontDestroyOnLoad(gameObject);
//Get a component reference to the attached BoardManager script
boardScript = GetComponent<BoardManager>();
//Call the InitGame function to initialize the first level
InitGame();
}
//Initializes the game for each level.
void InitGame()
{
//Call the SetupScene function of the BoardManager script, pass it current level number.
boardScript.SetupScene(level);
}
//Update is called every frame.
void Update()
{
}
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
public static T instance { get; private set; }
protected virtual void Awake() {
if (instance == null)
{
instance = (T)this;
DontDestroyOnLoad(gameObject);
OnInit();
}
else if (instance != this)
{
Destroy(gameObject);
}
}
protected virtual void OnInit()
{
}
}
GameManage :
class GameManager : Singleton<GameManager> {
}

Categories