Log warning when field with NotNull attribute is not valid

There is NotNull attribute with custom property drawer to make object field red when field is null.

[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
public class NotNullAttribute : Attribute
{
    // ...
}

I wonder if it’s possible to make some editor script that will log warning to console when there is script with null field while that object awakes. I don’t want to inherit from any weird base class, I just want to be able to slap attribute on field and let the magic happen.

The only solution in my head is to have static class with RuntimeInitializeOnLoad, find all objects on scene, iterate fields and log warning when attribute is present. The problem with this method is it does not take into account objects spawned with Instantiate or newly created one. Any ideas?

You can try using Unity’s property bags and property visitor.

In my blog I have created an example where if there are any null fields in a class a warning is logged and if you want you can also substitute some of them with default values.

Property bags are good because you can essentially choose if they will use reflection or code generation and you can also decide if you want to run them with RuntimeInitializeOnLoad, in OnValidate or in the game object’s Awake method as in my example.

Here’s the blog post https://giannisakritidis.com/blog/Property-Bags-Null-Replacement/, I would say it’s more of an intermediate level, not for beginners, but it is only three scripts, the Monobehavior that has the fields, the class that we call in the Awake method and the Visitor class, so it won’t take much time to copy/paste and start playing with them.

EDIT: I also created a public repository for the Unity project, in case anyone prefers accessing it instead of copying the code: https://github.com/meredoth/Property_Bags_Example

2 Likes

You have an IDE. Mine constantly underlines references in yellow to indicate “possible NullReferenceException”. I’m getting annoyed by these to be honest. But there’s a way to autogenerate null-checks ie in Awake.

You could make such an attribute work quite easily.

[NotNull] private GameObject thing;
void Awake
{
    NotNullCheck(this);
}

Then just fill in the code for NotNullCheck. :wink:
Well, the code to scan for fields with attributes and to get that field’s value all through reflection is readily available (ie stackoverflow). Shouldn’t take more than an hour. The property bags would be a more elaborate solution to this, less code but more time wrapping your head around it I suppose.

You could omit the manual call in Awake though. Use, like you said, RuntimeInitializeOnLoad and be sure to use Unity’s TypeCache to scan types with a “check” attribute first, to limit the number of types being checked.

But do note: in this case the attribute can only be on serialized fields, and those with field initializers. Any field that gets initialized in Awake or later cannot be checked because Awake hasn’t run at this point so it will still be null during the check.

The point is I don’t want to create additional awakes, inherit from classes with checks and any other similar stuff. Otherwise I could just slap Debug.Assert() in Awake and call it a day. I wish to add attribute and not worry about anything else.

The same here - interestin API, but unless I am missing something it’s the same problem and I need to call it manually somewhere.

The ideal solution would be some editor script that listens to Instantiate/creation/serialization to run checks without need to call anything else. Also this does not need to run in build, I want some editor only thing just to find not assigned fields in project.
Actually… perhaps it would be possible to create button to find all assets and their serialized classes, then check if there are null fields with certain attribute.

You can also do it like that, even better with an attribute on the class.

This code would need to run from a RuntimeInitializeOnLoad but only from one method, not one for every class you need, would enumerate through reflection all classes in an assembly and then run for the classes that are decorated with an attribute.

Of course you can also do it with attributes on fields and enumerating all fields of all classes for that attribute.

But honestly, I can’t see why such a code would be useful, fields that have not been assigned are very easy to find and fix, and the reflection code that enumerates all the possible classes and fields for an attribute would really make your hitting play in the editor very slow every time.

EDIT: Now that I think of it, on class level would not make sense as it would also check the fields that are assigned in Awake, you would still need an attribute for the class though, so that the reflection would only enumerate the fields with the appropriate attribute of those classes and not all the fields of all the classes in an assembly, because that would be much slower.

An IL weaving framework could be used to inject the necessary code to Awake methods.