Various types of singleton-like classes for Unity scripts and assets.
- Implement the singleton class of your choice
- Create a new game object in the scene and add the new component
- Reference the singleton as needed in code
- ???
- Profit
Provides singleton functionality for MonoBehaviour types.
// Singleton implementationpublicclassMySingleton:SingletonBehaviour<MySingleton>{publicvoidHelloWorld()=>Debug.Log("Hello World");}// A class that uses the singleton's function by calling `instance`publicclassMyBehaviour:MonoBehaviour{privatevoidStart(){MySingleton.instance.HelloWorld();}}Provides singleton functionality for ScriptableObject types.
// Singleton implementation[CreateAssetMenu(menuName="My Singleton")]publicclassMySingleton:SingletonScriptableObject<MySingleton>{publicintsomeConfigurationValue=20;}// A class that uses the singleton's configuration value by calling `instance`publicclassMyPlayerBehaviour:MonoBehaviour{publicintmovementSpeed{get;privateset;privatevoid Start(){movementSpeed=MySingleton.instance.someConfigurationValue;}}This attribute allows devs to use a resource as the source object for a singleton when an instance has not yet been set in the scene. Thus referencing a singleton implementation's instance property would instantiate the resource at the given path provided it exists and a current instance has not yet been set.
- Singletons can become prefabs or one-off configuration files
- Prevents race conditions issues
- Guarantees an instance is available for a singleton
- Can be used on either
SingletonBehaviour<T>orSingletonScriptableObject<T>
[LoadFromResource("Prefabs/System/MySingleton")]publicclassMySingleton:SingletonBehaviour<MySingleton>{}[LoadFromResource($"Prefabs/System/MyConfigurationSingleton")][CreateAssetMenu(menuName="My Configuration")]publicclassMyConfigurationSingleton:SingletonScriptableObject<MyConfigurationSingleton>{}It's often not best practice to provide global access to certain manager or system classes. However, in scenarios where game data is necessary on multiple levels, using singletons can be a means to save time and provide easy access.
My favorite use case is a generic GameConfiguration implementation that can be accessed from multiple classes, behaviours, etc. from across the codebase:
[LoadFromResource("Configuration/GameConfiguration)")][CreateAssetMenu(menuName="Configuration/Game Configuration")]publicclassGameConfiguration:SingletonScriptableObject<GameConfiguration>{publicintmaxLocalPlayers=4;publicintmaxAfkSeconds=20;// etc. }