Search Unity

Showcase Singleton that does not persist between scenes.

Discussion in 'Scripting' started by SolidAlloy, May 17, 2020.

  1. SolidAlloy

    SolidAlloy

    Joined:
    Oct 21, 2019
    Posts:
    58
    I've been using the Singleton pattern quite a lot, with implementations like this. But I think a singleton does not always have to persist between scenes.
    Why would you need it then, you ask? Well, if multiple objects on a scene depend on one component reference, each of them will have to call GetComponent() or FindObjectOfType() which is not very performance-efficient. If you know you will need only one instance of a MonoBehaviour component on the scene, you don't have to search for the component in each new script. Instead, access it through a static Instance property.

    I created a gist with the implementation of such a singleton. What do you think, is this an efficient way to manage components that occur only once per scene?
     
    PraetorBlue likes this.
  2. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Neither of both are real singleton patterns for the Type T unless T is A subtype of such implementation. So I'd say both implement a pattern that's sort of a very lightweight variant of a service locator.

    You could've used GetComponent or FindObjectOfType in Unity's messages such as Awake (probably not recommended, due to the (per default) unknown initialization order unless you initialize on demand/access or set an explicit execution order) or Start. Since there's supposed to be a single instance (or a real singleton) in the scene, you'll always get the reference and won't need to worry about grabbing the wrong one. Though GetComponent would also require to have the GO's reference to which that one instance is meant to be attached.
     
    Last edited: May 17, 2020
  3. SolidAlloy

    SolidAlloy

    Joined:
    Oct 21, 2019
    Posts:
    58
    Right, GetComponent can be called in Awake or Start only once in each GameObject's lifetime. However, if there are a lot of objects in the scene that need a reference to the component, GetComponent will still be called quite often. If it is something like projectiles, GetComponent may be called multiple times per second. The static Instance property improves the efficiency because a reference to the component needs to be found only once, and all other objects, regardless of their number, will have access to this reference.
     
    PraetorBlue likes this.
  4. Rocky_Unity

    Rocky_Unity

    Joined:
    Oct 13, 2017
    Posts:
    96
    Hi! I thought this was really cool, thank you for posting this! I had the same thoughts as you. For my immediate use case, I wanted a "Grid Manager" to be universally accessible like a static, but I did not want it to be persistent because other scenes may or may not have a unique Grid with different Tilemaps.
    Sorry for the Necro, but I think this is very relevant and I appreciate the code share to learn from
     
    Last edited: Mar 25, 2021
    SolidAlloy likes this.
  5. cybergamedeveloper

    cybergamedeveloper

    Joined:
    Aug 10, 2020
    Posts:
    5
    This is a nice approach guys, I implemented in my Game. Something like Scene pool managers...
    However, the singleton instance is destroyed before other object pool client.
    I want to have the instance NOT be destroyed (because we cannot control when the game object is destroyed).
    I used DontDestroyedOnLoad on the instance when it was first created.
    However, I want to hear your suggestions on this.

    Really appreciate.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,749
    Is there actually a question here? It sounds like whatever you're doing is working fine. Everything in this thread is what is colloquially referred to as "Unity singletons" and they can have any number of different lifespans.

    And yes, they do have a lot of characteristics of service locators.

    They are awesome time-savers, they play well with Unity, they mimic a lot of typical lifecycles found in interactive entertainment, and you can make them from MonoBehaviors or from ScriptableObjects (your choice).

    They work, despite all the "anti-pattern" blathering you might read.

    Simple Singleton (UnitySingleton):

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

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

    https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

    These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }