- Home /
How to handle a singleton to store game settings?
Hey!
I'm currently using a script called "GameController" to store several useful game settings: default value for some objects, difficulty settings, etc.
My current way of doing things is putting it on the "Player" object and having a property like this:
static GameController instanceStorage;
public static GameController instance
{
get
{
if(instanceStorage == null)
instanceStorage = GameObject.Find("Player").GetComponent<GameController>();
if (instanceStorage == null)
throw new UnityException("Could not find GameController!");
return instanceStorage;
}
}
It seems to work fine-ish, but I don't think it's pretty. Ideally, I'd like to have a singleton with only one instance for the whole game (ideally it should also survive scenes) but that's also visible/editable in the inspector.
How can I achieve this? Perhaps I need an entirely different system? This class is purely for data storage anyway (it also has a few convenience function to win/lose the game but that can be easily migrated to something else).
Thanks.
Answer by Aviryx · Aug 23, 2020 at 06:50 PM
Placing this on the player is not the "correct" way to do it. I used speech marks because technically you can.... it's just not best practice. The only scripts thst should be placed directly on the player GO are scripts that affect the player (a Player Controller script, for example)
The singleton pattern usually requires an "Empty Game Object" (you could name it Game Controller) that acts as a container - the "Game Controller" script would be attached to that. The reason is anything that inherents from MonoBehaviour must be attached to a GO
public class SomeClass : MonoBehaviour
{
// script must be attached to a gameobject to work
}
Also you don't appear to have implemented the singleton pattern correctly.
private static SingletonExample _instance;
void Awake()
{
// check if a instance exists
if (_instance == null)
{
// No instance exists so make this the instance
_instance = this;
// Do not destroy the gameobject this script is attached to so
// it can persist through scenes.
DontDestroyOnLoad(this.gameObject);
}
else
{
// Singleton instance already exists. This is an imposter so kill it. There can be only one!
Destroy(this);
}
}
There might be better ways to do what you want with data. I say "might" because singletons tend to be a contentious topic. For example, you could use Scriptable Objects to store data including passing data between scenes without a requirement for a singleton pattern.
https://docs.unity3d.com/Manual/class-ScriptableObject.html
using UnityEngine;
[CreateAssetMenu(fileName = "Data", menuName = "Data/SomeDataSO", order = 1)]
public class GameDataScriptableObject : ScriptableObject
{
public int someInteger;
}
public class SomeClass : MonoBehaviour
{
public GameDataScriptableObject gameData;
void Start()
{
Debug.Log(gameData.someInteger);
}}
}
Also, static classes might be useful just in case you are unaware of them. They do not inherit from MonoBehaviour and therefore are not required to be attached to a gameobject. They just exist as handy methods or settings you might want to access from anywhere.
public static class StaticClass
{
public static int someNumber;
}
public class MuhClass : MonoBehaviour
{
void Awake()
{
Debug.Log(StaticClass.someNumber);
}
}
Your answer
Follow this Question
Related Questions
Will Unity 3.0 have a scriptable Input Manager 1 Answer
unity 3 for iphone player project settings 0 Answers
Why game scene will automatically change to full screen 4 Answers
Is there a project setting that could be breaking animations? 0 Answers
How to export FBX from 3dsMax to Unity3d with texturs applied to materials? 0 Answers