NullReferenceException: Object reference not set to an instance of an object CameraRaycaster.Update () (at Assets/Camera & UI/CameraRaycaster.cs:46)

rpg_s01_using_delegates_in_c

#1

Hey I know there’s been a couple of related posts here but I don’t see how I am having the same issues (not confusing static/instance, not missing a particular function call). My game is actually working fine but wanted to see how can I go about resolving this issue? Maybe just where is the problem :slight_smile: ?

Thank you!

Once again the message is:

NullReferenceException: Object reference not set to an instance of an object
CameraRaycaster.Update () (at Assets/Camera & UI/CameraRaycaster.cs:46)


    public delegate void OnLayerChange(); // Declare new delegate type
    public event OnLayerChange layerChangeObservers; // instantiate an observer pool. 

    void Start() //TODO Awake?
    {
        viewCamera = Camera.main;
        // layerChangeObservers += LayerChangeHandler; // add to set of handling functions
        // layerChangeObservers(); // call all of the observers/subscribers/delegates
    }

    void Update()
    {
        // Look for and return priority layer hit
        foreach (Layer layer in layerPriorities)
        {
            var hit = RaycastForLayer(layer);
            if (hit.HasValue)
            {
                raycastHit = hit.Value;
                if(layerHit != layer){
                    layerHit = layer;
                    layerChangeObservers(); //problem here
                }
                return;
            }
        }

        // Otherwise return background hit
        raycastHit.distance = distanceToBackground;
        layerHit = Layer.RaycastEndStop;
    }


#2

Hi,

The line number in your error message is of little use unless you post all of the come from the script in question.

Could you update your post so it has the full script. :slight_smile:

The line you’ve indicated with the comment, you should always wrap these with a Null check, you may not have any subscribers at the time when the delegate is called.

if(layerChangeObservers != null)
{
    layerChangeObservers();
}

#3

Entire Script…sorry! Also please note that adding this doesn’t solve the problem and I was wondering if I am required or if it is best practice to use this within a method referring to the instance.

using UnityEngine;

public class CameraRaycaster : MonoBehaviour
{
    public Layer[] layerPriorities = {
        Layer.Enemy,
        Layer.Walkable
    };

    [SerializeField] float distanceToBackground = 100f;
    Camera viewCamera;

    RaycastHit raycastHit;
    public RaycastHit hit
    {
        get { return raycastHit; }
    }

    Layer layerHit;
    public Layer currentLayerHit
    {
        get { return layerHit; }
    }

    public delegate void OnLayerChange(); // Declare new delegate type
    public event OnLayerChange layerChangeObservers; // instantiate an observer pool. 

    void Start() //TODO Awake?
    {
        viewCamera = Camera.main;
        // layerChangeObservers += LayerChangeHandler; // add to set of handling functions
        // layerChangeObservers(); // call all of the observers/subscribers/delegates
    }

    void Update()
    {
        // Look for and return priority layer hit
        foreach (Layer layer in layerPriorities)
        {
            var hit = RaycastForLayer(layer);
            if (hit.HasValue)
            {
                raycastHit = hit.Value;
                if(layerHit != layer){
                    layerHit = layer;
                    this.layerChangeObservers();
                }
                return;
            }
        }

        // Otherwise return background hit
        raycastHit.distance = distanceToBackground;
        layerHit = Layer.RaycastEndStop;
    }

    RaycastHit? RaycastForLayer(Layer layer)
    {
        int layerMask = 1 << (int)layer; // See Unity docs for mask formation
        Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);

        RaycastHit hit; // used as an out parameter
        bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
        if (hasHit)
        {
            return hit;
        }
        return null;
    }
}

#4

Yes, I thought that might be the case, but the issue is even during game play the error recurs as I hit a different layermask (AKA I switch to pointed at an enemy)


#5

Hi @Rob That null check totally worked! Trying to wrap my head around why after startup that may have been a problem without that null check. Thank you very much for the support!


#6

Hey Corey,

You’re very welcome. Always best to protect against null with delegates, if you do not have any subscribers to the event at the time the delegate is called this error will occur.

I would also recommend using the OnEnable and OnDisable methods for subscribing/un-subscribing to delegates.

Invariably the issue will come down to the order of events, e.g. the delegate being called before the subscribers have subscribed, you could try adding a series of Debug.Log statements in various methods across your scripts and checking any specific script execution order you may have set. Additionally, you could add break points using Visual Studio and step through, monitoring layerChangeObservers.

Hope this helps and glad you can move forward again :slight_smile: