Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by DTFlip · Feb 02, 2015 at 11:10 AM · c#dontdestroyonloadsingleton

Unity C# Singleton?

I'm trying to make a simple singleton object, basically just exists and spams the console that it exists so I can confirm it works when switching scenes (using Application.LoadLevel(Scene)). This doesn't work yet, the Debug.Log fails to continue when loading the new scene and I'm kinda stuck. All the examples I've seen for Singletons look similar to this, just kinda banging my head into a wall. Any ideas?

 using UnityEngine;
 using System.Collections;
 
 public class SimpleSingleton : MonoBehaviour 
 {
     private static SimpleSingleton instance = null;
     
     // Game Instance Singleton
     public static SimpleSingleton Instance
     {
         get
         { 
             return instance; 
         }
     }
     
     private void Awake()
     {
         // if the singleton hasn't been initialized yet
         if (instance != null && instance != this) 
         {
             Destroy(this.gameObject);
         }
 
         instance = this;
         DontDestroyOnLoad( this.gameObject );
     }
 
     void Update()
     {
         Debug.Log( "SINGLETON UPDATE" );
     }
 }


Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image gjf · Feb 02, 2015 at 10:31 AM 0
Share

http://wiki.unity3d.com/index.php/Singleton

avatar image Glurth · Feb 02, 2015 at 11:54 AM 0
Share

Not really sure... but it looks like you are destroying the gameObject, then saying, to DontDestoyOnLoad it.. um... perhaps, instance = this; should be this = instance;

also, the following would mean it has not been initialized yet (instance==null) so you need to add, near the top... if(instance==null) instance=this;

avatar image Bonfire-Boy · Feb 02, 2015 at 12:23 PM 0
Share

I don't think that trying to assign to the this pointer is the answer to that Glurth. But certainly you're right that all the stuff in Awake after the conditional shouldn't be performed if the Destroy call has been made! I think the answer there is just to put it in an else block.

Also I don't like the look of && instance != this in that conditional. If true it would suggest that Awake is being called for a second time on the same object.

These changes would basically turn the code into what your second para says.

avatar image DTFlip · Feb 02, 2015 at 11:14 PM 0
Share

I tried the method at http://wiki.unity3d.com/index.php/Singleton, but maybe I'm misunderstanding something because it isn't behaving as I expect. Do I need a gameObject with the Singleton on it in every scene? I made a super simple Singleton object based on the URL above and Update() is only being called in the first Scene (where the object lives), and stopping in the second scene (where I currently do not have an object of the singleton). The object looks like:

 public class SimpleSingleton : Singleton<SimpleSingleton> 
 {
     protected SimpleSingleton() {} // guarantee this will be always a singleton only - can't use the constructor!
     
     public string debug$$anonymous$$essage = "THIS IS A SA$$anonymous$$PLE SINGLETON";
 
     void Update()
     {
         Debug.Log ( debug$$anonymous$$essage );
     }
 }
avatar image Bonfire-Boy DTFlip · Jan 09, 2017 at 08:40 PM 0
Share

I'm not sure exactly what's going on there, if the Awake() function in the base class is being called then DontDestroyOnLoad() should be being called, and the object should persist through scene changes. You could start by adding Debug.Log calls to that Awake() function to check it is being called.

One thing that is wrong though is your protected constructor. The class is a $$anonymous$$onoBehaviour so you shouldn't define a constructor at all. It's possible that that's what's messing things up.

And no, you shouldn't need an instance in every scene.

avatar image DTFlip · Feb 02, 2015 at 11:21 PM 0
Share

I just tried placing a copy of this SimpleSingleton object in both Scene01 and Scene02, and replacing the debug$$anonymous$$essage with:

  Debug.Log ( this.GetInstanceID() );

And I'm getting different values when switching between scenes.

6 Replies

· Add your reply
  • Sort: 
avatar image
9

Answer by mostwanted9192 · Feb 02, 2015 at 12:16 PM

