0
\$\begingroup\$

I just came upon programming patterns and learned about singleton. I'm in the process of creating my first game and it contains several managers:

enter image description here

I wanted to implement singleton on each of the managers,but the only way I can think is copy pasting the singleton pattern on each awake method script attached to each manager.

Is there a more efficient way to do it rather than pasting the pattern on each awake method?

\$\endgroup\$
2
  • \$\begingroup\$ Oh! That sounds simpler than what I have thought thanks! that actually works! \$\endgroup\$
    – tcg
    Aug 1 '20 at 12:04
  • \$\begingroup\$ What's the point of having a singleton instead of making everything static? \$\endgroup\$
    – user253751
    Aug 31 '20 at 16:34
1
\$\begingroup\$

An effective way to achieve this is to not do it.

You can create a single singleton that will be the entry point and owner of all the other managers. This way, you don't need to add the singleton infrastructure to all of your managers, just to one.

\$\endgroup\$
1
\$\begingroup\$

I have to say this question doesn't demonstrate much research. If you plug "unity singleton" into a search engine, the very first result is the Unify Community Wiki where they show how to make a reusable Singleton via the Curiously Recurring Template Pattern.

Here's a simplified version closer to the Awake style you're describing:

public abstract class Singleton<T> : MonoBehaviour where T :Singleton<T>
{
    public static T Instance { get; private set; }

    private void Awake() {

        if(Instance != null) {
            Debug.LogErrorFormat("Two copies of singleton {0} in the scene: ({1}, {2}). Please ensure only one is present.", 
                (typeof(T)).FullName, Instance.name, name);
            Destroy(gameObject);
            return;
        }

        Instance = (T)this;
    }
}

You can then apply this singleton behaviour to any MonoBehaviour type by deriving from the template:

public class SomeManager : Singleton<SomeManager>
{        
}

Then access its instance with SomeManager.Instance

That said, as Vaillancourt points out, you can skip having many singletons by just having one overall manager that holds references to the others. In this way it behaves like a version of the Service Locator pattern, giving you a common place to re-hook the references if you ever need to change the sub-managers or have more than one:

public class GameManager : Singleton<GameManager> {

    public AudioManager audioManager;
    public PuzzleManager puzzleManager;
    // ...
}

This can help you avoid a common problem we run into with Singletons, where we add multiplayer and suddenly all the systems that used to be globally unique for the only player, now need multiple instances, one for each player. The "manager of managers" gives you a convenient place to parcel out which references to use for each player, and you can look them up with something like GameManager.Instance.GetInventoryForPlayer(2).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .