I’m being curious: When we create a script, we inherit from MonoBehaviour class. This means that we can override method “Start”, “Update” and plenty more. But we cannot add the “override” word to any of those methods. So, what are we doing when we declare, for example:
Unity finds those methods when the app starts. MonoBehaviour doesn’t actually implement those methods itself, so there’s nothing to override or hide. If you have some hierarchy beyond MonoBehaviour yourself you can certainly set that up and Unity will respect it.
public class A : MonoBehaviour
{
protected virtual void Start()
{
Debug.Log("A");
}
}
public class B : A
{
protected override void Start()
{
base.Start();
Debug.Log("B");
}
}
Instances of B would log A and B to the console when they are loaded.
Another way without having to use “base”, because you can forget.
public abstract class A : MonoBehaviour
{
protected void Start()
{
Debug.Log("A");
StartCall();
}
protected abstract void StartCall();
}
public class B : A
{
protected override void StartCall()
{
Debug.Log("B");
}
}
Another question is, why unity use reflection since normally it’s more expensive since it can’t be optimized at compile time, at least in java reflection is more expensive than direct calls.
Which is a short answer for “We really don’t know exactly know how Unity does it”. It wouldn’t surprise me if Unity does have some compile time optimizations to make it all happen.
No, there is a post from Unity Blog said that it doesn’t use reflection, because it is the slowest way… And from the documentation you can see that these methods are on the title “Message”, so actually what 2F said are correct.
I’m familiar with the blog post. I note that the blog post also doesn’t say how Unity calls the methods, just that it doesn’t call them by reflection. Calling the methods is different from finding the methods.
There is no other technique to find the methods by name. Unity definitely uses reflection, or something very similar, to initially find the magic methods. Then it probably registers the methods internally so it never has to use reflection to actually call the methods.
Note that SendMessage uses the same basic technique, and is generally considered slow.
Topics are Code generation and Reflection…?
From the performance optimization aspect,
My guess is almost the same to Kiwasi.
From initial time (attach script component to the game object),
mask callback slots, and build method tables using reflection (and some name magic)
During play time, engine will check the callback slots, and call that method.
With regards to the code generation…,
I have no idea about the benefit to the coder writing callback method without override or new keywords.
If these keywords is necessary to the C# compiler, Unity might select definitely not to omit the keywords.
Then, there are no other beneficial code chunks left to generate, i think.
The blog emphasizes the fact Unity “searches” for the methods the first time a Monobehaviour class is loaded, then uses the cached result to actually call the method later.
Since this comes from the C++ side of the engine, they might have more direct methods of iterating over a type’s methods than plain C# reflection, but I’m not too familiar with the Mono plumbing to know whether it is possible like it is in Java’s C API bridge.