From Unity - Scripting API: GameObject.GetComponent, it said that GetComponent() is more efficient than the GetComponent(T) version, it even said to use GetComponent(T) only if necessary which imply that it is very bad on performance. But, why ? How does GetComponent implemented in unity which caused the generic version to be faster ?
No, that is not implied. Efficiency is not only about performance. Also the docs said “not as efficient” which does not imply very bad. The generic version is simply shorter to write as you don’t need to use typeof and you don’t need to type cast the result. So you can use the returned instance immediately.
In the past the generic version was just a wrapper for the non-generic version which did the typeof and the cast inside that method. So technically it was even a bit slower. However the current implementation uses a cast helper struct to avoid the cast all together. In this implementation the native Unity code directly sets the reference in that struct without any additional type checks. So it might be a tiny bit faster compared to doing the cast manually on the managed side. However this is a tiny difference. The generic version is mainly there for convenience and to avoid some mistakes as you only provide the type once.
“not as efficient”
This can mean anything from 0.1% more resource intensive, to infinitely more resource intensive. It does NOT indicate “performance”, it says “efficient”. This could also imply that it’s mainly using less memory or creates less garbage.
In addition, this may hold only true for the Unity editor version for which this part of the manual was written, since such statements are not consistently updated.
Therefore: measure!
I think under the hood, GetComponent<T>()
just calls GetComponent(typeof(T))
, so technically GetComponent(Type) should be “faster” (by faster here I mean by an unmeasurable amount of times, unless called millions of times in a row…)
And both are slower than TryGetComponent(out T)
.
Ok thank you everyone for the answer
If there is really only tiny difference, then unity documentation is just being too dramatic by saying to use it only if necessary, unless there is an actual case where that tiny difference become a big difference.
Correct me if i’m wrong, but in the implementation you linked, GetComponent() will call extern function GetComponentFastPath while GetComponent(T) is an extern function. Is there any actual difference between GetComponentFastPath and GetComponent(T) or they are the same under the hood?
I think you’re hanging onto the wrong thing here: that there would be advantage here which could make up for a lazy architecture.
What Unity scripters should take away from GetComponent
is
- to avoid it wherever it is possible
- if you can’t avoid it on any way, cache the result if possible, so next call won’t be a
GetComponent
- use
TryGetComponent
instead of explicit null-check
You save much more resources if you don’t call it or you cache it than you gain anything switching between the two types of GetComponent
methods.
There are really only rare usecases where you may use the non generic version of GetComponent. Those cases would all have to do with some dynamic gathering of components where you got the System.Type object through other means. For example when you do something like deserialization. Though in that case you usually use AddComponent. GetComponent may also be used when you create some custom animation system and you need to get a binding dynamically.
In the majority of cases you would use the generic version. It works with interfaces as well and you don’t have to do any explicit casting. That’s the main point. Casting in .NET requires the runtime to do a type check. Unity’s implementation does not require a type check as the conversion is done implicitly, essentially through native unsafe code. Though since the native implementation is asked for a specific type, the implicit unsafe cast is essentially safe.
The extra method call doesn’t really matter. The type cast is more important. Just to be clear, in the past the generic version looked like this:
public T GetComponent<T>() where T : Component
{
return (T)GetComponent(typeof(T));
}
Back then this was only for convenience as it still required a cast on the managed side (GetComponent returns a UnityEngine.Object) and this implementation also was constraint on Component. So you couldn’t ues interfaces with this implementation, now you can.
I was curious when this happened as I couldn’t remember, and after poking the chatbot came up with Unity 5.0.
Note that even before Unity 5 GetComponent could be used with interfaces, but not the generic version. Even version 2.6 did support interfaces (which was the first version I actually used something like 13 years ago ^^).
Yes time is passing way too fast considering version 5 is now 9 years old