Search Unity

Physics Raycast vs. Physics2D Raycast

Discussion in 'Scripting' started by Zebbi, Mar 24, 2021.

  1. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    Why does Physics Raycast use:
    Code (CSharp):
    1. RaycastHit hit;
    2.             if (Physics.Raycast(transform.position, aimdir, out hit, distanceOfAim, layerMask))
    3.             {
    4.                
    5.             }
    but Physics Raycast2D uses:
    Code (CSharp):
    1.             RaycastHit2D hit = (Physics2D.Raycast(transform.position, aimdir, distanceOfAim, layerMask));
    2.            
    3.             if (hit.collider != null)
    4.             {
    5.  
    6.             }
     
    MushyAvocado likes this.
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I don't know the answer, but my guess is it either has to do with the underlying physics engine API's (2D uses Box2D, while PhysX has been what 3D uses), or they just thought that the way they wrote the 2D version is better. Physics2D was added much later than the original Physics API, and Unity tries to avoid altering important API's unless they have good reason, so they don't unnecessarily break projects and tutorials.
     
    MushyAvocado, Zebbi and lordofduct like this.
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    I've been on these forums for over 10 years (almost 10 years active, longer lurking).

    In all that time I've never seen Unity come out and actually comment on why they made a specific choice with their API (I have seen blogs that sort of talk about it, and I bet a handful of posts might exist... but I doubt it). So I doubt they'll come and answer this one.

    The best we can offer is speculation.

    And as someone who has worked on large teams in corporate settings like Unity's dev team would be. Well... you're often broken into different teams from one another. The 2 APIs were very very likely to be written by different teams all together due to the many years between both development. And no one noticed the difference, or cared about the difference, before releasing it.

    And then once released, as Joe-Censored pointed out, they don't change it really. It'd break upgrading projects from previous versions to new versions (or require developing tools that altered your code on your behalf which can be flawed especially if using 3rd party code/plugins).

    Why?

    Why do you hang your toilet paper the direction you hang it?
     
    Zebbi, Kurt-Dekker and Joe-Censored like this.
  4. Zebbi

    Zebbi

    Joined:
    Jan 17, 2017
    Posts:
    521
    I imagine you're both right, it's definitely easier the second way, which leads me to question why the option to do it both ways for Physics 3D wasn't added?
     
  5. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,073
    Second option is actually worst.
    Structure is going to be copied on return even when no object was hit.

    Now check out this two examples below. You don't have to define RaycastHit hit, outside.
    Code (csharp):
    1.  
    2. RaycastHit[] raycastHits = new RaycastHits[count];
    3. if (Physics.Raycast(transform.position, aimdir, out raycastHits[0], distanceOfAim, layerMask)){
    4. }
    5.  
    6. if (Physics.Raycast(transform.position, aimdir, out RaycastHit hit, distanceOfAim, layerMask)){
    7. }
    8.  
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    I'm with koirat, the original option is the better option for many reasons. But I'm not hear to gripe about that.

    1) I don't use Unity in 2d
    2) It's not like it's going to change. The API is established.
     
    Joe-Censored likes this.
  7. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I don't believe C# allows function overloads with different return types, so they'd have to create a separate raycast function for returning a hit object instead of a bool. But then the naming of the functions won't make sense, since Physics.Raycast still returns a bool, Physics2D.Raycast returns an object, and then the new Physics.RaycastSortOfLike2DVersion returns an object. People would still complain :p

    I've noticed that Unity doesn't like to use a lot of "out" parameters in their API. I don't think they are very beginner friendly for people learning C#. That might have something to do with why the 2D version doesn't use one.
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,455
    This is spot on. Yes. a long time ago the scripting team recommended we don't use "out" like this. When the Physics 2D API was implemented, a lot of the 3D calls were copied and those "outs" were rejected during PRs. Years later I asked about this aspect and I got a shrug. In the last few years, standards have become much more important though.

    The 3D physics team wanted to implement the 2D physics API changes but time and resources never made that easy for them. Same with 3D not having support for "List<T>" which is present in all 2D physics API calls that return multiple results (can use fixed array or list).

    Note that you can also do "if (hit)" too as opposed to "if (hit.collider != null)" which makes it a little cleaner.

    In the end, 3D physics has been there for a very long time and 2D physics is a relative newcomer so new API was implemented using those new standards and we have to adhere to them. That said, API standards has been a battle that Unity devs have been fairly poor at sticking to and standards change/evolve but it's then not so easy to just rewrite an API.

    The above is a real dev story though, not any kind of defense or stating that certain overloads shouldn't exist. I hear you.