Easier null checking in Unity?

Paul Marsh
3 min readMar 24, 2021

--

I was reading a fellow developers plight with having to add so many null checks in their code when it made me wonder if it was possible to make life a bit easier with .net extensions.

The Problem

Consider this typical bit of code

What can be done about it?

TryGetComponent

Well obviously my first suggestion would be to use TryGetComponent but whilst that does save a line, you still end with a lot of scoped LogError lines...Dirty.

.net Extension Method

What about something like this;

The above is extending Component with an new overload of GetComponent<T> that includes an error message. Problem solved? Well, yes and a couple of no’s.

When you change the original code it doesn’t work

var fakeComponent = GetComponent<SphereCollider>("Oh no, I need this fake component");

and the why is sort of weird (to me). The compiler doesn’t find the extension. You have to explicitly use good .net standards — ah now I know why you should code properly ;)

var fakeComponent = this.GetComponent<SphereCollider>("Oh no, I need this fake component");

Spot the difference? Whenever you use a call to a method on yourself you’re supposed to be clear by using “this.” Now the extension springs to life.

Yay so we’ve gone from;

To

So much tidier, yay for us, job done?

Problem 1. Error in the wrong place

When you use this code the Unity Console will spit out the debug.LogError but it will be in the extension method and not the calling method. It’s not a massive problem but it’s one to be aware of.

E.g. if my script called SeatShuffle uses the above code then the error message looks like this;

at Assets/CBC/Scripts/Helpers/MonoExtensions.cs:16)
SeatShuffle:Start () (at Assets/CBC/Scripts/Player/SeatShuffle.cs:31)

The hyperlinks to both methods are there so it’s not too bad, but it’s not ideal.

Problem 2. Repeated error messages

Okay, now I’m getting a little crazy. But realistically all the error messages are pretty much going to be the same. “Null found, was expecting X”. Could we avoid that too?

CallerMemberName and/or default message

One of this less used .net attributes that can come in handy. Let’s change our call to just this;

var fakeComponent = this.GetComponent<SphereCollider>();

and add to our extension

In the above example if there wasn’t a sphere collider then we’d see;

“Start: Was expecting SphereCollider in SeatShuffle”

That’s pretty good, and if we really wanted to use our own message we can supply the default message too. Except…it doesn’t work.

The problem with the default param is that it is optional for the signature. Which means the compiler cannot know if our GetComponent call is supposed to use the extension or the original good ole GetComponent code. So we either always supply at least a constant string for the message and lose the CallerMemberName or we change the name of the method, classically in APIs that would mean adding a “Ext” suffix e.g.

public static T GetComponentExt<T>(this Component component  ...

TBH I don’t like that approach I’d rather stick with being forced to use at least some additional message. So we end up with the extension;

and the call looking like

You can get/contribute to the final code at GitHub

--

--

Paul Marsh
Paul Marsh

Written by Paul Marsh

Unity, VR, Enterprise and .Net Developer

No responses yet