Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Line Renderer/ Raycast troubles

Discussion in '2D' started by jsull1, Jan 14, 2020.

  1. jsull1

    jsull1

    Joined:
    Apr 3, 2018
    Posts:
    121
    I'm using raycast2D to move my ray, then Vector2.reflect, then connecting the hit points with line renderer. When I use this, the second line flashes and sometimes doesn't connect at all. I unfortunately don't know how to start solving this problem because I'm not familiar with any of these. If anyone has a similar experience or a theory as to why this is happening please let me know thank you!

    Here is my code:

    Code (CSharp):
    1. if (Ray)
    2.         {
    3.             LaserOrigin.transform.rotation = Quaternion.Euler(0.0f, 0.0f, AnglesOfJoystick - 90.0f);
    4.             Ray2D ray = new Ray2D(LaserOrigin.position, LaserOrigin.transform.up);
    5.             RaycastHit2D hit = Physics2D.Raycast(LaserOrigin.position, LaserOrigin.transform.up, 50.0f, 11);
    6.             lineRenderer.SetPosition(0, LaserOrigin.position);
    7.  
    8.             if (Physics2D.Raycast(LaserOrigin.position, LaserOrigin.transform.up, 50.0f, 11))
    9.             {
    10.                 Debug.DrawLine(LaserOrigin.transform.position, hit.point, Color.green);
    11.                 Vector3 ReflectionDirection = Vector3.Reflect(LaserOrigin.transform.up, hit.normal);
    12.                 lineRenderer.positionCount = 2;
    13.                 lineRenderer.SetPosition(1, hit.point);
    14.                 RaycastHit2D hit2 = Physics2D.Raycast(hit.point, ReflectionDirection);
    15.  
    16.  
    17.                 if (hit2)
    18.                 {
    19.                     lineRenderer.positionCount = 3;
    20.                     Debug.DrawLine(hit.point, hit2.point, Color.green);
    21.                     lineRenderer.SetPosition(2, hit2.point);
    22.                 }
    23.  
    24.                 else
    25.                 {
    26.                     lineRenderer.positionCount = 3;
    27.                     Ray LaserBounceMiss = new Ray(hit.point, ReflectionDirection);
    28.                     Debug.DrawLine(hit.point, LaserBounceMiss.GetPoint(10.0f), Color.red);
    29.                     lineRenderer.SetPosition(2, LaserBounceMiss.GetPoint(10.0f));
    30.                 }
    31.  
    32.             }
    33.             else
    34.             {
    35.                 Debug.DrawLine(LaserOrigin.transform.position, LaserTargetForNonHit.position, Color.red);
    36.                 lineRenderer.positionCount = 2;
    37.                 lineRenderer.SetPosition(1, LaserTargetForNonHit.position);
    38.             }
    39.         }
     

    Attached Files:

  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Check out Physics2D.Raycast documentation.

    It does not return a boolean, it returns a RaycastHit2D struct, which will never be null (structs can never be null). So putting a 2D Raycast in a conditional will always be true.

    Also, you already did that first raycast a few lines earlier, so you can check if that result was successful by looking at the "hit" variable contents.

    Eg.
    if(hit.collider != null)


    Another thing to note, your first raycast has a distance of 50f and a layer mask of 11, the second one (hit2) doesn't pass a distance or layermask, so will have a distance of infinity and will hit anything that is not on the layer "IgnoreRaycast" (as per the defaults seen in the docs).

    I'm assuming the ray shouldn't change layermasks between bounces, so the second raycast should match the first for the layermask parameter at least.

    Start with those changes and see how it goes.
     
    Last edited: Jan 15, 2020
    jsull1 likes this.
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,320
    Just to be clear here, it's true the method returns a RaycastHit2D but RaycastHit2D has an implicit overloaded operator for bool so it won't always be true. It'll be true or false depending on whether there was a hit or not which is signified by the collider field being null or not as you already mentioned: RaycastHit2D.collider. :)
     
    jsull1 likes this.
  4. jsull1

    jsull1

    Joined:
    Apr 3, 2018
    Posts:
    121
    Thank you guys! I’ll make these changes when I get back and tell you how they turned out
     
  5. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    I was not aware of that! That should be added to the docs, it's not mentioned or used in the example code.
     
    jsull1 likes this.
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,320
    It's mentioned in the link I provided. Also, you cannot just return a struct in C# amd pass it to something that expects a bool, that would be a compile error so it should be pretty obvious to a developer it does this too.

    If the example used this shortcut then it'd not be obvious what makes it valid or not. This is why the following is in the docs alongside the examples:

    "Note that some functions that return a single RaycastHit2D will leave the collider as NULL which indicates nothing hit. RaycastHit2D implements an implicit conversion operator converting to bool which checks this property allowing it to be used as a simple condition check for whether a hit occurred or not."
     
    jsull1 and LiterallyJeff like this.
  7. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    I think it's a bit much to say that it's obvious. If I didn't pick up on it I don't know how a beginner would. Especially considering how Physics.Raycast behaves, with this using a different paradigm and an implicit boolean operator that is only mentioned in RaycastHit2D.collider specifically and not in RaycastHit2D doc itself or Physics2D.Raycast doc, compounded with the fact that in Unity you can null check implicitly using "if(object)" already. I assumed there was some more under-the-hood stuff going on but I didn't check RaycastHit2D.collider doc. In any case, now I know.
     
    jsull1 likes this.
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,320
    Yes but that's not for structs, you're thinking about Unity classes (engine objects). If there's no implicit conversion available for the struct to the type you're wanting then the compiler will issue a "No implicit conversion available blah blah blah". Try this for RaycastHit (not the 2D one) and you'll see it not work.

    I said "obvious" not as a criticism at all but because this is a language feature/restriction of C#, something we don't teach in the API docs.

    I would say that it's actually quite natural to use it in an "if(hit)" statement (as shown abov) and I see new starters using it all the time without the doc change. It's why I added it and thought it would be very useful and natural.

    We don't mention it there in the same way that we don't mention it in every single physics query and all their overloads that use it (there are lots).

    Yes, it can and should be added there too. I'll add that API change to my next PR for sure!
     
    Last edited: Jan 16, 2020
    jsull1 and LiterallyJeff like this.
  9. jsull1

    jsull1

    Joined:
    Apr 3, 2018
    Posts:
    121
    Hey boys, thanks for the help. I only knew I could use a ray cast as a bool because I saw people on YouTube do it. I made the suggested changes but the ray is still having the same issues. I'm not sure what I can do differently.
    It happens often but especially happens a lot when the object I'm reflecting off is in motion
     

    Attached Files:

    Last edited: Jan 17, 2020
  10. jsull1

    jsull1

    Joined:
    Apr 3, 2018
    Posts:
    121
    I have a theory, it could be because I'm starting the next ray at hit.point, so the first hit objects collider could be interfering with the raycast.
     
  11. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    To test that theory try turning off "Queries Start In Colliders" in your Physics2D settings: Project Settings -> Physics 2D -> Queries Start In Colliders. That will make raycasts ignore the collider(s) they start inside of.
     
    jsull1 and MelvMay like this.
  12. jsull1

    jsull1

    Joined:
    Apr 3, 2018
    Posts:
    121
    That's it! Thank you so much man!