Skip to content

Instantly share code, notes, and snippets.

@lucasmeijer
Last active November 10, 2015 15:08
Show Gist options
  • Save lucasmeijer/7475fd40ff6ac34c7c44 to your computer and use it in GitHub Desktop.
Save lucasmeijer/7475fd40ff6ac34c7c44 to your computer and use it in GitHub Desktop.

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)

@Cotoff
Copy link

Cotoff commented Nov 6, 2015

There are two big cases to use GetComponent call:

  1. During initialization, to obtain references to components you KNOW are there.
  2. During gameplay, to check if a gameobject is of a certain kind (i.e. has a component you need)

In first case, you obviously don't expect to get null at all. In fact, if you get a null, the error has already happened, and exception should be thrown right away.
In second case, getting null reference is actually an expected outcome. If this null value gets used later, it's an error, but the problem is NOT "missing component", but you forgetting to check.

The correct way to handle this would be to add some method (GetRequiredComponent?) that throws right away if component is not found, and have GetComponent return plain nulls. Adding a "special kind of null" is helpful neither to experienced programmers (who dont expect this and get confused), nor to newbies (who now have to learn about a special-case and confusing behaviour - nothing works this way outside of unity)

@AngryAnt
Copy link

AngryAnt commented Nov 7, 2015

I don't see the point in the GetComponent variant of this exception. However is this the same exception thrown if a reference is serialised, but the target then goes missing? That one is very handy indeed and I would hate to see it go.

Compared to the GetComponent call, that scenario clearly highlights a specific bug of unexpected state.

@ZimM-LostPolygon
Copy link

There is a yet another issue with this. I've personally wasted half a day trying to track it out down.

Renderer someRenderer = GetComponent<Renderer> ?? someOtherObject.GetComponent<Renderer>

obviously, this resulted in different results between editor and player, as null coalescence operator ignores operator overload and actually returns the fake-error-string-containing-object instead of branching to the right side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment