How to smoothly move a camera with "Simple Follow With World Up" to a specific position?

I have a seemingly simple case that I spend over 5+ hours and still can’t figure out how to do it. The set up is simple - I have two cameras:

  • Cam ground” for when the car is on the ground with “Lock to Target With World Up”. This camera is fixed behind the car.
  • Cam Air” for when the car is in the air. The cam doesn’t have a fixed position since it’s “Simple Follow With World Up”.

Now two features I’d like to implement:
1. When the car lands we are using “cam ground” but while we are on the ground I want the “cam air” to transition behind the car to the position of “Cam ground” to be behind the car next time we jump. I solved it by waiting when the blend “cam air” → “cam ground” is finished (_brain.IsBlending == false) and only then I change the position of the “cam air” with ForceCameraPosition().

2. The solution above works great but I have issues with the following: Supposed we are in the air (picture below), the air cam is active and is positioned perpendicular to the car, since it “Simple Follow”. Now I want the user to be able to press a button and realign the “air cam” with Simple Follow to be behind the car, not fixed, but just move it there with a smooth blend and only then let the “Simple Follow” do its job.

To solve the 2. feature I tried using a second “air cam2” to switch between them in the air but the blend and transitions not always work and after 5+ hours I don’t know how to solve it elegantly. It seems to be a very easy problem, but my code for it looks very convoluted, there must be an easier way of solving it.
Full code (very messy and ugly) - hatebin

The camera set up is as follows
Ground cam - Imgur: The magic of the Internet
Air cam - Imgur: The magic of the Internet

You can achieve this with ForceCameraPosition with your original setup. To get a nice damped movement, move the camera some percentage of the remaining distance each frame.

I deleted my original answers, as it will not be the same behaviour. @Roboserg

ForceCameraPosition for the air cam? But then it will jump instantly, without cinemamachine cylindrical blend.
So for case 2, when the user presses a button and wants to realign the air cam to be behind the car I was trying to switch to the ground cam (does smooth blending) and changing the blend mode of the ground cam to “Simple Follow”. After the blend, I would then reset the position of the air cam. But this solution is convoluted, because when we land on the ground I now have to do lots of coding, change the binding modes (Lock to target and simple follow) etc.

“To get a nice damped movement, move the camera some percentage of the remaining distance each frame.”
So manually blending with something like Lerp()? I thought I am supposed to use cinemamachine blending feature since its already implemented for that kind of stuff.

You can use the CM blend feature, but as you point out, that gets convoluted because that’s meant to blend between different cameras, when what you’re trying to do is move the current camera.

If you call ForceCameraPosition on the AirCam every frame, moving it some percentage (let’s say 50%) of the remaining distance each frame, you will get a nice ease-in to the new position, not a sudden jump.

To get a cylindrical movement instead of a straight line, rotate about a pivot (the car). Here is a bit of code for that. The t param should be 0…1, and defines how far to interpolate each call. Keep calling it with some value of t: the larger it is, the faster will be the movement. Stop moving when you’re “close enough”.

        Vector3 InterpolatePosition(
            Vector3 posA, Vector3 posB, Vector3 pivot,
            float t, bool cylindrical)
        {
            if (cylindrical)
            {
                // Cylindrical interpolation about pivot
                var a = Vector3.ProjectOnPlane(posA - pivot, Vector3.up);
                var b = Vector3.ProjectOnPlane(posB - pivot, Vector3.up);
                var c = Vector3.Slerp(a, b, t);
                posA = (posA - a) + c;
                posB = (posB - b) + c;
            }
            return Vector3.Lerp(posA, posB, t);
        }

Note: in the above code, posA is the current airCam position each frame, not the start position of the blend. posB is the destination position.

Thanks, looks like a good solution! I also tried the following approach and it seems to work, I am using two Air Cams and blend between them:

    private void RealignAirCam()
    {
        if (ActiveVirtualCamera != camAir2 && _brain.IsBlending == false)
        {
            camAir2.ForceCameraPosition(camGround.transform.position, camGround.transform.rotation);
            ActivateCam(camAir2);
        }
        else if (ActiveVirtualCamera != camAir1 && _brain.IsBlending == false)
        {
            camAir1.ForceCameraPosition(camGround.transform.position, camGround.transform.rotation);
            ActivateCam(camAir1);
        }
    }

It’s still not “perfect” because the “Simple Follow” looks in the direction of the velocity vector of the body, so at the end of the video you can see how it quickly changes the position after I realign the cam behind the car:
3nbxzv

2 Likes