Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Null Reference Exception - Found the exception, but isn't this supposed to be null?

Discussion in 'Scripting' started by AdamCNorton, May 9, 2014.

  1. AdamCNorton

    AdamCNorton

    Joined:
    Apr 16, 2013
    Posts:
    57
    Ok, so I understand what a Null Reference Exception is. I even know exactly where mine is happening.

    I have a moving object, casting a ray a few feet ahead of it. When it hit's the player, then the alarm is raised, which makes the object run towards the player. So up until the ray hits the Player, it's NULL, which obviously gives the Null Reference Exception error. So my question is, how do I deal with it being null up until the point that it finds the player? Do I just manually set it to something else?

    The error gets thrown in line 8 where I check if the ray has hit the object named "Character".

    Here's my code where the error happens:

    Code (csharp):
    1. void Alert()
    2.     {
    3.         //Ray2D ray;
    4.         RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.right, 5, collisionMask);
    5.         Debug.DrawLine(transform.position, new Vector3(transform.position.x + 5,transform.position.y,transform.position.z));
    6.         if(hit != null)
    7.         {
    8.             if(hit.collider.name == "Character")
    9.             {
    10.                 Debug.Log("Ray has hit: " + hit.collider.name);
    11.                 alerted = true;
    12.             }
    13.         }
    14.         else
    15.         {
    16.             Debug.Log("Player Not Found");
    17.         }
    18.  
    19.     }
     
    Last edited: May 9, 2014
  2. Loius

    Loius

    Joined:
    Aug 16, 2012
    Posts:
    546
    The 'hit' is never null (since the Raycast initializes it). You actually want to check hit.collider instead:

    if ( hit.collider != null ) { stuff; }
     
  3. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Physics2D.Raycast returns a RaycastHit2D object only if a collider is hit by the ray, otherwise it returns null.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    It should also be noted that RaycastHit2D is a struct, so therefore can never be null (unless your variable was typed as a Nullable<T>, or T? for short).
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    I haven't used the 2d physics in Unity yet, but I know that RaycastHit2d is a struct... I just checked.

    I also just looked that the Physics2d.Raycast method is shaped differently from the 3d Physics.Raycast. In the 3d Physics class it uses an 'out' parameter and returns a bool on success... because RaycastHit is a struct.

    I do NOT know why unity decided to not have the same shape for the 2d physics raycast method. Unless they override the equality operator to test against null correctly. Which is kind of weird, and is inconsistent with their 3d physics API. As well as obfuscates the way structs are supposed to work.

    Shame on unity for that bad design there.

    [edit]

    metadata of the struct:
    Code (csharp):
    1.  
    2. #region Assembly UnityEngine.dll, v0.0.0.0
    3. // C:/Program Files (x86)/Unity/Editor/Data/Managed/UnityEngine.dll
    4. #endregion
    5.  
    6. using System;
    7.  
    8. namespace UnityEngine
    9. {
    10.     public struct RaycastHit2D
    11.     {
    12.  
    13.         public static implicit operator bool(RaycastHit2D hit);
    14.  
    15.         public Collider2D collider { get; }
    16.         public float fraction { get; set; }
    17.         public Vector2 normal { get; set; }
    18.         public Vector2 point { get; set; }
    19.         public Rigidbody2D rigidbody { get; }
    20.         public Transform transform { get; }
    21.  
    22.         public int CompareTo(RaycastHit2D other);
    23.     }
    24. }
    25.  

    ... I'm noticing from the metadata it doesn't override the null comparison. But it does have an implicit bool conversion on it. Try something like:

    Code (csharp):
    1.  
    2. if((bool)hit)
    3. {
    4.     //do stuff
    5. }
    6.  
     
    Last edited: May 9, 2014
  6. AdamCNorton

    AdamCNorton

    Joined:
    Apr 16, 2013
    Posts:
    57
    Thanks! This worked perfectly. It got rid of the error, and behaves exactly as expected. It always seems to be the simple stuff that holds me up...
     
  7. Landern

    Landern

    Joined:
    Dec 21, 2008
    Posts:
    354
    As a side note:
    explicit keyword in c#
    implicit keyword in c#

    explicit requires cast
    implicit does not and is technically the point

    Code (csharp):
    1.  
    2. if(hit)
    3. {
    4.     //do stuff
    5. }
    6.