Singleton instance created twice, what's the reason?

Hey There! I found a problem that my singleton class gets created twice each time I run the game. And when different classes try to access the same static property “Instance”, they get different instances.
The singleton class named “CommandQueue” is written as follows:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CommandQueue: IEnumerable<Command> {
    private CommandQueueNode headBand = new CommandQueueNode();
    private CommandQueueNode tailBand = new CommandQueueNode();

    public Command Head { get => headBand.next.content;}
    private static CommandQueue instance;
    public static CommandQueue Instance {get{
        if (instance is null)
            instance = new();
        return instance;
    }}

    private CommandQueue(){
        headBand.next = tailBand;
        tailBand.last = headBand;
        AddHead(new SGS());
        Debug.Log("CommandQueue is created!");
    }
    ## other codes
}

And when the game is run, the console outputs that this class gets created twice.
the screenshot is at https://imgur.com/a/xzA490T.

And I found it more interesting that this problem gets solved naturally when I turned CommandQueue into a MonoBehavior, rewriting construction and singleton logic into Awake(), and attached the script to some empty GameObject.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CommandQueue: MonoBehaviour, IEnumerable<Command> {
    private CommandQueueNode headBand = new CommandQueueNode();
    private CommandQueueNode tailBand = new CommandQueueNode();

    public Command Head { get => headBand.next.content;}
    private static CommandQueue instance;
    public static CommandQueue Instance {get => instance;}

    void Awake(){
        instance = this;
        headBand.next = tailBand;
        tailBand.last = headBand;
        AddHead(new SGS());
        Debug.Log("CommandQueue is created!");
    }
    ## other codes
}

Then console only output “CommandQueue is created” once and other logics functioned in an expected way.

Does anyone knows the reason? Can we only use the latter singleon writting style in Unity?

Do you have enter play mode domain reload enabled? If scripts are reloaded, it’s possible that one instance is created in the old domain (and immediately deleted) and then another one in the new domain.

Are you sure your play mode code is actually getting two separate instances?
What does the stack trace say about what triggers the calls to Instance?

Yet Another Defective Singleton (YASD)

My goodness they’re everywhere. Try this approach instead:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance

Alternately you could start one up with a [RuntimeInitializeOnLoad] attribute.

There is never a reason to drag a GameObject into a scene if it will be DontDestroyOnLoad.

If you do:

  • you may drag it into something else that isn’t DDOL. FAIL
  • you may drag something else into it that isn’t DDOL. FAIL

Just DO NOT drag anything into a scene that will be marked DontDestroyOnLoad. Just Don’t Do It!

@meowlamoon, the code as you have posted it cannot print what you’re showing in your screenshot if that’s the only place you construct a CommandQueue, unless you have turned off clear on play in the console and we’re looking at you having entered play mode several times. The two messages is very probably you instantiating a CommandQueue from somewhere else, or you doing something else funky.

As for your question, your way of doing things (no MonoBehaviour, no GameObject) is definitely supperior if you don’t need any of the messages from MonoBehaviour. And it for sure works!

If you want to change approach, I would go for just having a static class, and not a singleton. Reset the state in [RuntimeInitializeOnLoad]. There’s no real reason to have a singleton if you’re not doing something objecty with the object - like replacing it for some reason.