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?
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?
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.
Edit: this was completely wrong and I retract it.
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
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).

~Atin

3 Likes
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.
Getting the location of my ray in world space made getting the angle between the 2 objects very simple:
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:
//My two unit vectors
Vector3 a = hit.normal;
Vector3 b = transform.up;
//Create two objects
GameObject normal = new GameObject("normal");
GameObject ray = new GameObject("ray");
//Move the new objects to this
normal.transform.position = hit.point;
ray.transform.position = transform.position;
//Set the objects direction
normal.transform.rotation = Quaternion.LookRotation(a);
ray.transform.rotation = Quaternion.LookRotation(b);
//Set them as children so they are relative to my direction.
normal.transform.parent = transform;
ray.transform.parent = transform;
//Create the Vector2's
Vector2 normalXY = new Vector2(normal.transform.forward.x,
normal.transform.forward.y);
Vector2 rayXY = new Vector2(ray.transform.forward.x,
ray.transform.forward.y);
Vector2 normalYZ = new Vector2(normal.transform.forward.y,
normal.transform.forward.z);
Vector2 rayYZ = new Vector2(ray.transform.forward.y,
ray.transform.forward.z);
//Get the angles
float angleXY = Vector2.Angle(normalXY, rayXY);
float angleYZ = Vector2.Angle(normalYZ, rayYZ);
//output
Debug.Log (transform.name + " Angle X,Y: "
+ angleXY);
Debug.Log (transform.name + " Angle Y,Z: "
+ angleYZ);
But it is not right.
Considering your real world example you could do it like this:
wheelieAngle = Vector3.Angle(streetAtPosXZ.normal, transform.forward);
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.
/facepalm
I just knew there had to be a simple way to get this. Thank you very much Arterie.