SimpleCameraController.cs 6.0 KB

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