FreeLookCam.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System;
  2. using UnityEngine;
  3. using UnityStandardAssets.CrossPlatformInput;
  4. namespace UnityStandardAssets.Cameras
  5. {
  6. public class FreeLookCam : PivotBasedCameraRig
  7. {
  8. // This script is designed to be placed on the root object of a camera rig,
  9. // comprising 3 gameobjects, each parented to the next:
  10. // Camera Rig
  11. // Pivot
  12. // Camera
  13. [SerializeField] private float m_MoveSpeed = 1f; // How fast the rig will move to keep up with the target's position.
  14. [Range(0f, 10f)] [SerializeField] private float m_TurnSpeed = 1.5f; // How fast the rig will rotate from user input.
  15. [SerializeField] private float m_TurnSmoothing = 0.0f; // How much smoothing to apply to the turn input, to reduce mouse-turn jerkiness
  16. [SerializeField] private float m_TiltMax = 75f; // The maximum value of the x axis rotation of the pivot.
  17. [SerializeField] private float m_TiltMin = 45f; // The minimum value of the x axis rotation of the pivot.
  18. [SerializeField] private bool m_LockCursor = false; // Whether the cursor should be hidden and locked.
  19. [SerializeField] private bool m_VerticalAutoReturn = false; // set wether or not the vertical axis should auto return
  20. private float m_LookAngle; // The rig's y axis rotation.
  21. private float m_TiltAngle; // The pivot's x axis rotation.
  22. private const float k_LookDistance = 100f; // How far in front of the pivot the character's look target is.
  23. private Vector3 m_PivotEulers;
  24. private Quaternion m_PivotTargetRot;
  25. private Quaternion m_TransformTargetRot;
  26. protected override void Awake()
  27. {
  28. base.Awake();
  29. // Lock or unlock the cursor.
  30. Cursor.lockState = m_LockCursor ? CursorLockMode.Locked : CursorLockMode.None;
  31. Cursor.visible = !m_LockCursor;
  32. m_PivotEulers = m_Pivot.rotation.eulerAngles;
  33. m_PivotTargetRot = m_Pivot.transform.localRotation;
  34. m_TransformTargetRot = transform.localRotation;
  35. }
  36. protected void Update()
  37. {
  38. HandleRotationMovement();
  39. if (m_LockCursor && Input.GetMouseButtonUp(0))
  40. {
  41. Cursor.lockState = m_LockCursor ? CursorLockMode.Locked : CursorLockMode.None;
  42. Cursor.visible = !m_LockCursor;
  43. }
  44. }
  45. private void OnDisable()
  46. {
  47. Cursor.lockState = CursorLockMode.None;
  48. Cursor.visible = true;
  49. }
  50. protected override void FollowTarget(float deltaTime)
  51. {
  52. if (m_Target == null) return;
  53. // Move the rig towards target position.
  54. transform.position = Vector3.Lerp(transform.position, m_Target.position, deltaTime*m_MoveSpeed);
  55. }
  56. private void HandleRotationMovement()
  57. {
  58. if(Time.timeScale < float.Epsilon)
  59. return;
  60. // Read the user input
  61. var x = CrossPlatformInputManager.GetAxis("Mouse X");
  62. var y = CrossPlatformInputManager.GetAxis("Mouse Y");
  63. // Adjust the look angle by an amount proportional to the turn speed and horizontal input.
  64. m_LookAngle += x*m_TurnSpeed;
  65. // Rotate the rig (the root object) around Y axis only:
  66. m_TransformTargetRot = Quaternion.Euler(0f, m_LookAngle, 0f);
  67. if (m_VerticalAutoReturn)
  68. {
  69. // For tilt input, we need to behave differently depending on whether we're using mouse or touch input:
  70. // on mobile, vertical input is directly mapped to tilt value, so it springs back automatically when the look input is released
  71. // we have to test whether above or below zero because we want to auto-return to zero even if min and max are not symmetrical.
  72. m_TiltAngle = y > 0 ? Mathf.Lerp(0, -m_TiltMin, y) : Mathf.Lerp(0, m_TiltMax, -y);
  73. }
  74. else
  75. {
  76. // on platforms with a mouse, we adjust the current angle based on Y mouse input and turn speed
  77. m_TiltAngle -= y*m_TurnSpeed;
  78. // and make sure the new value is within the tilt range
  79. m_TiltAngle = Mathf.Clamp(m_TiltAngle, -m_TiltMin, m_TiltMax);
  80. }
  81. // Tilt input around X is applied to the pivot (the child of this object)
  82. m_PivotTargetRot = Quaternion.Euler(m_TiltAngle, m_PivotEulers.y , m_PivotEulers.z);
  83. if (m_TurnSmoothing > 0)
  84. {
  85. m_Pivot.localRotation = Quaternion.Slerp(m_Pivot.localRotation, m_PivotTargetRot, m_TurnSmoothing * Time.deltaTime);
  86. transform.localRotation = Quaternion.Slerp(transform.localRotation, m_TransformTargetRot, m_TurnSmoothing * Time.deltaTime);
  87. }
  88. else
  89. {
  90. m_Pivot.localRotation = m_PivotTargetRot;
  91. transform.localRotation = m_TransformTargetRot;
  92. }
  93. }
  94. }
  95. }