I know that we should avoid scripts to be dependent of each other. That's why I'm wondering if putting a script in a UnityEvent in the Inspector makes the script which owns this UnityEvent, dependent on the one called.
For instance, I have a script ScriptWithEvent.cs which has a UnityEvent. In the inspector I add an event to this UnityEvent which calls the method Open() inside an other script OtherScript.cs. Inside this script I have another method which changes a component active state linked to a GameObject containing ScriptWithEvent.cs or a public variable inside ScriptWithEvent.cs.
Does this make ScriptWithEvent.cs and OtherScript.cs dependent on each other ?
Does UnityEvent creates a dependency on the scripts we make it call ?
No it does not, UnityEvent takes a UnityAction which is a pointer to a method.
The script holding the UnityEvent does not know about the type of the method holder nor does it know about the content of the method. In the same way, a C# event would not know about the registered method, only that they need to match the delegate signature.
Your UnityEvent is a list of addresses where to find the methods to be run when invoke is called. But it is totally oblivious to what type it is stored in.
The only dependency for UnityEvent is that the method has to be stored in a MonoBehaviour and the method signature has some limitations.
UnityEvent has this advantage over normal C# event, in the latter the subscriber would need to find out how to register to the type or interface
UnityEvent via inspector removes that dependency as you can drag anything.
Related
I need to write a script that will call methods in another scripts on key events. How to write it to I could specify event type (i.e. using custom enum), game object, script, method and arguments.
In short I need to realize similar functionality as for Button script:
For example I choose an event Escape, a game object Main camera, my another script that attached to this game object GameManager, method Exit and its arguments (there aren't arguments in Exit method but it can be in others).
Is it possible to make so in the custom script?
What you're looking at there is a class field of type UnityEvent called OnClick. Here's the code for it:
public class ClickEvent : MonoBehaviour {
public UnityEngine.Events.UnityEvent OnClick;
public void Update() {
if (Input.GetMouseButtonDown(0))
OnClick.Invoke();
}
}
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.
This question already has an answer here:
How does Unity execute its methods?
(1 answer)
Closed 2 years ago.
How does Unity call the Awake, Update, and Start methods behind the scene? That they have no access modifier to me indicates they are private methods, and they don't use anything like new or override, so how does the Unity framework find the methods to call them?
On a related question, is there any particular reason virtual methods were not used?
Edit: For those unfamiliar with Unity scripts, this is how they generally appear:
public class MyClass : MonoBehaviour{
void Start(){
}
void Awake(){
}
void Update(){
}
}
What I don't understand is how the framework finds and automatically calls those methods for each script when, by all appearances, they look to just be private methods
Here is a piece of information in a Unity blog post
HOW UPDATE IS CALLED
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.
The reason the methods are not virtual is for performance. If it were virtual then every single MonoBehaviour would need all of the relevant methods called (Start, Awake, Update, FixedUpdate, etc.) which is a Bad Thing.
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.
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.