Should a Singleton ever extend Monobehaviour?

Hi
Using this Singleton recipe from this article (#4)
http://csharpindepth.com/Articles/General/Singleton.aspx

For it to work though I believe it cannot be attached to any game object, which I am accustomed to doing.

Is there any reason why you would want to attach a singleton class to a game object?

public sealed class Singleton
{
 private static readonly Singleton instance = new Singleton();

 // Explicit static constructor to tell C# compiler
 // not to mark type as beforefieldinit
 static Singleton()
 {
 }

 private Singleton()
 {
 }

 public static Singleton Instance
 {
 get
 {
 return instance;
 }
 }
}

There are certainly some things that you might want to be singleton; the Player character, for example
Manager objects also

1 Like

Monobehaviour singletons are possible and can have certain advantages. Read this http://wiki.unity3d.com/index.php/Singleton

1 Like

I don’t think this is possible, in the sense that MonoBehaviours are intended to be part of the scene, which means that they can be instantiated and duplicated outside of the singleton pattern.

That said, several of my game objects hold managers that are MonoBehaviours in order to hook into the Start() and Update() functions. While I don’t enforce the singleton pattern on these managers, I do have code that looks like this inside of the script:

public class GameManager : MonoBehaviour
{
   private static GameManager sManager = null;

  public static GameManager Instance()
  {
      if (sManager = null)
          sManager = FindGameManager();

      return sManager;
  }
}

so that other systems can just use

GameManager.Instance.DoSomething()

I forget the details of FindGameManager(), or whether you can just assign the this pointer. Not in front of the code right now.

Either way, this may look like the singleton pattern, but it isn’t, because you can still apply the GameManager script on another object. And calls to GameManager.Instance() may become ambiguous. I just make sure I don’t have another GameManager script in my hierarchy.

Heh, not sure if that’s clever or not, but damn does that look ugly.

I do it all the time and so does Unity (see UNet). Often, you want a manager that should still run Monobehaviour stuff, such as awake, setup, even update.

Don’t see the problem.

2 Likes

Also, it’s sometimes desirable for a singleton to only persist for the lifetime of a given scene. Or for it to contain serialized information. The latter isn’t quite a classic singleton in that it doesn’t create itself as needed, but it is an object that there can only be one of and which can be accessed by an Instance property.

1 Like

My singleton class derives from MonoBehaviour, and in fact I have hardly any top-level classes which don’t. For the reasons @hippocoder stated plus I love having the Inspector available which allows me to do things which make my life easier.

Adding to @Errorsatz post above, another handy pattern in Unity is a singleton which “spins up” from a Prefab asset, and may optionally do so on a per-scene basis.

Essentially you have a .Instance type static accessor field, and instead of just newing up a GameObject and attaching itself as a component, it Instantiates a particular prefab and gets the instance of itself out of there.

There are a lot of handy use cases that this addresses, such as having singletons that can have their properties modified in the Unity3D and saved as prefab assets, and also having multiple different variations of the prefab.

1 Like

This is code that I use all the time. All MonoBehaviours that are also Singletons extend this class like so:

public class SMBClass : MonoBehaviourSingleton<SMBClass>

It also enforces the Singleton nature by deleting any objects that come later

public class MonoBehaviourSingleton<T> : MonoBehaviour where T : MonoBehaviour
    {
        public static T Instance
        {
            get
            {
                if (instance == null)
                {
                    GameObject coreGameObject = new GameObject(typeof(T).Name);

                    instance = coreGameObject.AddComponent<T>();
                }

                return instance;
            }
        }

        private static T instance;

        protected virtual void Awake()
        {
            if (instance == null)
                instance = GetComponent<T>();
            else
                DestroyImmediate(this);
        }
    }
2 Likes

I hadn’t seen that before, much more complete solution than the one I’ve been using.

The one in the wiki is not that good.

Actually, that implementation in the wiki is more error-prone than your short version. With the wiki version, It’s just too easy to introduce bugs that are difficult to track down.