13. Null / NullOrInactive

  03. Features No Comments

Init(args) has been designed with inversion of control in mind and aims to make it as easy as possible to work with interfaces instead of specific classes in Unity.

One pain point when using interfaces in Unity is that checking them for null can be problematic. This is because in addition to being actually null, Objects in Unity can also be destroyed. You usually don’t even notice the difference when working with specific classes directly, because the Object class has a custom == operator which internally also checks whether the Object has been destroyed. However when an Object has been assigned to an interface type variable and this is compared against null, the overloaded == operator does not get used. This can result in null reference exceptions when trying to access the members of a destroyed Object.

Player player = FindObjectOfType<Player>();
IPlayer iplayer = player as IPlayer;

Destroy(player);

Debug.Log(player == null);  // Prints true
Debug.Log(iplayer == null); // Prints false
To help with this problem in version a property has been added into every base class in Init(args): Null. When an interface type variable is compared against this Null property it functions just like the overloaded == operator in the Object class and returns true when the instance has been destroyed.
Player player = FindObjectOfType<Player>();
IPlayer iplayer = player as IPlayer;

Destroy(player);

Debug.Log(player == null);  // Prints true
Debug.Log(iplayer == null); // Prints false
Debug.Log(iplayer == Null); // Prints true

It is also possible to utilize this safe null checking inside classes that don’t derive from any of the base classes in Init(args) by importing the static members of the NullExtensions class.

using UnityEngine;
using static Sisus.NullExtensions;

public static class PlainOldClass
{
    public static void Example()
    {
        Player player = Object.FindObjectOfType<Player>();
        IPlayer iplayer = player as IPlayer;

        Object.Destroy(player);

        Debug.Log(player == null);  // Prints true
        Debug.Log(iplayer == null); // Prints false
        Debug.Log(iplayer == Null); // Prints true
    }
}

In addition to the Null property there’s also a new NullOrInactive property. This functions identically to the Null property but also checks if the Object is a component on an inactive GameObject.

Player player = FindObjectOfType<Player>();
IPlayer iplayer = player as IPlayer;

player.gameObject.SetActive(false);

Debug.Log(player.gameObject.activeInHierarchy); // Prints true
Debug.Log(iplayer == NullOrInactive); // Prints true

This functionality can be particularly useful when utilizing Object Pooling and an inactive GameObject is meant to represent an object which doesn’t exist.

Leave a Reply

Your email address will not be published. Required fields are marked *