- Home /
Get the angle of a ray in respect to a camera
So here's a challenging question. I have a Ray generated by two points. Assuming the Ray's direction is not the same as camera's forward or backwards direction, how do I get the angle of that ray in respect to a camera?
Here's a few screenshots demonstrating what I'm trying to do.

I'm attempting to use a two camera setup (one perspective, one orthogonal) to generate a GUI with rotating buttons. The buttons are supposed to point in the direction a transform is at in respect to the character. I've tried the following method of "converting" a point in the ray from the perspective camera ( gameCamera ) to orthogonal camera ( guiCamera ), but the results were inconsistent:
Vector3 ConvertPoint(Vector3 gamePoint, Camera gameCamera, Camera guiCamera, float distanceFromGuiCamera)
{
Vector3 viewPortPoint = gameCamera.WorldToViewportPoint(gamePoint);
Ray guiRay = guiCamera.ViewportPointToRay(viewPortPoint);
return guiRay.GetPoint(distanceFromGuiCamera);
}
static float Angle(Vector3 originPoint, Vector3 endPoint)
{
float returnAngle = Mathf.Atan2((endPoint.y - originPoint.y), (endPoint.x - originPoint.x)) * (180f / Mathf.PI);
while(returnAngle > 0f)
{
returnAngle -= 360f;
}
while(returnAngle < 0f)
{
returnAngle += 360f;
}
return returnAngle;
}
public void PositionButton(Camera gameCamera, Camera guiCamera, Ray characterToTransform, float distanceFromGuiCamera,
float nearestDistance, float farthestDistance, float lerpValue, float deltaTime)
{
// Generate 2 points: one at the origin, and one several units away from it
origin = ConvertPoint(characterToTransform.origin, gameCamera, guiCamera, distanceFromGuiCamera);
farthestPoint = characterToTransform.GetPoint(farthestDistance);
farthestPoint = ConvertPoint(farthestPoint, gameCamera, guiCamera, distanceFromGuiCamera);
float angle = Angle(origin, farthestPoint);
Quaternion rotation = Quaternion.Euler(0, 0, angle);
CachedTransform.rotation = rotation;
}
In particular, Vector3 viewPortPoint = gameCamera.WorldToViewportPoint(gamePoint); has been oddly inaccurate. I don't know if it has to do with how the gameCamera is parented to another object for animation, but one odd scenario includes a camera looking in the positive X direction, while the ray is looking in the positive Z-direction (the screenshots above demonstrates this specific scenario). I would normally expect farthestPoint to be set left of origin, but instead, I get a farthestPoint in the right.
I'm having trouble sorting through the specifics of your question to get to a real answer, but here is a function that finds a signed angle between two Vectors:
float SignedAngle(Vector3 v1, Vector3 v2, Vector3 normal) {
Vector3 perp = Vector3.Cross(normal, v1);
float angle = Vector3.Angle(v1, v2);
angle *= $$anonymous$$athf.Sign(Vector3.Dot(perp, v2));
return angle;
}
Interesting, @robertbu. I'll give that a shot tomorrow.
I've attempted the following code, but don't get the desired goal:
static float SignedAngle(Vector3 v1, Vector3 v2, Vector3 normal)
{
Vector3 perpendicular = Vector3.Cross(normal, v1);
float angle = Vector3.Angle(v1, v2);
angle *= $$anonymous$$athf.Sign(Vector3.Dot(perpendicular, v2));
//angle += 90f;
return angle;
}
public void PositionButton(Camera gameCamera, Camera guiCamera, Ray characterToTransform, float distanceFromGuiCamera,
float nearestDistance, float farthestDistance, float lerpValue, float deltaTime)
{
// Generate 2 points: one at the character's origin, and one several units away from it
origin = ConvertPoint(characterToTransform.origin, gameCamera, guiCamera, distanceFromGuiCamera);
farthestPoint = characterToTransform.GetPoint(farthestDistance);
float angle = SignedAngle(characterToTransform.origin, farthestPoint, gameCamera.transform.forward * -1);
Quaternion rotation = Quaternion.Euler(0, 0, angle);
// Position the buttons
CachedTransform.position = origin;
CachedTransform.rotation = rotation;
}
Now every button gets rotated to the right side of the screen.
Didn't exa$$anonymous$$e your code in detail, but it sounds like you're trying to convert world-space vectors into screen-space, in which case the angle relative to the camera is non-essential data.
Have a look at transform.InverseTransformDirection() and Camera.WorldToScreenPoint()
Reading your question and code for the third time and trying to fit it into the code you've written is making my head hurt. The problem is that I'm having trouble visualizing what the right solution looks like (and if it is the one you are asking for). Given just the text of the problem you specify:
I have a Ray generated by two points. Assu$$anonymous$$g the Ray's direction is not the same as camera's forward or backwards direction, how do I get the angle of that ray in respect to a camera?
There are a number of solutions, but the most common would be to take the two world points (the origin of the ray, and another point some distance from the origin) and use Camera.WorldToScreenPoint() or Camera.WorldToViewportPoint() to generate two points. Then to get direction:
Vector3 dir = point2 - point1;
angle = $$anonymous$$athf.Atan2(dir.y, dir.x) * $$anonymous$$athf.Rad2Deg;
CachedTransform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
This code assumes your GUI camera has a rotation of 0,0,0, and that you are using a Sprite or Quad to display the indicator. The indicator needs to point to the right when the rotation is (0,0,0).
Answer by japtar10101 · Nov 01, 2014 at 07:06 PM
Well this is embarrassing. It looks like the the functions I wrote above is working just fine!
The Ray I was generating was not. I figured it out after putting in a ton of debugging statements. Apologize.
Your answer
Follow this Question
Related Questions
Raycast Ray ray origin problem 3 Answers
Ray.origin point moving from stationary object? 1 Answer
A little confused about scripting Raycasts 1 Answer
Changing position of a RayCast 1 Answer
Angles from Directions 2 Answers