LinkedinGitHub
Close

RIngleton – a resource Singleton!

NOTE: You should probably use ScriptableObjects instead.

The ringleton is a design pattern I’ve been (ab)using quite a lot recently. It’s a really handy way of serializing / deserializing data that is used across your game.

Basically, what I needed was a quick and simple way of storing some data which is then used on multiple locations in my game. In bigger games you would probably use some form of custom json serializatian but that seemed a bit much for my needs.

This is what I came up with.

Singleton

A singleton is basically a class that only ever has one instance of itself. This is useful when you want the state of your object to persist across multiple classes, without having to pass the same object over to every class. It usually uses a public static variable, that holds an instance of that class, which is instantiated either manually or the first time that static variable is accessed. A basic example would be:

public class Singleton
{
    private static Singleton instance;

    private Singleton() {}

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

In this case, the private constructor makes sure only this class can instantiate itself and the Instance property will do just that when it’s first accessed.

If you are already familiar with singletons then you know it’s a very useful design pattern. So useful, in fact, that it’s been abused to hell and beyond by developers everywhere.
So, why not poke at it again?

RIngleton

A RIngleton is a Singleton by heart, with a very important extra feature. When it’s first initialized, instead of manually instantiating it, we deserialize an existing instance from Unity’s Resources folder.
Why? For the glory of Satan, of course!

This way we can store persistent, static data, that can be used across our game. One of the things I use it for is storing audio clips with assigned IDs.

Here is a simple implementation of this pattern, using a modified version of a Singleton implementation available on Unity’s wiki:

using UnityEngine;

public class Ringleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _rinstance;
    private static object _lock = new object();
    private static bool applicationIsQuitting = false;

    public static T RInstance
    {
        get
        {
            if (applicationIsQuitting)
            {
                Debug.LogWarning("[RIingleton] RInstance '" + typeof(T) +
                                 "' already destroyed on application quit." +
                                 " Won't create again - returning null.");
                return null;
            }

            lock (_lock)
            {
                if (_rinstance == null)
                {
                    _rinstance = Resources.Load<T>(typeof(T).ToString());
                }

                return _rinstance;
            }
        }
    }

    public void OnDestroy()
    {
        applicationIsQuitting = true;
    }
}

To use it, you would have to:

  1. Create a class, that extends RIngleton.
  2. Put some serializable variables in (for instance, an array of strings)
  3. Create a new prefab in the Resources folder, with the same name as your class, and with your class attached as a component.
  4. In the inspector, fill your component with data you want to “save”

And that’s it! The first time you will access your ringleton with MyClass.RInstance it will deserialize all of the data from your prefab and return it back to you.

Leave a Reply

Your email address will not be published. Required fields are marked *