Search Unity

Delegates working, but giving constant errors

Discussion in 'Scripting' started by LoekvanKooten, Mar 1, 2019.

  1. LoekvanKooten

    LoekvanKooten

    Joined:
    Apr 3, 2017
    Posts:
    120
    This started happening all of a sudden. Unity no longer sees subscribers to events and says that all events are null.

    CameraRayCaster.cs
    Code (CSharp):
    1.         public delegate void OnMouseOverTerrain(Vector3 destination); // declare new delegate type
    2.         public event OnMouseOverTerrain onMouseOverPotentiallyWalkable; // instantiate an observer set
    3.  
    4.         public delegate void OnMouseOverEnemy(Enemy enemy); // declare new delegate type
    5.         public event OnMouseOverEnemy onMouseOverEnemy; // instantiate an observer set
    6.  
    7.         public delegate void OnMouseOverPickable(GameObject pickable);
    8.         public event OnMouseOverPickable onMouseOverPickable;
    9.  
    10.         public delegate void OnMouseOverUsable(GameObject usable);
    11.         public event OnMouseOverUsable onMouseOverUsable;
    Code (CSharp):
    1.         bool RaycastForPotentiallyWalkable(Ray ray)
    2.         {
    3.             RaycastHit hitInfo;
    4.             LayerMask potentiallyWalkableLayer = 1 << POTENTIALLY_WALKABLE_LAYER;
    5.             // Gives true if ray hits the potentiallyWalkableLayer
    6.             bool potentiallyWalkableHit = Physics.Raycast(ray, out hitInfo, maxRaycastDepth, potentiallyWalkableLayer);
    7.             if (potentiallyWalkableHit)
    8.             {
    9.                 Cursor.SetCursor(walkCursor, cursorHotspot, CursorMode.Auto);
    10.                 onMouseOverPotentiallyWalkable(hitInfo.point); // Broadcast the point I hit to observers interested in "I hit potentiallyWalkableLayer"
    11.                 return true;
    12.             }
    13.             return false;
    14.         }
    onMouseOverPotentiallyWalkable(hitInfo.point); is giving constant errors (Object reference not set to an instance of an object).

    The subscribers don't get triggered anymore either, so for some reason Unity is no longer detecting that the delegates have actual subscribers.

    However, PlayerMovement.cs for example says:
    Code (CSharp):
    1.             cameraRaycaster.onMouseOverPotentiallyWalkable += OnMouseOverPotentiallyWalkable;
    2.             cameraRaycaster.onMouseOverEnemy += OnMouseClickEnemy;
    3.             cameraRaycaster.onMouseOverPickable += OnMouseClickPickable;
    4.             cameraRaycaster.onMouseOverUsable += OnMouseClickUsable;
    This happens with each and single raycast below in CameraRayCaster.cs:

    Code (CSharp):
    1.         void PerformRaycasts3D()
    2.         {
    3.             // Only raycast if cursor is inside game window (else we get null errors)
    4.             if (currentScreenRect.Contains(Input.mousePosition))
    5.             {
    6.                 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    7.                 // Specify layer priorities below
    8.                 if (RaycastForEnemy(ray)) { return; }
    9.                 if (RaycastForPickable(ray)) { return; }
    10.                 if (RaycastForUsable(ray)) { return; }
    11.                 if (RaycastForPotentiallyWalkable(ray)) { return; }
    12.             }
    13.         }
    How come?
     
    Last edited: Mar 1, 2019
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,539
    Do you have more than one CameraRaycaster in your scene?

    Maybe there are multiple, and one of them doesn't have any subscribers.

    When firing off an event/delegate you should test if it's null or not first... or in newer versions of C# you can even use the null check operator:
    Code (csharp):
    1. onMouseOverPotentiallyWalkable?.Invoke(hitinfo.point);
    Mind you the dispatcher should not rely on a subscriber always existing... there is always the potential of no subscribers. So it should resolve for that scenario.
     
    LoekvanKooten likes this.
  3. LoekvanKooten

    LoekvanKooten

    Joined:
    Apr 3, 2017
    Posts:
    120
    There is only one CameraRaycaster.

    My original info was wrong though: there is indeed a null condition, as the subcribers (they are there) are no longer detected (ever). But they are there (see amended posting).
     
  4. LoekvanKooten

    LoekvanKooten

    Joined:
    Apr 3, 2017
    Posts:
    120
    Argh! Solved.

    This was the beginning of PlayerMovement.cs:

    Code (CSharp):
    1.         void Start()
    2.         {
    3.             ...blablabla...
    4.             waypoints = GameObject.Find("Waypoints").gameObject;
    5.             ...blablabla...
    6.             cameraRaycaster.onMouseOverPotentiallyWalkable += OnMouseOverPotentiallyWalkable;
    7.             cameraRaycaster.onMouseOverEnemy += OnMouseClickEnemy;
    8.             cameraRaycaster.onMouseOverPickable += OnMouseClickPickable;
    9.             cameraRaycaster.onMouseOverUsable += OnMouseClickUsable;
    10.         }
    The name of Waypoints had been changed to WanderWaypoints.

    It couldn't find Waypoints, and thus never got to actually subscribing to the delegates.

    Lesson learnt. Don't use string references. Ever.

    Sorry for wasting your time!