Vector3.Slerp, how to have linear movement and only affecting specific axis?

I’ve implemented some camera controls for my code so that it rotates around the player from above, while also allowing buttons to move the camera to the nearest 45° angle. [See attached video for example]

However, I’m running into some minor problems that are bothering me.

        offset = Quaternion.AngleAxis(rotate * turnSpeed, Vector3.up) * offset;
        transform.position = Vector3.Slerp(transform.position, player.position + offset, 25 * Time.deltaTime);
        transform.LookAt(player.position);

Here’s my current code that actually controls the movement of the camera itself.

The issues I’m having are that when I rotate the camera, the Y rotation acts as expected, but X rotation also increases (by a larger amount with slower camera speeds) which results in an unpleasant warping effect on slow camera speeds. The second issue I’m having is that when using Slerp the camera seems to move with acceleration and momentum, that is, it begins slow, builds up speed, and then slows down a bunch and continues movement after releasing the button.

Both of these issues aren’t majorly critical to the game, but leads to a very unpleasant experience with the camera.

UPDATE: I’ve fixed the second issue, in my Vector3.Slerp I was feeding in the current position for “transform.position”, I’ve not written the current transform.position to a new Vector3 and fed that in as my first variable in the Slerp, this fixed the issue.

I am still struggling to find a way to prevent the x rotational axis from changing at all.

Orbit cameras are way easier to implement when you simply parent the camera to a pivot gameobject which you can place at your desired target position. You simply orbit by rotating the pivot object and the camera will orbit around naturally and still point to the same position which is the center of that pivot object. If the elevation should also be controllable, you can simply introduce another empty gameobject as a child of the pivot object located at localposition (0,0,0). You would simply tilt that intermediate object to 45° and have the camera be a child of that intermediate object. Now you’re only dealing with single properties at a time. So the camera’s local z position determines the distance from the pivot. The intermediate objects local x rotation determines the elevation and the pivots position and y rotation determines the focus and the orbit angle.

There’s no need for manually messing around with absolute positions. Just setup a proper kinematic chain, insert as many pivot objects as you need and it simplifies the controls a lot. Of course this may not always be the best solution and may vary depending on the project and maybe what other kinds of camera controls you may want to support and how you transition between them. Though such relative accumulated rotation stuff never really works out unless you’re in an actual fully free 3d environment with 6 degrees of freedom.

Just wanted to say, although I didn’t exactly use your explanation, it made me return to the idea of using an empty game object as a pivot point (which I had used for something else but for some reason wouldn’t work for camera rotation). I’ve since gone back and redone chunks of code for both optimization (who knew writing code at 2am leads to un-optimized code :stuck_out_tongue_winking_eye: ) and for avoiding the aforementioned issue. I’ve just about got this working now, so I wanted to say thanks!