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

Left/Right test function

Discussion in 'Scripting' started by HigherScriptingAuthority, Oct 2, 2009.

  1. It is easy to get the angle between two vectors using Vector3.Angle, but this only gives an absolute value for the angle. How do you tell if one direction is to the left or to the right of the other?

    It seems as though it should be easy, but in fact it's a little bit subtle. I've attached a function (in both JS and C# versions) that illustrates how to go about it. You need to supply a forward direction, the direction that you want to check for left/right of forward and an up direction. The functions return -1 when the target direction is left, +1 when it is right and 0 if the direction is straight ahead or behind.

    As is so often the case, the magic ingredient in the function is the cross product.
     

    Attached Files:

  2. Muckel

    Muckel

    Joined:
    Mar 26, 2009
    Posts:
    471
    many many thanxxx
    ... how long was i searching for this solution...
    Now my Direction Display works !!!
    I really miss this in the Doc's !!!
    Great Community !!!
    :oops: kerstin

    P.S. Need#s to be on the Wiki !
     
  3. Robotron18

    Robotron18

    Joined:
    Aug 15, 2010
    Posts:
    12
    Thank you very much.
    You can get also the final vector, comfortable to transform own collisions.

    Code (csharp):
    1.  
    2. Vector3 VectorResult;
    3. float DotResult = Vector3.Dot(transform.forward, target.forward);
    4.         if (DotResult > 0)
    5.         {
    6.             VectorResult = transform.forward + target.forward;
    7.         }
    8.         else
    9.         {
    10.             VectorResult = transform.forward - target.forward;
    11.         }
    12.         Debug.DrawRay(transform.position, VectorResult * 100, Color.green);
     
    laurajhchen likes this.
  4. AkilaeTribe

    AkilaeTribe

    Joined:
    Jul 4, 2010
    Posts:
    1,149
    Simple and clean. Good job :wink:
     
  5. cerebrate

    cerebrate

    Joined:
    Jan 8, 2010
    Posts:
    261
    static version?

    Code (csharp):
    1. //returns -1 when to the left, 1 to the right, and 0 for forward/backward
    2. public static function AngleDir(fwd: Vector3, targetDir: Vector3, up: Vector3) : float {
    3.     var perp: Vector3 = Vector3.Cross(fwd, targetDir);
    4.     var dir: float = Vector3.Dot(perp, up);
    5.    
    6.     if (dir > 0.0) {
    7.         return 1.0;
    8.     } else if (dir < 0.0) {
    9.         return -1.0;
    10.     } else {
    11.         return 0.0;
    12.     }
    13. }
     
    kev000 likes this.
  6. elveatles

    elveatles

    Joined:
    May 2, 2009
    Posts:
    147
    Thank you so much HigherScriptingAuthority! This is exactly what I was looking for!
     
  7. samim23

    samim23

    Joined:
    Sep 11, 2012
    Posts:
    60
    Cool script, thanks for this. Here is the C# version:

    Code (csharp):
    1.  
    2.         //returns -1 when to the left, 1 to the right, and 0 for forward/backward
    3.     public float AngleDir(Vector3 fwd, Vector3 targetDir, Vector3 up)
    4.     {
    5.         Vector3 perp = Vector3.Cross(fwd, targetDir);
    6.         float dir = Vector3.Dot(perp, up);
    7.  
    8.         if (dir > 0.0f) {
    9.             return 1.0f;
    10.         } else if (dir < 0.0f) {
    11.             return -1.0f;
    12.         } else {
    13.             return 0.0f;
    14.         }
    15.     }  
    16.  
     
  8. yoyo

    yoyo

    Joined:
    Apr 16, 2010
    Posts:
    112
    In 2D there is a much simpler way, as explained in this stack overflow question.

    Code (csharp):
    1. public static float AngleDir(Vector2 A, Vector2 B)
    2. {
    3.     return -A.x * B.y + A.y * B.x;
    4. }
    This returns a negative number if B is left of A, positive if right of A, or 0 if they are perfectly aligned.

    It works by rotating B 90 degrees counter-clockwise (which is simply {-B.y, B.x}) and then taking the dot product to see if the rotated vector is ahead or behind A. (Make some vector combinations with your fingers and wiggle them around until you convince yourself this works! ;))
     
  9. NickP_2

    NickP_2

    Joined:
    Jul 9, 2013
    Posts:
    61

    You saved me a whole night and a gallon of coffee :)
     
    Last edited: Mar 4, 2014
  10. nsbigmotive

    nsbigmotive

    Joined:
    Aug 2, 2016
    Posts:
    1
    Thank you very much HigherScriptingAuthority! Perfect!
     
  11. andyblem

    andyblem

    Joined:
    Nov 11, 2014
    Posts:
    26
    great piece of code
     
  12. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    If you have a Transform, you can also just take the dot product of its .right vector, and the direction vector.

    Also, OP, I think this version of your code would be marginally easier to understand :)
    Code (CSharp):
    1. float AngleDir(Vector3 fwd, Vector3 targetDir, Vector3 up) {
    2.     Vector3 right = Vector3.Cross(up, fwd);        // right vector
    3.     float dir = Vector3.Dot(right, targetDir);
    4.    
    5.     if (dir > 0f) {
    6.         return 1f;
    7.     } else if (dir < 0f) {
    8.         return -1f;
    9.     } else {
    10.         return 0f;
    11.     }
    12. }
     
    uotsabchakma, fspore and DrWittenborg like this.
  13. LuckyMisterSleven

    LuckyMisterSleven

    Joined:
    May 20, 2014
    Posts:
    2
    Thanks a lot for sharing this
     
  14. CouchRonin

    CouchRonin

    Joined:
    Jul 9, 2017
    Posts:
    1
    Thank you so much for sharing this, it's just perfect for a game I am working on.
     
  15. GeneralKaiminus

    GeneralKaiminus

    Joined:
    Feb 17, 2018
    Posts:
    6
    Thank you for the share woah i'm now getting to understand how it works XD
     
  16. Kev00

    Kev00

    Joined:
    Dec 6, 2016
    Posts:
    229
    if all you need to know is what side an object is on there is another way.

    Vector3 localPos = objectFacing.InverseTransformPoint(objectToTest.transform.position);
    if (localPos.x < 0.0f) // left side
    else if (localPos.x > 0.0f) // right side
    else // center
     
    theDrake, taimex, Roman200333 and 3 others like this.
  17. abitofjohn

    abitofjohn

    Joined:
    Nov 6, 2012
    Posts:
    27
    Thanks so much HigherScriptingAuthority! You've saved me hours!
     
  18. modernator24

    modernator24

    Joined:
    Apr 7, 2017
    Posts:
    186
    @Kev00 That works. Thanks!
     
  19. Ikno_

    Ikno_

    Joined:
    Jun 13, 2018
    Posts:
    2
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;


    public class SamusDamage : MonoBehaviour
    {
    public GameObject Player;


    public Transform playerTransform;

    private float playerPos;
    private float collPos;




    private void OnCollisionEnter2D(Collision2D collision)
    {
    if(collision.gameObject.name == "Reo")
    {
    collPos = collision.transform.position.x;
    playerPos = Player.transform.position.x;



    if (playerPos >= collPos)
    {
    //you are on the right
    }
    else
    {
    //you are on the left
    }


    }
    }

    }



    this is for 2d
     
  20. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    What if the player isn't facing straight forward?
     
  21. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Almost 10 years later, and this answer is still useful. Thanks You!
     
  22. Alvarezmd90

    Alvarezmd90

    Joined:
    Jul 21, 2016
    Posts:
    151
    Wait.. can I use this for checking f.e. which side of a door a player is standing?
    'Cause I use a mouse axis code to make the player pull the door, but on the other side it's inverted. 0__o
     
  23. SwixDevs

    SwixDevs

    Joined:
    Apr 19, 2019
    Posts:
    6
    Works perfectly! Thanks a lot!
     
  24. launzone

    launzone

    Joined:
    Dec 2, 2015
    Posts:
    57
    if you just want to have a simple value of how much percent left/ right an object is to another one I think this is a pretty good solution:
    Code (CSharp):
    1. Vector3 dirVector = otherT.position - gameObject.transform.position;
    2. float dir = Vector3.Angle (
    3.             transform.right,
    4.             new Vector3(dirVector.x,0f,dirVector.z));
    5.  
    in this case the calculated values for dir would give you something between: 0 (completely right), 90 (center), 180 (completely left)
    After this I remapped the value to be between -1 and 1, now it is easy to tell how far left or right something is.
     
  25. florinel2102

    florinel2102

    Joined:
    May 21, 2019
    Posts:
    76
    I'm using this function a lot when I working with nodes . Thank you for sharing with us !
     
  26. niuage

    niuage

    Joined:
    Nov 17, 2019
    Posts:
    122
    Can't you just use Vector3.SignedAngle?
     
  27. Boz0r

    Boz0r

    Joined:
    Feb 27, 2014
    Posts:
    419
    I think you probably could, but that function didn't exist until 2017, and it's more expensive than my suggestion(It has more multiplications and even a square root) :)
     
  28. uotsabchakma

    uotsabchakma

    Joined:
    Sep 17, 2019
    Posts:
    93
    1. Ctrl + C
    2. Ctrl + V
    Thanks for clean code!!!
     
  29. JoystickLab

    JoystickLab

    Joined:
    Mar 18, 2016
    Posts:
    14
    The solution perfectly works. Can anyone help me understand why it works?
     
  30. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    655
    Basic trigonometry: