Hi,
We have a feature that if you do:
m_MyGUiLayer = GetComponent<GUILayer>();
if it turns out there was no GUILayer component, if you later use m_MyGUILayer, instead of getting a NullReferenceException (what you might expect as a c# dev), you get:
MissingComponentException: There is no 'GUILayer' attached to the "Directional Light" game object, but a script is trying to access it.
You probably need to add a GUILayer to the game object "Directional Light". Or your script needs to check if the component is attached before using it.
NewBehaviourScript.Start () (at Assets/NewBehaviourScript.cs:10)
We are able to give a much better error message that contains the type of the component that was requested, the gameobject name of the gameobject that apparently didn't have the component, and it also has "context" of that gameobject, so if you click this message in the console window, the editor will actually "ping" the gameobject in question. We do this only in the editor.
Awesome.
This feature comes at a (editor-only) cost of a c# allocation for that error message string (as well as the fake-null-object that holds the string). Every week, we get a bugreport about "GetComponent() is allocating, this is madness!" from folks that (probably) don't realise that this allocation only happens in the editor.
We're debating wether or not this error message provides enough value compared to cost it brings. (costs: apparently users getting confused about it a lot, us having to deal with a flow of bugreports about it, editor-allocation patterns being different from the player).
Options on the table are:
- Drop the feature, and make GetCompoment() return a normal null instead.
- add GetComponent(bool niceErrorMessageWhenNotFound = true), so that if you care about not having the allocation in the editor, you can tell us to not mak eit.
- not do anything about it.
- fake it, and internally mark this allocation as editor-only, and then have the profiler actually hide the allocation.
I'd love to hear from users if they have ever found the MissingComponentException to be especially helpful, and in which scenarios that was, and how one's workflow would be negatively affected by no longer having this detailed exception.
Thanks, Lucas (you can reply here, or on twitter @lucasmeijer)
Ultimately - while there is a debugging nicety to the message in the IDE - a
NullReferenceException
would still quickly draw attention to the issue: an allocation to the variable has allocatednull
, and (in well-written code, at least) there shouldn't be many candidates for the cause.For me, consistency between development and built environments is worth more than the nicety of the error. (Also, surely when the IDE logs an exception you can/do include the context anyway? I don't have Unity handy to test...)
However, both of those points ignore that it's generally desirable to expose an error as soon as it occurs: it's much more useful to have the error thrown at the assignment instead of 5 seconds later when referencing the null variable. For that reason, I think that an overload/alternative of
GetComponent<T>()
that throws when the component is missing would be most useful. (Ignoring backward compatibility issues, I'd argue this should be the default behaviour of the method.)There are two basic times that
GetComponent
is called, in my experience:when grabbing a component at runtime to check for a behaviour (e.g.: I've just pressed "Use"; does the object in front of me have a
Usable
component?). In this case, you frequently callThe
GetComponent
call would return a null, but you're immediately checking for the null, and the scope ofusable
is likely to be small/short.when wiring up long-term component references (e.g. assigning to private fields from
Awake
orStart
) - where you rarely want to accept a missing component, and so throwing the error at point of allocation makes sense. (I typically throw/log errors manually at this point if components are missing, so that the error is thrown immediately instead of causing problems later.) In this case, an overload that throws when the component is missing will make code shorter and more readable.