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.
Related
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.
I have noticed a rather weird behaviour in my application I am creating;
I have a class I defined that has a static "instance" variable of the class type.
I would assume that (as per code attached) the constructor would be called.
Alas, it is not, unless I use the Void.get in a non-static field anywhere in my code.
public class Void : TilePrototype {
public static Tile get = new Tile((int)TileEntities.Void);
public static Void instance = new Void();
public Void() {
Debug.Log("created");
id = (int)TileEntities.Void;
isBlocking = true;
register();
}
public override RenderTile render(Tile tile){
return new RenderTile(0, new Color(0, 0, 0, 0));
}
So when I have something like :
public static TileStack empty = new TileStack(Void.get, Void.get);
the Void class constructor never gets called. But, if I have:
Tile t = Void.get;
Anywhere in my code it will be called.
Why?
Thanks.
This is a really really subtle and nuanced area of C#; basically, you've stumbled into "beforefieldinit" and the difference between a static constructor and a type initializer. You can reasonably ask "when does a static constructor run?", and MSDN will tell you:
It is called automatically before the first instance is created or any static members are referenced.
Except... public static TileStack empty = new TileStack(Void.get, Void.get); isn't a static constructor! It is a static field initializer. And that has different rules, which basically are "I'll run when I must, no later, possibly sooner". To illustrate with an example: the following will not (probably) run your code, because it doesn't have to - there isn't anything demanding the field:
class Program
{
static void Main()
{
GC.KeepAlive(new Foo());
}
}
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
}
However, if we make a tiny tweak:
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
static Foo() { } // <=== added this
}
Now it has a static constructor, so it must obey the "before the first instance is created" part, which means it needs to also run the static field initializers, and so on and so on.
Without this, the static field initializer can be deferred until something touches the static fields. If any of your code actually touches empty, then it will run the static field initializer, and the instance will be created. Meaning: this would also have this effect:
class Program
{
static void Main()
{
GC.KeepAlive(Foo.empty);
}
}
public class Foo
{
public static TileStack empty = new TileStack(Void.get, Void.get);
}
This ability to defer execution of the static initialization until the static fields are actually touched is called "beforefieldinit", and it is enabled if a type has a static field initializer but no static constructor. If "beforefieldinit" isn't enabled, then the "before the first instance is created or any static members are referenced" logic applies.
Thanks to Marc Gravell's aswer I came up with this contraption (and admittedly I do like the new solution more than the old one, so thanks again!)
Modifications done to the Void class:
public class Void : TilePrototype {
public static Void instance = new Void();
public static Tile get {
get {
return new Tile(instance.id);
}
}
public Void() {
isBlocking = true;
}
public override RenderTile render(Tile tile){
return new RenderTile(0, new Color(0, 0, 0, 0));
}
}
So as You can see I made the "get" variable a property, so that it's evaluated later, when you actually need the tile, not on construction.
I've changed all "get"s this way.
Second change is in the TilePrototype:
public class TilePrototype {
public static Dictionary<int, TilePrototype> tilePrototypeDictionary = new Dictionary<int, TilePrototype>();
public static void registerPrototype(int id, TilePrototype tp){
tp.id = id;
tilePrototypeDictionary.Add(id, tp);
}
public static bool registered = false;
public static void registerAll(){
if( registered ) return;
registerPrototype(0, Void.instance);
registerPrototype(1, Air.instance);
registerPrototype(2, Floor.instance);
registerPrototype(3, Wall.instance);
(...)
Here I've added the registerPrototype and registerAll functions.
This gives me easy access to all the registered type ids (by say Wall.instance.id) as well as the other way around (from id to instance via the Dictionary)
I also have all registered things in one place, with the possibility of runtime adding more
Overall, much neater, and here I assure that all tiles are registered properly and assigned proper IDs.
Change of ID is simple and in one place and everywhere else, access to this ID is done via a short .instance.id
Thanks again for the help :)
I'm doing a basic game in C#, and I'm running up on a problem I can't solve. Here's the (relevant) code:
public class GameManager
{
public GameMap MainMap;
public EntityManager GameWorld;
public SystemManager GameSystems;
public GameManager()
{
EntityManager GameWorld = new EntityManager();
SystemManager GameSystems = new SystemManager();
GameMap MainMap = new GameMap(61, 41);
}
public void InputHandler(string Trigger)
{
switch (Trigger)
{
case "north":
GameSystems.Move(GameWorld, MainMap, 0, 8);
break;
//etc
}
}
}
public class SystemManager
{
public rkcPosition _position;
public SystemManager()
{
}
public bool Move(EntityManager TargetWorld, GameMap TargetMap, int TargetID, int TargetDirection)
{
rkcPosition _position = TargetWorld.GetPosition(TargetID);
// here, GetPosition returns an instance of rkcPosition
// pulled from a List<rkcPosition> - this seems to be the problem point
}
}
The problem I'm getting is with the part where I try to call GameSystems.Move - it jumps to highlight the last line of the code I included (w/rkcPosition) and gives a null ref exception. (rkcPosition is a class I've not included in this code snippet)
I'm trying to have the Move function perform some changes to values within the GameWorld and MainMap objects. I'm beginning to think I'm doing this all wrong, so...
If I want to run a method on my existing instances "GameWorld" and "GameSystems" from the InputHandler function, how would I do this properly?
Like Sami Kuhmonen said, the problem in your code is that you are constantly passing around and reassigning your objects that are essentially supposed to be global. Not only does this require that you pass them as parameters to anything that would need them, it is also incredibly error-prone (as you have discovered).
Instead of having these objects behave like instance objects, utilize the Singleton design.
What this means is that instead of instance members, these objects are static members that represent a single global object for everything else to access.
public class GameManager
{
public static GameMap MainMap;
public static EntityManager GameWorld;
public static SystemManager GameSystems;
static GameManager()
{
GameWorld = new EntityManager();
GameSystems = new SystemManager();
MainMap = new GameMap(61, 41);
}
//...
}
Now in your other classes, instead of having to worry if you are passing around the correct object, simply reference these singletons from the GameManager.
public class SystemManager
{
public rkcPosition _position;
//...
public bool Move(int TargetID, int TargetDirection)
{
rkcPosition _position = GameManager.MainMap.GetPosition(TargetID);
}
}
You are constantly redefining variables inside methods that override the member variables. As your debugger shows the GameWorld, MainMap etc are null and you're trying to use them. I don't know how it even goes to Move() since the member variable GameSystems will also be null.
Remove the definitions of the variables inside the methods, that way you're actually storing the objects somewhere and not throwing them away immediately after the method is over. For example:
public GameManager()
{
GameWorld = new EntityManager();
GameSystems = new SystemManager();
MainMap = new GameMap(61, 41);
}
So I have got this class called TypingKeyboard. It's a class that draws a string on the screen as if it is typed by someone, with sounds. I use this for many things, for example in the main menu, credits and the game itself.
class TypingKeyboard
{
SoundEffect foo;
public TypingKeyboard(string text, int intervalBetweenKeys, blah blah blah){}
public void LoadContent(ContentManager content)
{
foo = Content.Load<SoundEffect>("keysoundthinggy");
}
}
In order to hear sounds you need to load the sounds, and store them. This happens for every instance of the class I have.
So every time you make this class, you need to call LoadContent and it loads the SoundEffect to the RAM. This is not very efficient since I always use the same sounds.
Is there a way that I can create a class that you need to make an instance of once and then can call the sounds from "anywhere" I want?
Like this:
// I need to play the sound!
TypingKeyboardData.Foo.Play();
Use the lazy singleton pattern:
public class TypingKeyboardData
{
private static readonly Lazy<TypingKeyboardData> _instance
= new Lazy<TypingKeyboardData>(() => new TypingKeyboardData());
// private to prevent direct instantiation.
private TypingKeyboardData()
{
}
// accessor for instance
public static TypingKeyboardData Instance
{
get
{
return _instance.Value;
}
}
// Add all required instance methods below
}
More here.
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> {
}