Hello This post is just meant to be proof for a friend of mine, and I thought it would be wise to share it here so others won't make the same mistake. I had a friend of mine who told me that using GameObject.FindWithTag() is much faster and a more professional replacement to Singletons. I ran some tests with this: P.S: AudioManager is a singleton GameObject with an "Audio Manager" tag. Code (CSharp): public void Init() { const int max = 1000000; var s1 = Stopwatch.StartNew(); for(int i = 0; i < max; i++) { AudioManager.Instance.Test(0); AudioManager.Instance.Test(0); } s1.Stop(); var s2 = Stopwatch.StartNew(); for(int i = 0; i < max; i++) { GameObject.FindWithTag("Audio Manager").GetComponent<AudioManager>().Test (0); GameObject.FindWithTag("Audio Manager").GetComponent<AudioManager>().Test (0); } s2.Stop(); var res1 = (double)(s1.Elapsed.TotalMilliseconds * 1000000) / max; var res2 = (double)(s2.Elapsed.TotalMilliseconds * 1000000) / max; UnityEngine.Debug.Log ("res1: " + res1.ToString("0.00 ns")); UnityEngine.Debug.Log ("res2: " + res2.ToString("0.00 ns")); } The results came out like this: In the given test conditions, singletons were 10 times as fast. Singletons are FREAKIN' FANTASTIC, but has to be used wisely... For more info and alternative: check out these two sources: One Two
I always wonder how someone can find a string based method call professional. I would even use non string based methods if they were slower. If someone renames a tag, a game object or something else in a project, it shouldn't have any impact on the code.
i have been rather partial to doing singletons like this. Code (CSharp): using UnityEngine; using System.Collections; public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour { protected static T instance; public static T Instance { get { if (instance == null) { instance = (T)FindObjectOfType<T>(); if (instance == null) { Debug.LogError("An instance of " + typeof(T) + " is needed in the scene, but there is none."); } } return instance; } } } Code (CSharp): using UnityEngine; using System.Collections; public class GameManager : Singleton<GameManager> { private int myInt; public static void DoGMShit() { Instance.myint = 4; } } Lets me isolate all the singleton initialization code, while giving a easy way to access a instance publicly using Instance, and is cached statically to help performance and to prevent having to look for the instance every time.
Of course it's faster, Find single functions might loop thought all scene object in the worst case. While by singleton you access hard coded reference. There's even nothing to compare here to be honest. Doing it once and caching the reference doesn't sound that bad either. But I've seen code where find functions are used 20 times in an update. Personally i don't use any Unity Find fucntions, but create my own pools.
Right tool for the right job. You are comparing apples with oranges here. The job of a singleton is not the same as the job of a tag. There are also plenty of non performance factors to consider here. There are actually only a few cases where a singleton is the right solution.
This might be the most biased performance test I've ever seen. Compare them like you would use them in the real world: Code (csharp): var s2 = Stopwatch.StartNew(); var audioManager = GameObject.FindWithTag("Audio Manager").GetComponent<AudioManager>(); for(int i = 0; i < max; i++) { audioManager.Test(0); audioManager.Test(0); } s2.Stop(); Singletons are bad design and you should avoid them whenever possible to keep your codebase modular and reuseable.
Agreed. I wish Unity had more built-in tools to deal with this (like auto-creating enums/constants for tags/layers with proper renaming support). I believe string-based search solutions for things like Tags and Layers (not to mention method calls, like in SendMessage) are bad design and prone to not so easy to spot errors.
Singletons are not bad design. Some people avoid them like the plague, but they are not bad. They are a viable solution to many problems (Audio, logging, file management, etc...). Correct me if I am wrong, but the general consensus agree that Singletons are bad when they encourage coupling, when they are used wrongly in multi-threading situations, and because they offer an "overkill" solution to a simple problem (Most of the time). But, if the developer used them sparingly and smartly, they wouldn't offer a problem. Personally, I'd prefer a decent observer and service locator pattern, but I would use a singleton for audio management, and as a "Director/HoldAllManagers" manner like this: Code (CSharp): Director.Instance.GetAtlasManager().CreateSprite("mySprite"); P.S: The idea for the above came from Game Programming Patterns by Robert Nystrom. EDIT: One more question, please. I can understand that string-based call methods are not very optimal, but they are necessary for a messaging system, right ?? I am referring to the Advanced C# Messanger from the wiki.
No, they are not required. They can be designed differently. There are several solutions for that. You may e.g. have a delegate for each kind of message, which automatically eliminates the need for strings. The very minimum one should do when using string based calls is to use constant strings that are defined globally and everyone can get the same one in order to avoid typos.
I did some research and found the "Type-Safe Enums" pattern which works great with what you said. Thanks for the tip. +1
This Code (csharp): AudioManager.Instance.Test(0); is faster than this Code (csharp): GameObject.FindWithTag("Audio Manager").GetComponent<AudioManager>().Test (0); not because it's a singleton, but because that second line is a bazillion slow function calls just to get to the Test() function call. In the first case you have a reference pointed already to the AudioManager object (singleton or not), then calling the Test() function directly. In the second case you're calling several functions just to get a reference to the AudioManager object so you can call the Test() function which takes an eternity. This is why the first method is faster, it has nothing to do with it being a singleton. You could have an AudioManager array of many AudioManager objects and get the same results. This article I wrote some time ago might help shed a little light on function call overhead. This is geared toward math and physics in Unity, but the same principle applies. http://www.performancesimulations.c...ses-in-unitys-physics-or-any-math-heavy-code/
This is a very good suggestion. And in general strings based methods should be avoided, especially if the strings are defined by the coder. There are some situations were stings are the only way to go though. Communicating between different systems using different frame works for example. Or communicating with scripts and code that was not available to the coder or compiler at the time of production of the code.
I agree. There are certainly situations in which it can't be avoided. In Unity that is e.g. required when a material modifies a shader property or in Mecanim it is required too. But also in those situations, it may be possible to check during the initialization whether the strings are valid to avoid issues with not frequently used options. Do you have an example for what you mean with different systems using different frame works? Do you mean something within Unity or something external?
I am not really a fan of this approach, as it has an unnecessary indirection. In most situations that I have faced, it wasn't necessary to have that indirection and I could directly work with whatever I needed. If you have to pass the enum to get what you want, you know anyways what you want, based on the enum and as such you can access it directly. Of course in Unity, you may configure something in the inspector where you specify an enum value. But that is often abused in my opinion. With that approach, we can get a situation where we pass an enum in order to get something back, but if there is nothing for this enum, we have a problem. I can also run into initialization problems, e.g. when someone makes a query for a certain enum, but the dictionary wasn't initialized yet. When I call the thing I want directly, there is the advantage of compile time warning. When I query something that doesn't exist, I get a compile time error. When I extend the enum with another entry, but forget to initialize the dictionary, there is no warning. If it is not properly tested, it can have consequences at some point in the future, which could often be avoided.
just use what is best for the job, events and delagates are sometimes the key, sometimes its singletons. in situations where i cant avoid strings i will usually have static class full of string constants, so i can avoid typos. In the case of animations i will often just use hashes for state names, with static constants that refer to them.
Well you described one in your post, communicating with shaders. It could also be communicating externally, like contacting a web service. Internet based applications depend on strings heavily because you never know what kind of system is on the receiving end. You don't know the word size they operate on, the word format, the OS, the processor type, nothing. You could be communicating with a water droplet based processor (http://www.engadget.com/2015/06/10/water-droplet-computer/).
Of course, web services are using strings. However, the communication is usually using e.g. Xml or Json. Those have been developed exactly to avoid issues with strings by providing a standard solution to make them better accessible. Yes, I missed that case.