Search Unity

Static function or singleton?

Discussion in 'Scripting' started by Deleted User, Aug 18, 2017.

  1. Deleted User

    Deleted User

    Guest

    Hello, please follow me in the dilemma I'm facing. In my game I make everything at runtime, reading from external files and then building what is required.

    I have a monobehaviour where I store and cache loaded and built assets, they are stored in a private static Dictionary, and I get them out from there from a static function. It all works fine and all, my doubt is if I should drop this system and convert the script to a singleton.

    When changing scene I have in place already a system to clear the static dictionary from stuff I don't need aymore then proceed to add new one if the scene requires it. Got a doubt on this too, clearing a static collection will give me back memory, or once is populated it will keep the same memory amount no matter what I do to it?

    Thanks.
     
  2. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    adding static to your class variable makes it automatically a singleton, or Omni. Its how you implemented it that makes a difference. Just like when you add abstract to a class.
     
  3. Deleted User

    Deleted User

    Guest

    Bad explanation on my part, maybe is better to show with an example.

    Would be better this:

    Code (csharp):
    1.  
    2.  private static Dictionary<string, object> _cache = new Dictionary <string, object>();
    3.  
    4. public static object GetCachedObject (string id)
    5. {
    6.  blah blah return object;
    7. }
    8.  
    So basicly I would get back the object from the function by referecinging the script directly, or is better to do like this?

    Code (csharp):
    1.  
    2.  
    3. private Dictionary<string, object> _cache = new Dictionary <string, object>();
    4.  
    5. public object GetCachedObject (string id)
    6. {
    7.  blah blah return object;
    8. }
    9.  
    Using the Instance of the script in this case.

    What would be the cons of having the dictionary static? Just to add to it, this whole thing is done once at scene load, then enver on the fly while playing.
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Static and singleton aren't the same thing. I've also never heard the term Omni.

    "better" is sort of a loaded term. I'm sure you'll get people arguing on either side. If you made it a singleton that didn't survive scene changes and lazily built its cache then you could theoretically reduce some coupling in your code. As you have it now (assuming based on your description) you need to hook scene loads with some logic to clear the existing cache and repopulate it. That would go away if the singleton was simply destroyed with the unloaded scene (assuming you dumped your cache in OnDestroy). Then you could populate the cache in the new scene the first time something else needed it
    Code (csharp):
    1.  
    2. public static void GetInstance()
    3. {
    4.     if (instance == null)
    5.     {
    6.         instance = new GameObject("_cache").AddComponent<Cache>();
    7.         PopulateCache();
    8.     }
    9. }
    10.  
    I'm not saying that is "better" (if your cache takes a long time to populate and causes too much frame latency for instance).
     
  5. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Singleton is a design pattern, class types are used to follow this pattern. There is no other reason to use static other than when your doing singletone. Means you have a single class/variable. Omni means 1 channel or Universal. You can google it.
    When you add the static type to a class it can only be one instance of it, how you design your singletone is up to you,

    AddComponent is expensive, i would rather use something like this:

    Code (CSharp):
    1. public sealed class Singleton
    2. {
    3.     private static Singleton instance = null;
    4.     private static readonly GameObject ThisGameObject  = new GameObject();
    5.  
    6.     Singleton()
    7.     {
    8.     }
    9.  
    10.     public static Singleton Instance
    11.     {
    12.         get
    13.         {
    14.             lock (ThisGameObject )
    15.             {
    16.                 if (instance == null)
    17.                 {
    18.                     instance = new Singleton();
    19.                 }
    20.                 return instance;
    21.             }
    22.         }
    23.     }
    24. }
    Thread safe
     
    Last edited: Aug 18, 2017
  6. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I did and nothing came up in a programming context.

    Disagree. Static utility classes that are stateless, for one.

    True. I misread what you wrote to mean adding static to the class definition.

    No it isn't - and you're doing it once anyway. And if you want your Singleton to also be a MonoBehaviour then the only other way to do it is to manually place it in the scene or make a prefab of it and instantiate. If you don't then obviously that part can be skipped.
     
    Ironmax likes this.
  7. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    I've never heard the "omni" term before either as applied to the singleton pattern, and unless my google-fu is weak this morning, some google searches didn't turn up anything. Even stackoverflow didn't turn up anything unless you're talking about OmniXML. :p

    Anyway, all that's a bit off topic from what the OP wants to know :p
     
    KelsoMRK likes this.
  8. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Not every word in the English dictionary is related to programming, it was just a way of my speaking.. Singleton is a design pattern not a syntax :p I am pretty sure Omni have been used with eCommerce as concept.. (lets not dig ur self out of the topic here)



    Actually when i come to think of it, its more than that. (i was more wrong here) Because you can Implement a Interface in a Singleton, some thing you can not with static , ohh well my bad sorry.

    Back to the OP at hand.
    Try this tutorial on singleton..
    https://unity3d.com/learn/tutorials/projects/2d-roguelike-tutorial/writing-game-manager

    Its pretty much good enough..
     
    Last edited: Aug 19, 2017
  9. Deleted User

    Deleted User

    Guest

    Thanks for the info.
     
  10. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I use pure static most of the time.

    A singleton only makes sense if you need instance like behaviour. There are two cases I find this useful:
    • If you need to access a GameObject.
    • If you regularly need to replace the instance with another one.
     
    Ryiah likes this.
  11. kru

    kru

    Joined:
    Jan 19, 2013
    Posts:
    452
    I know its off topic, but this is not thread safe. If ThisGameObject were of a type System.Object (or similar) then it would be safe. Lock objects should be completely private, as best practice. However, GameObject references are publicly available to any class via Unity's Find* methods. Trouble can ensue.

    As to the topic at hand:

    Prefer singletons over statics, for serialization.

    Prefer services over singletons, for testabilty.

    Prefer injected references over services, for decoupling.

    Each of those preferences comes with increased complexity. Increased complexity should only be considered when the benefits outweigh the overhead.
     
    KelsoMRK and Kiwasi like this.
  12. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Or if the thing being discussed needs to maintain some kind of significant internal state.
     
    Kiwasi likes this.
  13. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,997
    The obvious answer is if you don't have any immediate problems, what you have now is fine. Otherwise you can spend way too much time redoing stuff back and forth for no good reason.

    A Monobehaviour with statics? That's odd. If you have static variables, you may as well use a regular class and not need to attach it to any gameObject. Likewise the advantage of Monobehaviours is you can use the Inspector, and easily make several as needed (but if it works now, don't change it.)
     
    Kiwasi likes this.
  14. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    My experience is that you can never have good enough structure at least one a big game. The back paddling of poor structure code is hard.