Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice

Raycasting to get angles

Discussion in 'Scripting' started by YazourAU, May 24, 2013.

  1. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    I am new to Unity and scripting in 3D space.

    I am trying to get an angle back from a Raycast on a single axis (ie on the horizontal plain). The Raycast is firing perpendicular to its direction of travel.

    My approach so far has been to get the Normal of the plain hit and then try to use the transform of my Raycasting Object to calculate the difference on the desired axis.

    My problem (I think) is that no matter how I compare the objects (using Vector3's, or Quaternions), one is relative to itself, and the other is relative to the world. Is it possible to translate one to be be on the same plain as the other so I can get the delta I need?

    Or is there a simpler approach?
     
    Last edited: May 29, 2013
  2. ardo314

    ardo314

    Joined:
    Jul 7, 2012
    Posts:
    345
    I think one needs at least two axis for an angle?,
    But i guess thats what you mean, so wouldnt Vector2.Angle work out for you?
     
  3. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    Thanks for the reply. It looks like my communication skills are failing me. I will try another explanation.



    The raycast is hitting an object. I want to know what angle my ray is making to that object.

    To put it another way...

    I have 2 lines. They cross at a known point (x,y,z). What angles are they making relative to the x axis and z axis.


    This calculation would be much simpler if the 2 objects were using the same set of co-ordinates.
     
  4. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    Edit: this was completely wrong and I retract it.
     
    Last edited: May 27, 2013
  5. ardo314

    ardo314

    Joined:
    Jul 7, 2012
    Posts:
    345
    Youre really confusing me...

    The angle between normal of hit and raydir on the x-z-plane is Vector2.Angle() of the correspondig x and z values.
    The angle between hit surface and ray will be 90 - result.
    The angle between the in and out rays will be result * 2.

    The direction of the outgoing ray would be Quaternion.LookRotation(hit.normal) * incomingRayDir
     
  6. Atin Skrita

    Atin Skrita

    Joined:
    Feb 18, 2011
    Posts:
    94
    If you want to Reflect the ray, use Vector3.Reflect. It will take the direction of your raycast(the incident ray) and the normal of the hit object and return the reflected direction(reflected ray in the image).



    $96587-004-A0E35F35.gif

    ~Atin
     

    Attached Files:

    Spacejet13, ercion and VenetianFox like this.
  7. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    Thank you for your input it has increased my understanding of what is going on. I realise now I was asking the wrong question.

    I was asking how to get an angle, when I would have been asking: "How do I get the Vectors that will allow me calculate the angle?"

    So far I have been using RaycastHit.point and RaycastHit.normal and comparing them to my Object's transform trying to get the difference. However both RaycastHit.point and RaycastHit.normal are both relative to the world so simple comparisons cannot be made. Nor can I set them as children of my Object as they don't have their own transforms.

    Edit: Writing this response has given me another idea. I can get my Objects world relative transform and use that for comparison I think.
     
  8. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    Getting the location of my ray in world space made getting the angle between the 2 objects very simple:
    Code (csharp):
    1. differenceAngle = Vector3.Angle(hit.normal, transform.up);
    But this brings me back to my first problem. That angle is in 3 dimensions. I only need the angel made on one plane. I thank Arterie for their suggestion but I don't think it would work. Taking only x and z values will only work if my object can only move in 2 dimensions.

    To give a real world example:
    I want to know what angle a car is making to the road. I need its front to back roll as a distinct angle. I need its side to side roll as a distinct angle. You can see how these angles would have different applications? Vector3.Angle() doesn't work as it won't tell you if a car is doing a wheelie or rolling over. So Vector2.Angle() looks ideal. Get the (z,y)'s for pitch and (x,y)'s for roll. All good, until you turn a corner. Suddenly (x,y)'s are your pitch and (x,y)'s are your roll because they stay relative to the world, not the car.

    This is where I am coming unstuck.

    My best attempt to get around this is:
    Code (csharp):
    1.             //My two unit vectors
    2.             Vector3 a = hit.normal;
    3.             Vector3 b = transform.up;
    4.            
    5.             //Create two objects
    6.             GameObject normal = new GameObject("normal");
    7.             GameObject ray = new GameObject("ray");
    8.            
    9.             //Move the new objects to this
    10.             normal.transform.position = hit.point;
    11.             ray.transform.position = transform.position;
    12.            
    13.             //Set the objects direction
    14.             normal.transform.rotation =  Quaternion.LookRotation(a);
    15.             ray.transform.rotation = Quaternion.LookRotation(b);
    16.            
    17.             //Set them as children so they are relative to my direction.
    18.             normal.transform.parent = transform;
    19.             ray.transform.parent = transform;
    20.            
    21.             //Create the Vector2's
    22.             Vector2 normalXY = new Vector2(normal.transform.forward.x,
    23.                 normal.transform.forward.y);
    24.             Vector2 rayXY = new Vector2(ray.transform.forward.x,
    25.                 ray.transform.forward.y);
    26.            
    27.             Vector2 normalYZ = new Vector2(normal.transform.forward.y,
    28.                 normal.transform.forward.z);
    29.             Vector2 rayYZ = new Vector2(ray.transform.forward.y,
    30.                 ray.transform.forward.z);
    31.            
    32.             //Get the angles
    33.             float angleXY = Vector2.Angle(normalXY, rayXY);
    34.             float angleYZ = Vector2.Angle(normalYZ, rayYZ);
    35.            
    36.             //output
    37.             Debug.Log (transform.name + " Angle X,Y: "
    38.                 + angleXY);
    39.             Debug.Log (transform.name + " Angle Y,Z: "
    40.                 + angleYZ);
    But it is not right.
     
    Last edited: May 27, 2013
  9. ardo314

    ardo314

    Joined:
    Jul 7, 2012
    Posts:
    345
    Considering your real world example you could do it like this:

    Code (csharp):
    1. wheelieAngle = Vector3.Angle(streetAtPosXZ.normal, transform.forward);
    2. rollAngle = Vector3.Angle(streetAtPosXZ.normal, transform.right);
    If the car stands on the street it will output 90°, also the angle is in the bounds of [0,180], means if you want to know if the car is upside down you need to work around that.
     
  10. YazourAU

    YazourAU

    Joined:
    May 21, 2013
    Posts:
    10
    /facepalm

    I just knew there had to be a simple way to get this. Thank you very much Arterie.