How does Unity wiki's Singleton work? - c#

I have a "manager" GameObject in my scene with a Manager Script component attached to it.
I need this Manager script to be a singleton since it makes no sense for there to be several managers.
I used the singleton implementation from the Unity wiki.
I have two questions about it:
Why does it create a new GameObject and then use GameObject.AddComponent<T>() to instantiate the singleton? Why not just do new T()?
I have protected both of my Singleton and Manager class constructors. No one should be able to instantiate these classes except themselves. How does the Unity Editor do to instantiate them?

As the comments say:
MonoBehaviour classes cannot be instanciated with new T() because of the way GameObject components work: they must be attached to a GameObject! As such, the GameObject class provides a way of instantiating a new MonoBehaviour attached to that GameObject: AddComponent<T>() which presumably operates through reflection (other MonoBehaviour methods such as Start() and Update() aren't exactly invoked with reflection, not every frame during runtime, but it's easy to make the comparison that they are; it's about as opaque and magical and has significant overhead, so it may as well be reflection).
Preventing the constructor from being called at all would probably just break everything, so don't bother trying to protect it any more than you already are. Because of the way AddComponent works, calling the constructor through reflection, you can't actually prevent a new instance from being created, but you CAN detect that it happened and do something about. My preferred way is the script going "oh, an instance already exists and its not me" and destroys itself.
Additionally, as components can require other components (RigidBody requires a Collider, MonoBehaviours can specify their own requirements as well) which is specified through an attributes, when AddComponent<T>() is called to add the one component, it will search the class attributes to see if there are any [RequireComponents] specified and add them too, automatically. This would also be done through reflection.

Related

How does Unity execute its methods?

I only have a small experience in Unity3D, but I noticed that classes that derive from MonoBehaviour may contain functions with predefined signatures that will be called in a special way. For instance, if I write:
void Update()
{
//some code
}
this method will be called every frame.
I imagine that inside Unity there is some sort of an endless loop that calls the Update method every frame for each object on the scene. But how does it know that the object actually provides the Update method implementation? It would have been clear if Update was an override for a method in the MonoBehaviour class, but judging by the syntax (and the fact that you can implement such methods with any access modifier) it's not. Is there some reflection magic happening there?
http://blogs.unity3d.com/2015/12/23/1k-update-calls/
No, Unity doesn’t use System.Reflection to find a magic method every
time it needs to call one.
Instead, the first time a MonoBehaviour of a given type is accessed
the underlying script is inspected through scripting runtime (either
Mono or IL2CPP) whether it has any magic methods defined and this
information is cached. If a MonoBehaviour has a specific method it is
added to a proper list, for example if a script has Update method
defined it is added to a list of scripts which need to be updated
every frame.
During the game Unity just iterates through these lists and executes
methods from it — that simple. Also, this is why it doesn’t matter if
your Update method is public or private.

Why are the MonoBehaviour methods not implemented for overriding?

In Unity3d you have the MonoBehaviour class, which is the normal base class for all scripts. When implementing a script, one has to implement the methods such as Awake() or Start() or Update().
However, These methods are not implemented as virtual or abstract in the MonoBehaviour class so that one could easily override them; in fact they are not implemented at all. The method one writes at the Moment is a new method that the class did not have beforehand.
Why are these methods not implemented as virtual or abstract in the base class (MonoBehaviour)?
If you check the documentation you will see that all those 'functions' are listed in the 'Messages' section; MonoBehaviour Doc.
So that means that 'functions' (like Start, OnEnable or Awake), they are not implemented as methods but as messages.
Now, MonoBehaviour inherits from Behaviour, which inherits from Component which has the SendMessage method. That method basically calls a message/method with the option to report an error if the message/method exists or not. The parameter of the name message/method is a string, /~~so they are using reflection there.~~/ Check Update!!
Seems like Unity behind the scenes determines if those messages were implemented to see if it has to call them or not. According to this UnityAnswer:
Unity is mainly written in c++ and therefore most magic happens in
native code. Unity uses reflection to determine, after your scripts
have been compiled, what of those "events" you've implemented and
remember that for this class. Unity only calls Update / LateUpdate /
OnGUI when it has been implemented.
So, the short answer is, they are not 'real' methods that you have to override, they are messages that are called only if they were implemented.
Update;
As #Raining noted, I was wrong in the way that Unity obtains the messages to call.
Unity doesn't use reflection to do this.
According this 1k-update-calls (also provided by #Rainin) scripts are inspected to check if they contain some of those 'magic methods'. If so, they are added to lists that will be executed accordingly.

Can I create game objects from outside monobehaviour

I want to instantiate in a class that is not a monobevaviour.
At the moment I call a helper class to do it but I want to reduce dePendency.
You can simply do this:
MonoBehaviour.Instantiate(ObjectPrefab);
This is because Instantiate is actually static in the MonoBehaviour class.
You can instantiate GameObjects or anything that derives from GameObject. ScriptableObjects are very useful.
If you don't want the Update/Start/Awake/etc. methods that are part of GameObjects, then you can use constructors of any objects that you want to Instantiate and/or create your own Instantiate methods.

How to handle class visibility/access correctly

I'm designing a simple game and I'm not sure how to correctly handle the access and relations between classes. E.g:
Class Game - method Start that will initialiaze objects (fields) Player, CPUPlayer, Board.
Player/CPUPlayer contains a method "Place a pawn" but they would need to access the Board object to check for coordinates.
But they do not see the Board object. Does it mean I need to pass the Board object reference (or any other objects) in their constructor?
Yes, if they have a dependency on that object you need to inject it into them when they are created. The constructor is the right place. Later on, as you get a handle on things, you may want to look into using a DI container like Unity or something, but for now, just receive an instance of the Board in their constructors.
In this particular case, it does indeed seem that they need a reference to a Board object. If you would like to over-engineer that, you could create a specialized interface ICoordinateCheckable, implement it in the Board, and have Player accept an instance of this interface (instead of the Board) in constructor.

C# Ways to access containing class without passing reference

Is there any way to access the containing/enclosing class during initialization (constructor logic) of the nested owned class without needing a reference passed as a constructor parameter?
The reason I don't want to pass a reference to the containing class as a constructor parameter to the nested owned class is because virtually every single object in my program would need it, and it just feels sloppy passing in an argument manually every time that would never change anyways. I want to simplify the programming as much as possible as other team members of mine will be using my engine.
I tried making a method for the container class to use when adding new objects that would take the new instance as a parameter and then set that instance's "container" variable to "this" (the container class), but the nested owned object's initialization code happens first which defeats the purpose (I want to be able to access the container during initialization, so the container variable needs to be set before, not after the constructor code is executed).
Any ways to make this happen? Or am I doomed to manually pass in a reference to the container class every time I make a new nested owned object?
EDIT:
Example:
Let's say I'm making a video game, and the player is going to cast a magic spell that spawns a HealerGoblin:
From Player class:
spawnMonster(new HealerGoblin(30)); //30 = Monster's Combat Level
In HealerGoblin class:
public HealerGoblin(int Level)
{
Owner.Health += Level; //Owner in this case, being the player.
}
As you could probably see, the player would cast the spawn monster spell, select a level 30 healer goblin, and the healer goblin has a special effect when he spawns that increases his owner's health by some amount (in this case equal to the goblin's level). (Keep in mind this is a hypothetical, I know there are other, probably better, ways to do something like this specifically, but this is just an example of what I'm trying to do).
So the problem is, any player or NPC in the game could cast that spell and be the "owner". How would the goblin's Owner property be set by the time that initialization code that references the owner is executed?
I know I could pass the owner by reference:
spawnMonster(new HealerGoblin(this, 30); //First argument being what Owner is set to.
But I want every single object in my program to automatically have a reference to their "owners", and manually putting (this) every time I initialize a new object, and having to set up a new owner parameter to be passed every time I make a new derived class, just seems sloppy and counter-intuitive considering you would never not pass the reference.
So my question is what other ways would there be to do get a reference to the container/owner object before initialization besides passing it by reference through the constructor? If any?
I understand your pain. I've been there too. But the answer is no in a standard way of programming. It maybe possible by using the call stack, reflection and some hack work, but since you are trying to simplify your code, you don't want to have that kind of stuff in your code.
As far as I know. In short there is no such feature.

Categories

Resources