Toolbox
From Unify Community Wiki
Revision as of 15:02, 2 February 2016 by Chris Oakley (Talk | contribs)
Contents |
Introduction
Originated from http://www.ibm.com/developerworks/webservices/library/co-single/index.html
If you're here, you probably want to implement Global Variables. For any other usage, just take this as a starting place.
The toolbox is a singleton, before anything else. But it improves upon the concept. Basically this encourages better coding practices, such as reducing coupling and unit testing.
Usage Example
MyClass.cs
public class MyClass : MonoBehaviour { void Awake () { Debug.Log(Toolbox.Instance.myGlobalVar); Toolbox toolbox = Toolbox.Instance; Debug.Log(toolbox.language.current); // (optional) runtime registration of global objects MyComponent myComponent = Toolbox.Instance.RegisterComponent<MyComponent>(); Debug.Log(myComponent.anotherGlobalVar); Debug.Log(Toolbox.Instance.GetComponent<myComponent>().anotherGlobalVar); // GetComponent is not recommended Destroy(myComponent); } } [System.Serializable] public class MyComponent { public string anotherGlobalVar = "yeah"; }
Implementation
Toolbox.cs
public class Toolbox : Singleton<Toolbox> { protected Toolbox () {} // guarantee this will be always a singleton only - can't use the constructor! public string myGlobalVar = "whatever"; public Language language = new Language(); void Awake () { // Your initialization code here } // (optional) allow runtime registration of global objects static public T RegisterComponent<T> () where T: Component { return Instance.GetOrAddComponent<T>(); } } [System.Serializable] public class Language { public string current; public string lastLang; }
Requirement
(optional) MonoBehaviourExtended.cs (from GetOrAddComponent)
static public class MethodExtensionForMonoBehaviourTransform { /// <summary> /// Gets or add a component. Usage example: /// BoxCollider boxCollider = transform.GetOrAddComponent<BoxCollider>(); /// </summary> static public T GetOrAddComponent<T> (this Component child) where T: Component { T result = child.GetComponent<T>(); if (result == null) { result = child.gameObject.AddComponent<T>(); } return result; } }
Singleton.cs (from Singleton)
using UnityEngine; /// <summary> /// Be aware this will not prevent a non singleton constructor /// such as `T myT = new T();` /// To prevent that, add `protected T () {}` to your singleton class. /// /// As a note, this is made as MonoBehaviour because we need Coroutines. /// </summary> public class Singleton<T> : MonoBehaviour where T : MonoBehaviour { private static T _instance; private static object _lock = new object(); public static T Instance { get { if (applicationIsQuitting) { Debug.LogWarning("[Singleton] Instance '"+ typeof(T) + "' already destroyed on application quit." + " Won't create again - returning null."); return null; } lock(_lock) { if (_instance == null) { _instance = (T) FindObjectOfType(typeof(T)); if ( FindObjectsOfType(typeof(T)).Length > 1 ) { Debug.LogError("[Singleton] Something went really wrong " + " - there should never be more than 1 singleton!" + " Reopenning the scene might fix it."); return _instance; } if (_instance == null) { GameObject singleton = new GameObject(); _instance = singleton.AddComponent<T>(); singleton.name = "(singleton) "+ typeof(T).ToString(); DontDestroyOnLoad(singleton); Debug.Log("[Singleton] An instance of " + typeof(T) + " is needed in the scene, so '" + singleton + "' was created with DontDestroyOnLoad."); } else { Debug.Log("[Singleton] Using instance already created: " + _instance.gameObject.name); } } return _instance; } } } private static bool applicationIsQuitting = false; /// <summary> /// When Unity quits, it destroys objects in a random order. /// In principle, a Singleton is only destroyed when application quits. /// If any script calls Instance after it have been destroyed, /// it will create a buggy ghost object that will stay on the Editor scene /// even after stopping playing the Application. Really bad! /// So, this was made to be sure we're not creating that buggy ghost object. /// </summary> public void OnDestroy () { applicationIsQuitting = true; } }