Erroneous NullReferenceException

I’m hoping someone might help figure out how to eliminate an erroneous NullReferenceException. Here’s the errors I’m getting. They come as a pair.

NullReferenceException: Object reference not set to an instance of an object
CursorController.CursorClick (UnityEngine.InputSystem.InputAction+CallbackContext callbackContext) (at Assets/Scripts/Player/CursorController.cs:171)
UnityEngine.InputSystem.Utilities.DelegateHelpers.InvokeCallbacksSafe[TValue] (UnityEngine.InputSystem.Utilities.CallbackArray`1[System.Action`1[TValue]]& callbacks, TValue argument, System.String callbackName, System.Object context) (at Library/PackageCache/com.unity.inputsystem@1.3.0/InputSystem/Utilities/DelegateHelpers.cs:46)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)
NullReferenceException while executing 'performed' callbacks of 'Player/CursorPrimary[/Mouse/leftButton]'
UnityEngine.InputSystem.LowLevel.NativeInputRuntime/<>c__DisplayClass7_0:<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType,UnityEngineInternal.Input.NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate (UnityEngineInternal.Input.NativeInputUpdateType,intptr)

I’ve cut my code down for easier reading. The quick explanation: CursorRay() projects a ray through the mouse position (iPoint) then outs it’s collisions so that CursorOver() can detect what GameObject the player is hovering over. If the player then clicks on the GameObject, CursorClick() will check it for the component InteractableObjectBase and start any Active() methods inherited by that class.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class CursorController : MonoBehaviour
{
    public GameObject mainPlayer;
    public Camera playerCamera;
    public Vector2 cursorScreenPoint;
    private PlayerInputActions pInputs;
    public Vector2 iPoint;

    private void Awake()
    {
        mainPlayer = transform.root.gameObject;
        playerCamera = Camera.main;
        cursorRange = 40;
        cursorMask = ~(LayerMask.GetMask("Player", "Ignore Raycast"));
        pInputs = new PlayerInputActions();
    }

    private void OnEnable()
    {
        pInputs.Player.CursorPoint.performed += x => iPoint = x.ReadValue<Vector2>();
        pInputs.Player.CursorPrimary.performed += CursorClick;
        pInputs.Player.Enable();
    }

    private void OnDisable()
    {
        pInputs.Player.CursorPoint.performed -= x => iPoint = x.ReadValue<Vector2>();
        pInputs.Player.CursorPrimary.performed -= CursorClick;
        pInputs.Disable();
    }

private void Update()
    {
        cursorScreenPoint = iPoint;
        CursorRay(cursorRange, cursorMask);
        CursorOver();
    }

    public void CursorRay(int rayDepth, LayerMask rayMask)
    {
        Ray ray = playerCamera.ScreenPointToRay(cursorScreenPoint);
        RaycastHit hit;
        cursorRay = Physics.Raycast(ray, out hit, rayDepth, rayMask);
        cursorHit = hit;
    }

    public void CursorOver()
    {
        if (cursorRay)
        {
            overObject = cursorHit.collider.transform.gameObject;
            overParent = cursorHit.collider.transform.root.gameObject;
        }
        else
        {
            overObject = null;
            overParent = null;
        }
    }

    private void CursorClick(InputAction.CallbackContext callbackContext)
    {

//The following line would have been 171 in the unabridged script
        if(overObject.TryGetComponent(out InteractableObjectBase interactable))
        {
            interactable.Activate(mainPlayer);
        }
    }
}

So the problem starts in CursorClick() when the player clicks anything that I haven’t designated as interactable with the InteractableObjectBase component, which would of course return null. I’ve used every iteration of a null check I could think of, but the problem persists. Then again, the debug log also refers to the Input System, so maybe there is something there that I’m not accounting for?

        else
        {
            overObject = null;
            overParent = null;
        }

        // then you have
        if(overObject....)

just quickly, try before the if statement place

if(objectOver == null)
{
    Debug.LogError("objectOver is not set");
    Debug.Break();
}

// your other if statement
....

i suspect you are nullifying the object before processing

1 Like

Sorry, tried it out but it just goobered the script. I’m pretty sure that’s the wrong place to look. overObject is frequently null but has never thrown an error.

The debug log refers to line 171 which would be this:

if(overObject.TryGetComponent(out InteractableObjectBase interactable))

I just don’t understand why that would throw an NullReferenceException error because if(TryGetComponent(out Component component)) should be able to handle a null return. It’s boolean. When it looks for a component either finds it or it doesn’t, thus null.

It will throw an error if overObject itself is null. So if there is a situation where it can be null, you should guard your CursorClick method to prevent it from trying to access a null reference.

EDIT:

The above doesn’t change the fact that you can’t access instance members of null references.

1 Like

Damn, you’re right. I wrapped the whole thing in another null check and that totally took care of it. I’m gonna blame sleep deprivation. Thanks a bunch.

    private void CursorClick(InputAction.CallbackContext callbackContext)
    {
        if (overObject != null)
        {
            if (overObject.TryGetComponent(out InteractableObjectBase interactable))
            {
                interactable.Activate(mainPlayer);
            }
        }
    }
1 Like