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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Normal vector of a Raycast 2D wrong ?

Discussion in 'Scripting' started by Inward, May 22, 2020.

  1. Inward

    Inward

    Joined:
    Jun 27, 2015
    Posts:
    7
    Hi everyone,

    It's my first time posting here because after spending the whole day on a problem, I just can't find an answer by myself.
    Here is my issue:

    Annotation 2020-05-22 223113.png
    What i try: I would like my skateboarder to rotate to match the inclined plane and the ground.
    Current code:
    To do so, i use a Raycast that points the ground (the white line) and check the normal and calculate the angle I need to rotate.
    Code (CSharp):
    1. private void FixedUpdate()
    2.     {
    3.         Vector2 raycastOrigin = _rigidbody.position + (Vector2) transform.right * 0.16f + (Vector2)transform.up * 0.1f;
    4.         Debug.DrawRay(raycastOrigin, -transform.up);
    5.         RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, -transform.up, 1f, LayerMask.GetMask("Ground"));
    6.         if (hit.collider != null)
    7.         {
    8.             Debug.DrawLine(hit.point, hit.normal, Color.yellow, 10f);
    9.             float angle = Vector2.Angle(hit.point, hit.normal);
    10.             Debug.Log("angle = " + angle);
    11.         }
    12.     }
    But it seems like the normal of my Raycast is always the same position as you can see with the yellows lines and I can't explain why this one in particular. It moves when the skater is on the inclined plane, but same behaviour.

    What I expect: I would like to have something that tells me the angle of the ground, for example 180° at first and then 160° or 200° (depending on which side)

    Any help would be much appreciated !

    Thanks by advance

    PS: don't judge my drawing skills it's only to learn Unity haha
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    I think your raycast is working fine. But you're using Debug.DrawLine to draw the yellow line, and that expects two world space coordinates. You're giving it a world space coordinate (the hit point) and a direction vector (the normal). Try using Debug.DrawRay instead for that line of code (line 8 in your snippet).
    Code (CSharp):
    1. Debug.DrawRay(hit.point, hit.normal, Color.yellow, 10f);
    Also your use of Vector2.Angle has a similar problem. Vector2.Angle expects two direction vectors. You're giving it one world position (the hit point) and one direction vector (the normal). What you probably want is
    Code (CSharp):
    1. float angle = Vector2.Angle(Vector2.up, hit.normal)
    which will give you the angle between straight up and your raycast normal. That will return 0 for flat ground, and a non-zero angle for slanted ground.
     
    Last edited: May 22, 2020
  3. Inward

    Inward

    Joined:
    Jun 27, 2015
    Posts:
    7
    Thank you very much, I found the solution before your edit :D

    Here is what I did:


    Code (CSharp):
    1. private void FixedUpdate()
    2.     {
    3.         Vector2 raycastOrigin = _rigidbody.position + (Vector2) transform.right * 0.16f + (Vector2)transform.up * 0.1f;
    4.         Debug.DrawRay(raycastOrigin, -transform.up);
    5.         RaycastHit2D hit = Physics2D.Raycast(raycastOrigin, -transform.up, 1f, LayerMask.GetMask("Ground"));
    6.         if (hit.collider != null)
    7.         {
    8.             Debug.DrawRay(hit.point, hit.normal, Color.yellow, 10f);
    9.             float angle = Vector2.Angle(transform.right, hit.normal) - 90;
    10.             Debug.Log("angle = " + angle); // 0 on ground, 18.2 on inclined plane
    11.         }
    12.     }
    Annotation 2020-05-22 223113.png

    I didn't understand very well that there is a difference between Vector2 that are "points" and other that are directions.
    I wonder why both of these notions are stored in the same object (Vector2) instead of making Point2D and Direction2D, I must check the basic maths now haha

    Thanks again !
     
    Kurt-Dekker likes this.
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    If you think about it they are the same thing. A world point is a "direction" vector that starts from the origin (coordinates [0, 0]). It's basically a matter of where the "origin" of the vector is when you think about it. "direction" vectors are generally thought about as originating from some place other than the origin (such as your player position), whereas "position" vectors are always thought about as originating from the origin. They are really the same though.
     
  5. Inward

    Inward

    Joined:
    Jun 27, 2015
    Posts:
    7
    Oh that makes sense, the x and y values depend on the reference. If we know the origin we can know the direction we're pointing at.

    Thank you for your time and your quick answer
     
    PraetorBlue likes this.