- Home /
Lazy initialization of a MonoBehaviour derived class without singleton
I have made myself an gesuture recognition class with C# (similar to Input). The thing is, it is a children of MonoBehaviour (so it cannot be made static) because it needs Update, but I want it to be lazy initialized, so I don´t ever forget to include it in my projects.
I know I could use a singleton to solve this, but I don´t want to write GestureRecognition.Instance
every time I need to check something, I want it to be clean and similar to Unity´s Input. Is this possible?
Thanks.
Answer by GameVortex · Nov 26, 2013 at 12:42 PM
I had an idea. Maybe instead of having the GestureRecognition as child of MonoBehaviour, you put it as a static class and then have a GestureRecognitionUpdater class that controls the update of the GestureRecognition class.
Example:
public class GestureRecognitionUpdater : MonoBehaviour
{
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
private void Update()
{
GestureRecognition.Update();
}
}
And then in the GestureRecognition you could do something like this:
public class GestureRecognition
{
private static bool initialized;
public static void Initialize()
{
if (!initialized)
{
new GameObject("GestureRecognitionUpdate").AddComponent<GestureRecognitionUpdater>();
initialized = true;
}
}
public static void Update()
{
//Do the update stuff
}
public static void GetGesture()
{
Initialize();
//Do the get gesture stuff
}
}
This way you get the static access to all the functions of GestureRecognition class and it also gets Updated each frame and you won't have to double up on writing wrappers for each function.
You would have to either call the Initialize function on all the other functions to check for if the Updater has been initialized, or you have to call the Initialize function on the start of your game.
Answer by Bunny83 · Nov 26, 2013 at 12:17 PM
No need for a second class. You can hide the singleton inside the class itself:
public class GestureRecognition : MonoBehaviour
{
private static GestureRecognition m_Instance = null;
private static GestureRecognition Instance
{
get
{
if (m_Instance == null)
{
m_Instance = (GestureRecognition) FindObjectOfType(typeof(GestureRecognition ));
if (m_Instance == null)
{
m_Instance = (new GamaObject("GestureRecognition")).AddComponent<GestureRecognition>();
}
DontDestroyOnLoad(m_Instance.gameObject);
}
return m_Instance;
}
}
public static void RecognizeGesture()
{
Instance._RecognizeGesture();
}
private void _RecognizeGesture()
{
// do something on the instance
}
private void Update()
{
// ...
}
}
whenever you access one of the static methods of your class it automatically creates an instance. You can't even access Instance from outside since it's only used in other static methods.
That said, to answer the question, it's generally bad design to implement such things the lazy way. That way your class is tightly bound to other classes. For example: If you create your class using Input.touches. You add more and more stuff and everything's working fine. Now you want it to work on PC and web as well... No way without rewriting the whole thing with mouse input.
There are so many great software design patterns out there, but most people pick the worst one (the singleton pattern).
Thank you, specially for the softare design lesson, I find it insteresting and I think I will make some research on what is the best way to hande this.
These are all variations of the singleton design pattern. The best way is what works best for you. I personally use the typical singleton implementation where I use .Instance
to access it. It's not that much extra typing with all the code-complete functionality these days, and it helps you remember that you're using a singleton (+ will make your code more "mainstream", which means other people will have an easier time reading it, helping you, etc).
Answer by Tomer-Barkan · Nov 26, 2013 at 09:56 AM
If it's that important to you not to use the .Instance
part, you could create a static class that will have its own instance and expose all the functionality that your GestureRecognition
class has:
// this is a new class, not the one you created
public class GestureRecognition {
public static GestureRecognitionInternal instance;
public static void RecognizeGesture() {
instance.RecognizeGesture();
}
}
// this is your original class
public class GestureRecognitionInternal : MonoBehaviour {
public void Awake() {
GestureRecognition.instance = this;
}
public void RecognizeGesture() {
// your code here
}
}
Depending on the game, it might be a good idea to add DontDestroyOnLoad to Awake. Othwerwise, if the game loads another level, you might end up with NullReferenceException.
But then I would need to call GestureRecognition.instance, which is the same as before!
No, if you create a static function for each function in your gesture recognition class, such as RecognizeGesture() in my example, then you simply call GestureRecognition.RecognizeGesture()...
The idea behind tbkn answer is that you duplicate methods from GestureRecognitionInternal
class in GestureRecognition
class (btw - this class might be static). If you want to call a method, for example RecognizeGesture()
, you just do
GestureRecognition.RecognizeGesture()
which in turn calls exactly the same method on the stored GestureRecognitionInternal
instance.
To prevent confusion, you can make instance
field private, and introduce method SetInstance
, which you could call in Awake.
public static void SetInstance(GestureRecognitionInternal instance)
{
this.instance = instance;
}
Ok now I understand it, thank you! I still would have the same issue for variables however, although I could solve it with properties... Probably I should bear the ".Instance" because this seems kind of tedious in the long term.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Jumping by using unity input system 1 Answer
New Unity Input System Delay on Keyboard 0 Answers
Flip over an object (smooth transition) 3 Answers