I have made my own custom singleton pattern which I use for my games. Its very easy to use. Here's a code snippet which i would like to share with you.

 #region SINGLETON PATTERN
 public static BicycleHandler _instance;
 public static BicycleHandler Instance
 {
     get {
         if (_instance == null)
         {
             _instance = GameObject.FindObjectOfType<BicycleHandler>();
             
             if (_instance == null)
             {
                 GameObject container = new GameObject("Bicycle");
                 _instance = container.AddComponent<BicycleHandler>();
             }
         }
     
         return _instance;
     }
 }
 #endregion


P.S BicycleHandler is the script name of my current script which will be used for any object to make it singleton. And "Bicycle is the object name of my GameObject. Replace them according to yours. After that you will be able to use your singleton object like: scriptName.Instance.function();

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image sunderplugs11 · Jan 09, 2017 at 06:58 AM 1
Share

You are a good person, and a great programmer.

avatar image bisher-d790 · Feb 28, 2020 at 03:02 AM 4
Share

This is the most elegant implementation I've found so far... But you should change the _instance scope to private.


private static BicycleHandler _instance;

Also, for multi-threaded environments, the get method should be synchronised between threads, so you can add this line before the get method:


[$$anonymous$$ethodImpl($$anonymous$$ethodImplOptions.Synchronized)] get { if (instance == null) {...


avatar image
2

Answer by DTFlip · Feb 03, 2015 at 12:00 AM

Well one problem is I'm dumb, I had all my Singleton objects parented to a GameObject that wasn't set to DontDestroyOnLoad... so that fixed pretty much everything. Yay for being a dumb dumb >.<

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Glurth · Feb 03, 2015 at 03:32 AM 0
Share

Well one problem is I'm dumb,

Actually, it takes a genius to realize that about oneself. Obviously, I'm a complete idiot.

avatar image
1

Answer by AndresBarrera · Feb 03, 2015 at 11:07 AM

Also, the function Destroy does not destroys the game object instantly. From the documentation: "Actual object destruction is always delayed until after the current Update loop, but will always be done before rendering."

So in your Awake you should put a return statement to avoid executing the whole function. Try this:

 private void Awake()
 {
    // if the singleton hasn't been initialized yet
    if (instance != null && instance != this)
    {
       Destroy(this.gameObject);
       return;//Avoid doing anything else
    }
 
    instance = this;
    DontDestroyOnLoad( this.gameObject );
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by Brb_Code · Oct 26, 2017 at 10:46 AM

I have developed two version of singleton , both can destroy the component on editor without use the attribue [ExecuteOnEditMode].

GameSingleton only can be added on first built scene and can't be destroyed on load, persist all game. Singleton can be added on any scene but is destroyed on load. Obviously both only let one instance.

This is the Singleton sample:

 public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
 {
     private static T instance;
     public static T Instance
     {
         get
         {
             if (instance == null)
                 instance = FindObjectOfType<T>();
             if (instance == null)
                 Debug.LogError("Singleton<" + typeof(T) + "> instance has been not found.");
             return instance;
         }
     }
 
     protected void Awake()
     {
         if (instance == null)
             instance = this as T;
         else if (instance != this)
             DestroySelf();
     }
 
     protected void OnValidate()
     {
         if (instance == null)
             instance = this as T;
         else if (instance != this)
         {
             Debug.LogError("Singleton<"+this.GetType() + "> already has an instance on scene. Component will be destroyed.");
             #if UNITY_EDITOR
             UnityEditor.EditorApplication.delayCall -= DestroySelf;
             UnityEditor.EditorApplication.delayCall += DestroySelf;    
             #endif
         }
     }
 
    
     private void DestroySelf()
     {
         if(Application.isPlaying)
             Destroy(this);
         else
             DestroyImmediate(this);
     }
 }

The scripts are aviable on my gitHub, https://github.com/Brbcode/BrbAssets/tree/master/Singleton

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Oct 26, 2017 at 11:19 AM 0
Share

You should use a generic constraint like this:

 public class Singleton<T> : $$anonymous$$onoBehaviour where T : Singleton<T>

In your case i can create a class like this:

 public class $$anonymous$$ySingleton : Singleton<SomeOther$$anonymous$$onoBehaviour>
 {
 }

In this case "T" will not be the same type as "this". By forcing the generic constraint on Singleton<T> the type parameter can only be a class that is derived from Singleton<T>

It's still possible to create a second singleton with the type of another singleton which would also not work, but at least you can't pick an arbitrary $$anonymous$$onoBehaviour.

 public $$anonymous$$ySingleton1 : Singleton<$$anonymous$$ySingleton1> { } // <-- works as intended
 public $$anonymous$$ySingleton2 : Singleton<$$anonymous$$ySingleton1> { } // <-- problem here
avatar image Brb_Code · Oct 27, 2017 at 05:40 PM 0
Share

I didn't realize about that problem, thank you to made me realize. I tried rewrite the code following your advice but i didn't find any change.

In order to solve the problem I have add a new check inside OnValidate funtion.

 public $$anonymous$$ySingleton1 : Singleton<$$anonymous$$ySingleton1> { } // <-- works as intended
 public $$anonymous$$ySingleton2 : Singleton<$$anonymous$$ySingleton1> { } // <-- It's removed when is added as component

It's the best solution that I've find.

 using UnityEngine;
 
 /// <summary>
 /// Singleton only let one instace of Type T per scene.
 /// <para>Note: Singleton instance can be destroyed.</para>
 /// </summary>
 /// <typeparam name="T">T inherits from $$anonymous$$onoBehavior</typeparam>
 public class Singleton<T> : $$anonymous$$onoBehaviour where T : Singleton<T>
 {
     private static T instance;
     public static T Instance
     {
         get
         {
             if (instance == null)
                 instance = FindObjectOfType<T>();
             if (instance == null)
                 Debug.LogError("Singleton<" + typeof(T) + "> instance has been not found.");
             return instance;
         }
     }
 
     protected void Awake()
     {
        if (this.GetType() != typeof(T))
             DestroySelf();
 
         if (instance == null)
             instance = this as T;
         else if (instance != this)
             DestroySelf();
     }
 
     protected void OnValidate()
     {
         if (this.GetType() != typeof(T)) //Change to solve the problem
         {
             Debug.LogError("Singleton<"+typeof(T)+ "> has a wrong Type Parameter. " +
                 "Try Singleton<" + this.GetType() + "> ins$$anonymous$$d.");
             #if UNITY_EDITOR
                         UnityEditor.EditorApplication.delayCall -= DestroySelf;
                         UnityEditor.EditorApplication.delayCall += DestroySelf;
             #endif
         }
 
         if (instance == null)
             instance = this as T;
         else if (instance != this)
         {
             Debug.LogError("Singleton<"+this.GetType() + "> already has an instance on scene. Component will be destroyed.");
             #if UNITY_EDITOR
             UnityEditor.EditorApplication.delayCall -= DestroySelf;
             UnityEditor.EditorApplication.delayCall += DestroySelf;
             #endif
         }
     }
 
    
     private void DestroySelf()
     {
         if(Application.isPlaying)
             Destroy(this);
         else
             DestroyImmediate(this);
     }
 }

avatar image
0

Answer by OcarinhaOfTime · Feb 02, 2015 at 11:56 AM

Here you may find what you need (around 22 min): http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/creating-a-scene-menu. Here he makes the background music a "DontDestroyOnLoad" object to have the the same instance of object in multiples scenes and give some tips to guarantee that we have only one instance of this object.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

13 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Preventing my game object from multiplying due to DontDestroyOnLoad() 2 Answers

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

Singleton and DontDestroyOnLoad question 1 Answer

DontDestroyOnLoad Duplicating Objects When Scene Reloaded 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges