Camera movement algorithm

I have an xna background and am just getting started with Unity. What I’d like to do is script a camera to follow an object (3d space environment), but modify its own position in space so that another object is always a certain distance from the camera and located in the upper right corner of the view frustrum. Essentially, I want to follow object A while keeping object B a fixed distance from the camera and always in the upper right corner of the screen. I can see this in my head and believe it is possible, but I can’t yet visualize how to begin on working out the offsets.

Is object B at a fixed location in space? In other words are you trying to position the camera to see object B or are you just trying to position object B relative to the camera so it looks like a UI element?

Well thats a bunch of trigonometry. This is the code for the camera pointing to Vector2.forward. The trigonometric cals are not as hard as from another angle… But theorically you could do the same with the camera seeing to all the angles. … with hardcore trigonometric calcs :slight_smile:

using UnityEngine;

public class CameraController : MonoBehaviour
{
    public Transform target, corner;
    private readonly float cornerOffset = 1, minCameraDistance = -5;
    private float proportion;

    private void Awake()
    {
        proportion = (float)Screen.height/(float)Screen.width;
    }

    private void LateUpdate()
    {
        var zOffset = -(Vector2.Distance(corner.position, target.position) + cornerOffset) / Mathf.Tan(Mathf.Deg2Rad * Camera.main.fieldOfView / 2);
        var angle = Mathf.Sign(corner.position.y - target.position.y) * Mathf.Acos((corner.position.x - target.position.x) / Vector2.Distance(target.position, corner.position)) * Mathf.Rad2Deg;
        transform.rotation = Quaternion.Euler(0, 0, angle - Mathf.Rad2Deg * Mathf.Atan(proportion));
        transform.position = target.position + new Vector3(0, 0, Mathf.Min(minCameraDistance, zOffset));
    }
}
1 Like

B is fixed in space, A is moving. I wanted to position the camera so that the view direction is toward A and B is on the vector following the top right of the frustum.

Looking at the attached (?) figure in 2d illustrates what I wanted to do. The left “camera start” shows the camera, view direction (big green cylinder) and the the directions of the frustum left and right edges (dark and light green cylinders off to the sides, terminating in dark green on left and dark green+red spheres on right). These are directions. The dark green/red sphere on the right intersecting with the Desired Position camera frustum represents the position of object B in space where it’d appear in the right corner of the screen The yellow square is object A. The camera would need to be rotated around point B (green/red sphere) keeping the distance constant until the new view vector (blue) landed on object A.

6071802--658383--upload_2020-7-9_15-42-2.png

Seems like this ought to be solvable with some vector math. I’m going to talk it out and see how far I get.
The direction to the right corner is some fixed function (e.g., SFF() of the view direction and vice versa (e.g., IFF() )

All the bold is known

C1 is the camera start position
V1 is the current view direction that puts B in the corner
D is the distance of camera to B
V2 is the direction of the current camera to object A
D1a is the distance of the current camera to object A
Vab is the direction from B to A
Dab is the direction from B to A

these are unknown

C2 is the final position of the camera
V2 is the direction from C2 to A
Da is the distance from C2 to A

So this is all known
C1 + SFF(V1) * D = B
C1 + V2 * D1a = A
A = B+Vab*Dab
B = A-Vab*Dab

Leaving me 2 equations with 3 unknowns, C2, V2 and Da
C2+IFF(V2)D = B
C2+V2
Da = A

So I guess its not solvable without some further constraint or I’m too far removed from my high-school algebra. In the fringe case where the yellow square fell on the white line, perpendicular to the view direction and passing through point B, then the camera could be rotated in space any number of degrees around that white line while keeping D and V2*Da constant. So, there are cases where there could be multiple C2s.

Maybe take a look at Cinemachine’s Framing Transposer.

Well, I can make this code, I think it’s really more simple than the above one I made before, but you have to realize before about some desing error it could be. You could though about it yet but:

If you wanna D as a constant value and the distance between A and B is lower than d, it will be imposible to keep A at the center of the Desired position camera. If you’re sure the distance between A and B will be larguer than d, and thats not a matter, I think I can get this code.

1 Like

U.U i never used cinemachine xD. Can I be doing tard useless calcs? :face_with_spiral_eyes:

You have a good eye- I’d not seen that. I suppose for my needs, if A us in the view frustum, and more-or-less centered it will be enough. The camera is going to be “lazy” in that A can move around in the frustum, with the camera moving to slowly give the object more room when it gets close to an edge. If, in the game, I can keep A at least d away from B. d would be D*sin(half_horizontal_view) wouldn’t it?