Search Unity

Why isn't RaycastHit nullable and turned into the return value of Physics.Raycast?

Discussion in 'Physics' started by Kikbow, May 4, 2020.

  1. Kikbow

    Kikbow

    Joined:
    Jun 13, 2019
    Posts:
    2
    As it is Physics.Raycast returns a bool, and you have the option to add an out parameter to get the RaycastHit variable information.

    Why?

    You could remove the out parameter entirely and just return RaycastHit which seems cleaner, making the RaycastHit class/struct nullable to keep the ability to use Physics.Raycast directly in if calls
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    It allows for really clean if statements:
    Code (CSharp):
    1. if (Physics.Raycast(ray, out RaycastHit result)) {
    2.   // got a hit!
    3. }
    if you returned a nullable RaycastHit you would have to do something a bit more complicated:
    Code (CSharp):
    1. var result = Physics.NullableRaycast(ray);
    2. if (result.HasValue) {
    3.   // we got a hit!
    4. }
    There may also be memory management advantages - you can reuse the same RaycastHit struct over and over again with the "out" formulation. Feel free to write your own wrapper if you would prefer it though:
    Code (CSharp):
    1. public static RaycastHit? RaycastWrapper(Ray ray) {
    2.   if (Physics.Raycast(ray, out RaycastHit result)) {
    3.     return result;
    4.   }
    5.   return null;
    6. }
     
    SparrowGS and Kikbow like this.
  3. Kikbow

    Kikbow

    Joined:
    Jun 13, 2019
    Posts:
    2
    Oh, I was under the assumption that
    if(null) == false
    (and trying it now I see that very few variables are nullable, maybe I'm confusing with C)
    I got confused into thinking this way because this works:
    Code (CSharp):
    1. GameObject object;
    2. Ray ray = new Ray(Vector3.one, Vector3.one);
    3. RaycastHit hitInfo;
    4.  
    5. Physics.Raycast(ray, out RaycastHit result);
    6.  
    7. if(object)
    8.   print("the object exists!");
    9. if(hitInfo.collider)
    10.   print("the raycast hit a collider!");
    I was assuming that
    object
    and
    hitInfo.collider
    were set to null before being set to something.
    If it isn't that, how do they work as both bools and their respective types and why can't this be the same for
    RaycastHit
    ?
     
    Last edited: May 5, 2020
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    The reason it works in your example above is because Unity has provided a custom operator for its base object class that allows automatic conversion to bool: https://docs.unity3d.com/ScriptReference/Object-operator_Object.html

    They are taking advantage of a builtin C# feature to define this automatic conversion: https://docs.microsoft.com/en-us/do...e/operators/user-defined-conversion-operators

    Since RaycastHit is not an object but a struct (which is a value type, not a reference type), it doesn't work for that, nor does it work for anything that doesn't extend from UnityEngine.Object
     
    Kikbow likes this.