Camera zoom in/out function zooming in/out at different rates

I’m using the the simple camera controller from the unity examples. I added a “set zoom” method but the problem is that it zooms in/out at different rates.

This is my script:

using UnityEngine;
namespace UnityTemplateProjects
{
     public class SimpleCameraController : MonoBehaviour
     {
         class CameraState
         {
             public float yaw;
             public float pitch;
             public float roll;
             public float x;
             public float y;
             public float z;
             public void SetFromTransform(Transform t)
             {
                 pitch = t.eulerAngles.x;
                 yaw = t.eulerAngles.y;
                 roll = t.eulerAngles.z;
                 x = t.position.x;
                 y = t.position.y;
                 z = t.position.z;
             }
             public void Translate(Vector3 translation)
             {
                 Vector3 rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation;
                 x += rotatedTranslation.x;
                 y += rotatedTranslation.y;
                 z += rotatedTranslation.z;
             }
             public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct)
             {
                 yaw = Mathf.Lerp(yaw, target.yaw, rotationLerpPct);
                 pitch = Mathf.Lerp(pitch, target.pitch, rotationLerpPct);
                 roll = Mathf.Lerp(roll, target.roll, rotationLerpPct);
                
                 x = Mathf.Lerp(x, target.x, positionLerpPct);
                 y = Mathf.Lerp(y, target.y, positionLerpPct);
                 z = Mathf.Lerp(z, target.z, positionLerpPct);
             }
             public void UpdateTransform(Transform t)
             {
                 t.eulerAngles = new Vector3(pitch, yaw, roll);
                 t.position = new Vector3(x, y, z);
             }
         }
        
         CameraState m_TargetCameraState = new CameraState();
         CameraState m_InterpolatingCameraState = new CameraState();
         [Header("Movement Settings")]
         [Tooltip("Exponential boost factor on translation, controllable by mouse wheel.")]
         public float boost = 3.5f;
         [Tooltip("Time it takes to interpolate camera position 99% of the way to the target."), Range(0.001f, 1f)]
         public float positionLerpTime = 0.2f;
         [Header("Rotation Settings")]
         [Tooltip("X = Change in mouse position.\nY = Multiplicative factor for camera rotation.")]
         public AnimationCurve mouseSensitivityCurve = new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f));
         [Tooltip("Time it takes to interpolate camera rotation 99% of the way to the target."), Range(0.001f, 1f)]
         public float rotationLerpTime = 0.01f;
         [Tooltip("Whether or not to invert our Y axis for mouse input to rotation.")]
         public bool invertY = false;
         void OnEnable()
         {
             m_TargetCameraState.SetFromTransform(transform);
             m_InterpolatingCameraState.SetFromTransform(transform);
         }
         public void SetZoom(float value)
         {
             var translation = ((value < 0 ? Vector3.back : Vector3.forward) * Mathf.Abs(value));
             Debug.Log(translation);
             m_TargetCameraState.Translate(translation);
             //// Framerate-independent interpolation
             //// Calculate the lerp amount, such that we get 99% of the way to our target in the specified time
             //var positionLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / positionLerpTime) * Time.deltaTime);
             //var rotationLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / rotationLerpTime) * Time.deltaTime);
             //m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct);
             m_InterpolatingCameraState.UpdateTransform(transform);
         }
         Vector3 GetInputTranslationDirection()
         {
             Vector3 direction = new Vector3();
             if (Input.GetKey(KeyCode.W))
             {
                 direction += Vector3.forward;
             }
             if (Input.GetKey(KeyCode.S))
             {
                 direction += Vector3.back;
             }
             if (Input.GetKey(KeyCode.A))
             {
                 direction += Vector3.left;
             }
             if (Input.GetKey(KeyCode.D))
             {
                 direction += Vector3.right;
             }
             if (Input.GetKey(KeyCode.Q))
             {
                 direction += Vector3.down;
             }
             if (Input.GetKey(KeyCode.E))
             {
                 direction += Vector3.up;
             }
             return direction;
         }
        
         void Update()
         {
             // Hide and lock cursor when right mouse button pressed
             if (Input.GetMouseButtonDown(1))
             {
                 Cursor.lockState = CursorLockMode.Locked;
             }
             // Unlock and show cursor when right mouse button released
             if (Input.GetMouseButtonUp(1))
             {
                 Cursor.visible = true;
                 Cursor.lockState = CursorLockMode.None;
             }
             // Rotation
             if (Input.GetMouseButton(1))
             {
                 var mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") * (invertY ? 1 : -1));
                
                 var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude);
                 m_TargetCameraState.yaw += mouseMovement.x * mouseSensitivityFactor;
                 m_TargetCameraState.pitch += mouseMovement.y * mouseSensitivityFactor;
             }
            
             // Translation
             var translation = GetInputTranslationDirection() * Time.deltaTime;
             // Speed up movement when shift key held
             if (Input.GetKey(KeyCode.LeftShift))
             {
                 translation *= 10.0f;
             }
            
             // Modify movement by a boost factor (defined in Inspector and modified in play mode through the mouse scroll wheel)
             boost += Input.mouseScrollDelta.y * 0.2f;
             translation *= Mathf.Pow(2.0f, boost);
             m_TargetCameraState.Translate(translation);
             // Framerate-independent interpolation
             // Calculate the lerp amount, such that we get 99% of the way to our target in the specified time
             var positionLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / positionLerpTime) * Time.deltaTime);
             var rotationLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / rotationLerpTime) * Time.deltaTime);
             m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct);
             m_InterpolatingCameraState.UpdateTransform(transform);
         }
     }
}

bump. I jsut want to add a zoom function to the SimpleCameraController

That’s a vague problem description and a lot of complex code, most of which looks irrelevant, and a lot of which is clearly needlessly complicated; e.g. line 68 could just use “value * Vector3.forward” and skip the ternary operator and the Abs() call.

But it’s probably also missing relevant stuff, because (for example) nothing in there actually calls SetZoom, and the values in your CameraState objects don’t appear to be getting applied to actual GameObjects at any point.

Sorry, disentangling this is too much work.

I’m calling SetZoom from another script. The zoom level changes. This is just the built-in camera controller script from unity. SetZoom calls UpdateTransform which updates the transform values.

I haven’t used that Unity template before, but your SetZoom function looks broken in at least 2 ways: it’s controlling camera position instead of FOV, and I can’t figure out why you’re referencing m_InterpolatingCameraState at all. Also, as previously mentioned, your calculation of the “translation” variable is pointlessly byzantine

But I don’t see anything in there that should be asymmetric between forwards and backwards. Given that you have offered no explanation at all as to what observations lead you to conclude that an asymmetry exists and that you haven’t given enough data for a reproduction of your functionality, my money’s on it being an optical illusion resulting from the fact that you’re probably doing linear camera movement but comparing it to exponential zooms from other games. But it could also absolutely be due to problems with the other script you haven’t posted that calls SetZoom, or a number of other things that are impossible to deduce from the information given.

OK thank you modifying the field of view works ok for now. It’s not an optical illusion though. I have a slider and when I slide it calls SetZoom with the value. The more I slide it and eventually the camera is very far back and won’t come back to its original place.

You realize that although your function is called SetZoom, it’s actually a delta, not an absolute value? If you call SetZoom(1) and then SetZoom(1) again, it will keep moving further every time even though you’re “setting” it to the same value.

Oh no didn’t realize. Where is it a delta?

CamersState.Translate uses += to add the new translation to the existing position.