Please Make NullReferenceExceptions More Verbose in a Future Version of Unity!

One of those nuances that always bugged me about Unity is the NullReferenceException error. It’s a necessary error, and gets the job done. However, sometimes you find you’ve got an object with an object inside of it. Like this:

bool isDarth = deathStar.xWing.pilot.sithLord;

Let’s say something happened in code that caused one of those objects to be invalid. We’d get a message like this in the console:

The problem here is that the NullReference issue could be on the deathStar object, the xWing object or the pilot object (assuming sithLord is a boolean). Which means to track down the issue, we have to do something like this:

Debug.Log("deathStar = " + deathStar);
Debug.Log("xWing = " + deathStar.xWing);
Debug.Log("pilot = " + deathStar.xWing.pilot);

And from there, run the code again and see which of THOSE lines that it NullRef’s on. Then we can see where the problem lies.

My point of all this is to say it would be great if the initial NullRef error could be a little more verbose. Something like the following:

Wouldn’t that be awesome?

Yeah, I was thinking the same thing one time …
This would be quite nice.

Edit: But I’m not sure how much of this is in Unity’s control. It might be restricted by what the C# runtime gives Unity.

That’s pretty much the way the standard .NET Null Reference exception works - the best solution would be to code defensively:

if (deathStar == null || deathStar.xWing == null ||  deathStar.xWing.pilot == null) 
     SetupPilotOrThrowCustomException();

bool isDarth = deathStar.xWing.pilot.sithLord;

Alternatively, just move each property onto it’s own line - then you could match the one causing the problem by the line number reported:

var xWing = deathStar.xWing;
var pilot = xWing.pilot;
bool isDarth = pilot.sithLord;

This forum needs a way to Like posts. Good advice, minionnz!

Yeah, it’s not a Unity thing, it’s the way that .NET / Mono works.

Assuming that this is for stuff that doesn’t happen often, minionnz approach is a pretty good one - when you need stuff check that it’s there.

If it’s for stuff that does happen often (ie: multiple times per frame) then I’d suggest splitting it into an initialisation phase and a per-frame phase. The init phase makes sure that the per-frame phase has everything it needs and throws an error if it does not.

One of the downsides to Unity is how much global access there is to everything, though. The latter approach works quite well, but you need to be disciplined about not accessing things outside of an object’s logical scope, because if you do then you’re at a huge risk of screwing something up that you’re previously initialized. Just because I can find something through the scene graph and mess with it does not mean that I should! Be disciplined about maintaining object responsibilities and sticking to them, and get practice at designing how that will work ahead of time.

Couldn’t agree more with you, angrypenguin. You wouldn’t believe how much code I review that has things like this in it:

GameObject.Find("SomeOtherObject").GetComponent<ThisComponent>().UpdatePosition(transform.position);

And the above would be run in the update cycle. A very surprising amount of developers in Unity write code like that… something that would be good for the community as a whole to try and teach early devs not to do (and why not to do it).

Yeah, there’s rather a lot wrong with that code. :slight_smile:

I think that a lot of people get that kind of things from tutes. Unfortunately, there’s two things they don’t realise.

First, many Unity tutes are made by people who are not experts or even particularly (or at all!) experienced, and these are often full of crap. Unfortunately if you’re new yourself you often don’t know how to spot a good tute from a crap one.

Secondly, even good tutes have code that’s not necessarily best practice because the purpose of the tute is to demonstrate some specific thing, not to teach you how to code in general. Tutes often have code that makes wild assumptions or performs poorly because the point is to demonstrate how something works or how to use an API or whatever it is. You’re not meant to copy the code, you’re meant to go over the tute, learn the things you need to learn, then implement them properly yourself in your own code. (After all, if you could just copy-paste it then there’d actually be no need for a tute in the first place, because instead of coding something you’d just drop a ready-to-go thing into your game.)

Dear Honda,

I note that your current range of cars all have a air-bag feature. This feature deploys an air bag when the vehicle is involved in a collision. I own one of your cars, and as yet, have not needed this feature. I think Honda should urgently consider adding a new feature to their airbag system. Some seconds before the airbag deploys the car should warn the driver that the car will shortly be involved in a collision, and that the airbag is being prepared. I do not think it is the drivers responsibility to check the road conditions and avoid collisions. It’s Honda’s responsibility to design the car to warn the driver.

Kind regards,
Graham

(The airbag and the null reference are used when something bad has happened. The assumption is that the driver, and the coder, are vigilant enough to avoid needing these systems.)

Though you have a point Graham, nobody stated it’s Unitys responsibility to add this “feature”. It just would be a great thing to have for some people :slight_smile:

I agree. And until Honda add this new anti-crash feature, it’s remains the driver’s responsibility to not crash. :wink:

My amateurish solution is to usually do something like this:

#boo
try: DoStuff(whatever)
except: raise "DoStuff() failure, received $(whatever) as $(whatever.GetType())"

Why not remove null reference notification altogether? If the user should be smart enough to just know when they occur, they shouldn’t ever need it.

Hell, why not remove notification for all exceptions!

Because people are not as vigilant as they should be. If I drove like I code, I would’ve been banned from driving years ago :slight_smile:

There are some exceptions outside of our control - especially those thrown by third-party plugins/libraries - which you’d have to catch and handle in your code.
They have their place in the framework, but throwing an exception (in most cases) should be a last resort - ie: When there’s no way to recover from the situation.
I do agree that you should know what exceptions can be thrown from your code - if you don’t then you need to do some more testing/handling. Nothing is ever bug free though.

Also, I believe there are technical reasons why more detail isn’t included.

Except that’s missing the point, isn’t it? The OP didn’t say they wanted a somehow omniscient system that detects when a null reference will happen in the future and tell us how to fix it. They simply want the null reference exception to be more descriptive when it occurs to save time during development. You know, a better tool to help them do their job a little more effectively, as opposed to some magic that does it for them.

In the sense of a deployed build, yes, it’s quite reasonable to expect that a null ref exception is something that results from a lack of vigilance and is a last ditch effort to not crash. But in a development environment they’re a tool that should help you craft that vigilance in the first place. As mentioned, there are practices that do indeed make what’s being asked for irrelevant in a build, but we don’t always get to control 100% of the code we work with during development.

The existence of exceptions is itself evidence that we can’t rely on people not to cause them to be thrown. :wink:

But yeah, I’m also under the impression that this would actually be pretty difficult to implement for some cases.

@op: You can also attach your monodevelop and then use Run → Exceptions to configure “break on nullreferenceexception”. This will allow you to inspect the variables without needing to change your code.

To the OP: It’s actually not possible to do what you want because the runtime doesn’t know the variable name or type of the null reference. Since the reference is null, there is no object to get that information from. There is a good explanation of the problem here:

http://stackoverflow.com/questions/4719047/why-doesnt-nullreferenceexception-contain-information-about-what-is-null

Note that in some cases - such as accessing a public GameObject variable that hasn’t been wired up in the inspector - Unity already does tell you which variable is null.