There are many ways to implement a singleton pattern. You can inherit from a base singleton class, or write out static accessors for each one if inheriting isn’t an option.
I’m working on a project that requires multiple singletons, but they all can’t inherit from a base class, so I wrote a utility class to make them quick and easy:
using UnityEngine;
using System.Collections.Generic;
namespace UnityExtensions {
public static class Singleton {
/// <summary>
/// Holds cached references to multiple singletons.
/// </summary>
static Dictionary<string, MonoBehaviour> singletons = new Dictionary<string, MonoBehaviour>();
/// <summary>
/// Returns a cached reference if one exists, otherwise it finds and creates a cached reference. If no instance exists, throws an error.
/// </summary>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static T Get<T>() where T : MonoBehaviour {
var type = typeof(T).Name;
T instance;
if (singletons.ContainsKey(type) && (instance = singletons[type] as T))
return instance;
if (!(instance = GameObject.FindObjectOfType<T>()))
throw new UnityException("No instance of "+type+" exists. Place one in the editor.");
if (singletons.ContainsKey(type))
singletons[type] = instance;
else
singletons.Add (type, instance);
return instance;
}
/// <summary>
/// Should be called in a singletons Awake() or Start(). Ensures only one instance of a singleton exists.
/// </summary>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static void Ensure<T>() where T : MonoBehaviour {
T instance = Get<T>();
var instances = GameObject.FindObjectsOfType<T>();
if (instances.Length != 1) {
Debug.LogError ("Only one instance of "+(typeof(T)).Name+" should ever exist. Removing extraneous.");
foreach(var otherInstance in instances)
if (otherInstance != instance)
Object.Destroy (otherInstance);
}
}
Usage is as follows:
public class Manager : MonoBehaviour {
public static Manager instance {
get {
return Singleton.Get<Manager>();
}
}
void Awake() {
Singleton.Ensure<Manager>();
}
}
Works well. Anything I didn’t think of?