I am rotating a globe like XCOM's hologlobe,
I rotate it using Quaternion.RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta).
I found a good value for maxDegreesDelta, in my case it is 5.0f.
There is a limit on how close or far the camera can be, let's assume clos is 1.0f and far is 2.0f.
I want to be able to zoom into the globe, but obviously when I do, it rotates a bit too fast then.
When zoomed out, rotation speed is satisfying:
When zoomed in, rotation is too fast, making it more difficult to manipulate:
And the problem is even more evident as game view size gets bigger, i.e. fullscreen.
Using Mathf.Lerp and Mathf.InverseLerp, I've tried to make maxDegreesDelta and mouse delta proportional to the distance the camera is but it's hardly convincing.
Note: I rotate the globe, not the camera.
Question:
How can I ensure object rotates at same speed on screen, no matter how close or far camera is ?
Code:
(assumes there is a sphere of radius 0.5 at Vector3.zero and camera is positioned at Vector3.back)
using UnityEngine; using UnityEngine.InputSystem; namespace Test2 { public class GeoScapeController : MonoBehaviour { #region Public public Transform TargetObject; public Camera TargetCamera; [Range(0.01f, 1.0f)] public float Sensitivity; public bool Smooth; public float ZoomDistanceMin; public float ZoomDistanceMax; #endregion #region Private [SerializeField] [HideInInspector] private Quaternion TargetRotation; [SerializeField] [HideInInspector] private int ZoomLevel; [SerializeField] [HideInInspector] private int ZoomLevels; [SerializeField] [HideInInspector] private Vector3 ZoomVector; [SerializeField] [HideInInspector] private Vector3 ZoomVelocity; private void Reset() { Sensitivity = 0.05f; Smooth = true; ZoomDistanceMin = 0.625F; ZoomDistanceMax = 1.25F; ZoomLevels = 10; } private void Start() { TargetRotation = Quaternion.LookRotation(TargetObject.forward, TargetObject.up); ZoomVector = TargetCamera.transform.position; } private void Update() { var mouse = Mouse.current; var delta = mouse.delta.ReadValue(); var scale = new Vector4(-1.0f, +1.0f, +1.0f); var x = mouse.leftButton.isPressed ? delta.y * scale.y * Sensitivity : 0.0f; var y = mouse.leftButton.isPressed ? delta.x * scale.x * Sensitivity : 0.0f; var z = mouse.middleButton.isPressed ? delta.x * scale.z * Sensitivity : 0.0f; var r = Quaternion.AngleAxis(x, Vector3.right) * Quaternion.AngleAxis(y, Vector3.up) * Quaternion.AngleAxis(z, Vector3.forward); if (Smooth) // hopefully, quaternion limits won't be crossed ! { TargetRotation = Quaternion.RotateTowards(TargetRotation, r * TargetRotation, 2.5f); TargetObject.rotation = Quaternion.Slerp(TargetObject.rotation, TargetRotation, Time.deltaTime * 5.0f); } else { TargetObject.rotation = TargetRotation = r * TargetRotation; } var wheel = (int) mouse.scroll.ReadValue().y / 120; if (wheel != 0) { ZoomLevel = Mathf.Clamp(ZoomLevel + wheel, 0, ZoomLevels); var lerp1 = Mathf.InverseLerp(ZoomLevels, 0, ZoomLevel); var lerp2 = Mathf.Lerp(ZoomDistanceMin, ZoomDistanceMax, lerp1); ZoomVector = Vector3.back * lerp2; } TargetCamera.transform.position = Smooth ? Vector3.SmoothDamp(TargetCamera.transform.position, ZoomVector, ref ZoomVelocity, 0.3f) : ZoomVector; } #endregion } } 



