SimpleCameraController.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using UnityEditor;
  2. using UnityEngine;
  3. namespace UnityTemplateProjects
  4. {
  5. public class SimpleCameraController : MonoBehaviour
  6. {
  7. [Header("Movement Settings")] [Tooltip("Exponential boost factor on translation, controllable by mouse wheel.")]
  8. public float boost = 3.5f;
  9. [Tooltip("Time it takes to interpolate camera position 99% of the way to the target.")] [Range(0.001f, 1f)]
  10. public float positionLerpTime = 0.2f;
  11. [Header("Rotation Settings")]
  12. [Tooltip("X = Change in mouse position.\nY = Multiplicative factor for camera rotation.")]
  13. public AnimationCurve mouseSensitivityCurve =
  14. new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f));
  15. [Tooltip("Time it takes to interpolate camera rotation 99% of the way to the target.")] [Range(0.001f, 1f)]
  16. public float rotationLerpTime = 0.01f;
  17. [Tooltip("Whether or not to invert our Y axis for mouse input to rotation.")]
  18. public bool invertY;
  19. private readonly CameraState m_InterpolatingCameraState = new CameraState();
  20. private readonly CameraState m_TargetCameraState = new CameraState();
  21. private void Update()
  22. {
  23. // Exit Sample
  24. if (Input.GetKey(KeyCode.Escape))
  25. {
  26. Application.Quit();
  27. #if UNITY_EDITOR
  28. EditorApplication.isPlaying = false;
  29. #endif
  30. }
  31. // Hide and lock cursor when right mouse button pressed
  32. if (Input.GetMouseButtonDown(1)) Cursor.lockState = CursorLockMode.Locked;
  33. // Unlock and show cursor when right mouse button released
  34. if (Input.GetMouseButtonUp(1))
  35. {
  36. Cursor.visible = true;
  37. Cursor.lockState = CursorLockMode.None;
  38. }
  39. // Rotation
  40. if (Input.GetMouseButton(1))
  41. {
  42. var mouseMovement =
  43. new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") * (invertY ? 1 : -1));
  44. var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude);
  45. m_TargetCameraState.yaw += mouseMovement.x * mouseSensitivityFactor;
  46. m_TargetCameraState.pitch += mouseMovement.y * mouseSensitivityFactor;
  47. }
  48. // Translation
  49. var translation = GetInputTranslationDirection() * Time.deltaTime;
  50. // Speed up movement when shift key held
  51. if (Input.GetKey(KeyCode.LeftShift)) translation *= 10.0f;
  52. // Modify movement by a boost factor (defined in Inspector and modified in play mode through the mouse scroll wheel)
  53. boost += Input.mouseScrollDelta.y * 0.2f;
  54. translation *= Mathf.Pow(2.0f, boost);
  55. m_TargetCameraState.Translate(translation);
  56. // Framerate-independent interpolation
  57. // Calculate the lerp amount, such that we get 99% of the way to our target in the specified time
  58. var positionLerpPct = 1f - Mathf.Exp(Mathf.Log(1f - 0.99f) / positionLerpTime * Time.deltaTime);
  59. var rotationLerpPct = 1f - Mathf.Exp(Mathf.Log(1f - 0.99f) / rotationLerpTime * Time.deltaTime);
  60. m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct);
  61. m_InterpolatingCameraState.UpdateTransform(transform);
  62. }
  63. private void OnEnable()
  64. {
  65. m_TargetCameraState.SetFromTransform(transform);
  66. m_InterpolatingCameraState.SetFromTransform(transform);
  67. }
  68. private Vector3 GetInputTranslationDirection()
  69. {
  70. var direction = new Vector3();
  71. if (Input.GetKey(KeyCode.W)) direction += Vector3.forward;
  72. if (Input.GetKey(KeyCode.S)) direction += Vector3.back;
  73. if (Input.GetKey(KeyCode.A)) direction += Vector3.left;
  74. if (Input.GetKey(KeyCode.D)) direction += Vector3.right;
  75. if (Input.GetKey(KeyCode.Q)) direction += Vector3.down;
  76. if (Input.GetKey(KeyCode.E)) direction += Vector3.up;
  77. return direction;
  78. }
  79. private class CameraState
  80. {
  81. public float pitch;
  82. public float roll;
  83. public float x;
  84. public float y;
  85. public float yaw;
  86. public float z;
  87. public void SetFromTransform(Transform t)
  88. {
  89. pitch = t.eulerAngles.x;
  90. yaw = t.eulerAngles.y;
  91. roll = t.eulerAngles.z;
  92. x = t.position.x;
  93. y = t.position.y;
  94. z = t.position.z;
  95. }
  96. public void Translate(Vector3 translation)
  97. {
  98. var rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation;
  99. x += rotatedTranslation.x;
  100. y += rotatedTranslation.y;
  101. z += rotatedTranslation.z;
  102. }
  103. public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct)
  104. {
  105. yaw = Mathf.Lerp(yaw, target.yaw, rotationLerpPct);
  106. pitch = Mathf.Lerp(pitch, target.pitch, rotationLerpPct);
  107. roll = Mathf.Lerp(roll, target.roll, rotationLerpPct);
  108. x = Mathf.Lerp(x, target.x, positionLerpPct);
  109. y = Mathf.Lerp(y, target.y, positionLerpPct);
  110. z = Mathf.Lerp(z, target.z, positionLerpPct);
  111. }
  112. public void UpdateTransform(Transform t)
  113. {
  114. t.eulerAngles = new Vector3(pitch, yaw, roll);
  115. t.position = new Vector3(x, y, z);
  116. }
  117. }
  118. }
  119. }