CameraController.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. 
  2. // =================================
  3. // Namespaces.
  4. // =================================
  5. using UnityEngine;
  6. // =================================
  7. // Define namespace.
  8. // =================================
  9. namespace MirzaBeig
  10. {
  11. namespace Demos
  12. {
  13. namespace TheLastParticle
  14. {
  15. // =================================
  16. // Classes.
  17. // =================================
  18. //[ExecuteInEditMode]
  19. [System.Serializable]
  20. public class CameraController : MonoBehaviour
  21. {
  22. // =================================
  23. // Nested classes and structures.
  24. // =================================
  25. // ...
  26. public struct ClipPlanePoints
  27. {
  28. public Vector3 UpperLeft;
  29. public Vector3 UpperRight;
  30. public Vector3 LowerLeft;
  31. public Vector3 LowerRight;
  32. }
  33. // =================================
  34. // Variables.
  35. // =================================
  36. // ...
  37. new Camera camera;
  38. // Transforms.
  39. [Header("Transforms")]
  40. public Transform target;
  41. public Transform offset;
  42. // Position.
  43. [Header("Position")]
  44. public float followTargetSpeed = 8.0f;
  45. // Rotation.
  46. [Header("Rotation")]
  47. Vector2 mouseInput;
  48. public float mouseRotateAmount = 5.0f;
  49. public float mouseRotateSpeed = 5.0f;
  50. public float rotateZSpeed = 1.0f;
  51. public float resetZRotationSpeed = 5.0f;
  52. public Vector2 lookUpDownRange = new Vector2(-80.0f, 80.0f);
  53. // Zoom.
  54. [Header("Zoom")]
  55. public float zoomDistance = 4.0f;
  56. public float mouseZoomAmount = 1.0f;
  57. public float mouseZoomSpeed = 5.0f;
  58. public float mouseZoomMin = 1.0f;
  59. public float mouseZoomMax = 5.0f;
  60. // ...
  61. [Header("Occlusion Zoom")]
  62. public float occlusionZoomSpeed = 8.0f;
  63. public float occlusionZoomOffset = 0.0f;
  64. public float occlusionRaycastDownDistance = 0.5f;
  65. public AnimationCurve occlisionRaycastDownCurve =
  66. new AnimationCurve(new Keyframe(0.0f, 1.0f), new Keyframe(1.0f, 0.0f));
  67. // Offset framing.
  68. [Header("Offset (Framing)")]
  69. public float offsetFramingAmount = 2.0f;
  70. public float offsetFramingSpeed = 1.0f;
  71. public float minPlayerSpeedForOffsetFraming = 1.0f;
  72. public float minMouseMoveForOffsetFraming = 1.0f;
  73. Vector3 offsetStartPosition;
  74. Vector3 offsetPositionTarget;
  75. Vector3 offsetMouseFramePosition;
  76. // Stored locally as euler because Quaternions take shortest
  77. // path around for rotation. By using euler, I don't run into
  78. // the problem of spinning the camera too quickly and causing
  79. // a sudden snap because the rotation exceeded 180 degrees.
  80. Vector3 rotationEuler;
  81. Vector3 targetRotationEuler;
  82. // Player.
  83. Player player;
  84. // =================================
  85. // Functions.
  86. // =================================
  87. // ...
  88. void Awake()
  89. {
  90. }
  91. // ...
  92. void Start()
  93. {
  94. lockMouse();
  95. camera = Camera.main;
  96. player = FindObjectOfType<Player>();
  97. zoomDistance = Vector3.Distance(camera.transform.position, target.position);
  98. offsetStartPosition = offset.localPosition;
  99. offsetPositionTarget = offsetStartPosition;
  100. }
  101. // ...
  102. void lockMouse()
  103. {
  104. Cursor.visible = false;
  105. Cursor.lockState = CursorLockMode.Locked;
  106. }
  107. void unlockMouse()
  108. {
  109. Cursor.visible = true;
  110. Cursor.lockState = CursorLockMode.None;
  111. }
  112. // ...
  113. void FixedUpdate()
  114. {
  115. }
  116. // ...
  117. void Update()
  118. {
  119. // Input.
  120. mouseInput.x = Input.GetAxis("Mouse X");
  121. mouseInput.y = Input.GetAxis("Mouse Y");
  122. if (Input.GetMouseButtonDown(0))
  123. {
  124. lockMouse();
  125. }
  126. else if (Input.GetKeyDown(KeyCode.Escape))
  127. {
  128. unlockMouse();
  129. }
  130. }
  131. // ...
  132. void LateUpdate()
  133. {
  134. // Follow position.
  135. transform.position = Damping.dampVector3(transform.position, target.position, followTargetSpeed, Time.deltaTime);
  136. if (Cursor.lockState == CursorLockMode.Locked)
  137. {
  138. // Rotation.
  139. // Can't get it to smooth when rotating, so I just set the physica time step to 0.01f (half of default).
  140. targetRotationEuler.y += mouseInput.x * mouseRotateAmount;
  141. targetRotationEuler.x += -mouseInput.y * mouseRotateAmount;
  142. targetRotationEuler.x = Mathf.Clamp(targetRotationEuler.x, lookUpDownRange.x, lookUpDownRange.y);
  143. targetRotationEuler.z += mouseInput.x * rotateZSpeed;
  144. rotationEuler = Damping.dampVector3(rotationEuler, targetRotationEuler, mouseRotateSpeed, Time.deltaTime);
  145. transform.eulerAngles = rotationEuler;
  146. //transform.rotation *= Quaternion.AngleAxis(mouseRotateSpeed * Time.deltaTime, Vector3.up);
  147. // Offset framing.
  148. float playerSpeed = player.rb.velocity.magnitude;
  149. if (playerSpeed < minPlayerSpeedForOffsetFraming)
  150. {
  151. offsetMouseFramePosition = offsetStartPosition;
  152. }
  153. else
  154. {
  155. if (mouseInput.x > minMouseMoveForOffsetFraming)
  156. {
  157. offsetMouseFramePosition.x = -offsetFramingAmount;
  158. }
  159. else if (mouseInput.x < -minMouseMoveForOffsetFraming)
  160. {
  161. offsetMouseFramePosition.x = offsetFramingAmount;
  162. }
  163. if (mouseInput.y > minMouseMoveForOffsetFraming)
  164. {
  165. offsetMouseFramePosition.y = -offsetFramingAmount;
  166. }
  167. else if (mouseInput.y < -minMouseMoveForOffsetFraming)
  168. {
  169. offsetMouseFramePosition.y = offsetFramingAmount;
  170. }
  171. }
  172. offsetPositionTarget = Damping.dampVector3(offsetPositionTarget, offsetMouseFramePosition, offsetFramingSpeed, Time.deltaTime);
  173. // Balance out rotation around Z back to 0.0f.
  174. targetRotationEuler.z = Damping.dampFloat(targetRotationEuler.z, 0.0f, resetZRotationSpeed, Time.deltaTime);
  175. // Zoom.
  176. // Scrolling happens as 0.1f increments. x10.0f to make it 1.0f.
  177. float scroll = Input.GetAxis("Mouse ScrollWheel") * 10.0f;
  178. zoomDistance -= scroll * mouseZoomAmount;
  179. zoomDistance = Mathf.Clamp(zoomDistance, mouseZoomMin, mouseZoomMax);
  180. // Player occlusion check and zoom.
  181. RaycastHit hitInfo;
  182. checkIfPlayerOccluded(out hitInfo);
  183. //float nearestDistance = checkCameraPoints(out hitInfo);
  184. Vector3 finalOffsetPositionTarget;
  185. RaycastHit hitInfo2;
  186. Transform cameraTransform = camera.transform;
  187. Vector3 directionToTarget = (target.position - cameraTransform.position).normalized;
  188. Vector3 end = target.position - (directionToTarget * (zoomDistance + occlusionZoomOffset));
  189. Physics.Raycast(end, Vector3.down, out hitInfo2, occlusionRaycastDownDistance);
  190. Debug.DrawLine(end, end + (Vector3.down * occlusionRaycastDownDistance), Color.white);
  191. if (hitInfo.collider)
  192. {
  193. //finalOffsetPositionTarget = offsetPositionTarget.normalized * nearestDistance;
  194. finalOffsetPositionTarget = offsetPositionTarget.normalized * hitInfo.distance;
  195. }
  196. //if (hitInfo2.collider)
  197. //{
  198. // float curveResult = 1.0f - occlisionRaycastDownCurve.Evaluate(hitInfo2.distance / occlusionRaycastDownDistance);
  199. // finalOffsetPositionTarget = (offsetPositionTarget.normalized * zoomDistance) * curveResult;
  200. //}
  201. //else if (hitInfo.collider)
  202. //{
  203. // finalOffsetPositionTarget = Vector3.zero;
  204. //}
  205. else
  206. {
  207. finalOffsetPositionTarget = offsetPositionTarget.normalized * zoomDistance;
  208. }
  209. offset.localPosition = Damping.dampVector3(offset.localPosition, finalOffsetPositionTarget, mouseZoomSpeed, Time.deltaTime);
  210. }
  211. }
  212. // ...
  213. void checkIfPlayerOccluded(out RaycastHit hitInfo)
  214. {
  215. if (!camera)
  216. {
  217. camera = Camera.main;
  218. }
  219. Transform cameraTransform = camera.transform;
  220. Vector3 directionToTarget = (target.position - cameraTransform.position).normalized;
  221. Vector3 start = target.position;
  222. Vector3 end = Application.isPlaying ?
  223. (target.position - (directionToTarget * (zoomDistance + occlusionZoomOffset))) :
  224. (offset.position + (-directionToTarget * occlusionZoomOffset));
  225. Physics.Linecast(start, end, out hitInfo);
  226. if (!Application.isPlaying)
  227. {
  228. Gizmos.color =
  229. hitInfo.collider ? Color.red : Color.green;
  230. Gizmos.DrawLine(start, end);
  231. }
  232. else
  233. {
  234. Debug.DrawLine(start, end, hitInfo.collider ? Color.red : Color.green);
  235. }
  236. }
  237. // ...
  238. void OnDrawGizmos()
  239. {
  240. RaycastHit hitInfo;
  241. checkIfPlayerOccluded(out hitInfo);
  242. //checkCameraPoints(out hitInfo);
  243. }
  244. // =================================
  245. // End functions.
  246. // =================================
  247. }
  248. // =================================
  249. // End namespace.
  250. // =================================
  251. }
  252. }
  253. }
  254. // =================================
  255. // --END-- //
  256. // =================================