Help getting angles between camera and object

Hi there, I’m trying to make a 3D scene with a third person camera and billboard sprites.

The environmental billboard sprites in the scene are working fine (they have their GFX component looking at the camera), but the billboard agents (billboard sprites that can move around) are giving me trouble.

I want to play different animations based on their movement direction and the camera’s position, but I’m having trouble getting the angle right on this.

For a simple test right now I just have a blank sprite set to change color based on the camera’s movement, but it’s not working right. I’m sure I’m doing something wrong but I could use some help.

Here is my code:

private void Update()
        {
            float angle = Vector3.Angle(agentTransform.forward, camTransform.transform.position);

            Debug.Log(angle);

            if (angle > 90)
            {
                spriteRenderer.color = backColor;
            }
            else if (angle > 45)
            {
                spriteRenderer.color = sideColor;
            }           
            else
            {
                spriteRenderer.color = mainColor;
            }
        }

the agentTransform is the main agent (not the billboarded gfx child transform), and the camTransform is the Camera.main.transform.

Basically I was trying to get the angle between them and depending on that change the color to show when the sprite should switch to side or back view.

The angles I’m debugging are not what I expect though.

I’m wondering if it has something to do with using the Vector3s and really I should be using Vector2 since I don’t care about the camera’s y position relative to the agent. I’m just not sure how to get the

What are you expecting?

Note… you can’t have an angle between 2 points. Angles are between 2 lines/directions (3d or 2d). So at the very least you need 3 points.

It’s common, especially in 2d, to measure an angle off some axis (like x-axis), where the axis behaves as one of the 2 lines.

In your code here you say:

Vector3.Angle(agentTransform.forward, camTransform.transform.position)

Vector3.Angle takes the 2 vectors. The resulting angle is the angle between those 2 directions.

So basically if you draw a line from (0,0,0) to the camera’s position. Then you draw a line from (0,0,0) in the direction of the agentTransform. THAT is what you’re measuring the angle of.

If you want an angle of something else… well, you need to know what angle you’re attempting to measure.

I think I’m having an issue because what I want is the angle between the forwards of the agent and the camera, but as seen from above. What I mean by that is since the camera can rotate on the X axis, it’s forward sometimes points up or down and I don’t want to take that aspect of the forward into acount.

So I want the angle between the two forwards as if they were seen from above in 2D space I think

I’m just not sure how to do that.

In terms of what I was expecting, well I guess I was expecting 0 and 180 degrees when the camera is in front or behind the agent, and 45 and 135 degrees when to either side.

I think I got it! I made a new camera forward vector based on the default one:

camForwardVector = new Vector3(camTransform.forward.x, 0f, camTransform.forward.z);

            float angle = Vector3.Angle(agentTransform.forward, camForwardVector);

This one doesn’t rotate along the x-axis and so from above works like a 2D vector and this is working.

The issue now is I don’t know how to tell if I should flip the sprite’s side view or not.

In 2D I would flip the sprite’s side view depending on if it was moving in positive or negative X, but in 3D with the rotating camera I’m not sure what property to use to determine if I should flip the sprite.

I’ll try to get a gif up here to show what I mean in case it’s not clear.

EDIT: Here is a gif showing the issue Imgur: The magic of the Internet

Notice how when the camera turns towards the left the sprite is also facing left. That’s when I would want to flip the side sprite, but I’m not sure how to determine what side the camera is relative to the agent.

Ok I got it! Turns out there’s a Unity Vector function called SignedAngle: Unity - Scripting API: Vector3.SignedAngle

This is what I needed as it returns the sign of the angle rather than only the absolute value. With this I can tell what side of the agent the camera is in, and then flip the sprite based on whether the number is positive or negative.

So now I think it’s working well! Time to put it in the animation blend tree now :slight_smile: