MyFirstPersonController.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. using System;
  2. using UnityEngine;
  3. using UnityStandardAssets.CrossPlatformInput;
  4. using UnityStandardAssets.Utility;
  5. using Random = UnityEngine.Random;
  6. using UnityCommon;
  7. #pragma warning disable 618, 649
  8. namespace UnityStandardAssets.Characters.FirstPerson
  9. {
  10. [RequireComponent(typeof(CharacterController))]
  11. //[RequireComponent(typeof(AudioSource))]
  12. public class MyFirstPersonController : MonoBehaviour
  13. {
  14. [SerializeField] private bool m_IsWalking;
  15. [SerializeField] private float m_WalkSpeed;
  16. [SerializeField] private float m_RunSpeed;
  17. [SerializeField][Range(0f, 1f)] private float m_RunstepLenghten;
  18. [SerializeField] private float m_JumpSpeed;
  19. [SerializeField] private float m_StickToGroundForce;
  20. [SerializeField] private float m_GravityMultiplier;
  21. [SerializeField] private MouseLook m_MouseLook;
  22. [SerializeField] private bool m_UseFovKick;
  23. [SerializeField] private FOVKick m_FovKick = new FOVKick();
  24. [SerializeField] private bool m_UseHeadBob;
  25. [SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob();
  26. [SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob();
  27. [SerializeField] private float m_StepInterval;
  28. //[SerializeField] private AudioClip[] m_FootstepSounds; // an array of footstep sounds that will be randomly selected from.
  29. //[SerializeField] private AudioClip m_JumpSound; // the sound played when character leaves the ground.
  30. //[SerializeField] private AudioClip m_LandSound; // the sound played when character touches back on ground.
  31. private Camera m_Camera;
  32. private bool m_Jump;
  33. private float m_YRotation;
  34. private Vector2 m_Input;
  35. private Vector3 m_MoveDir = Vector3.zero;
  36. private CharacterController m_CharacterController;
  37. private CollisionFlags m_CollisionFlags;
  38. private bool m_PreviouslyGrounded;
  39. private Vector3 m_OriginalCameraPosition;
  40. private float m_StepCycle;
  41. private float m_NextStep;
  42. private bool m_Jumping;
  43. //private AudioSource m_AudioSource;
  44. // Use this for initialization
  45. private void Start()
  46. {
  47. m_CharacterController = GetComponent<CharacterController>();
  48. m_Camera = Camera.main;
  49. Camera.main.tag = "MainCamera";
  50. m_OriginalCameraPosition = m_Camera.transform.localPosition;
  51. m_FovKick.Setup(m_Camera);
  52. m_HeadBob.Setup(m_Camera, m_StepInterval);
  53. m_StepCycle = 0f;
  54. m_NextStep = m_StepCycle / 2f;
  55. m_Jumping = false;
  56. //m_AudioSource = GetComponent<AudioSource>();
  57. m_MouseLook.Init(transform, m_Camera.transform);
  58. #if ENABLE_INPUT_SYSTEM
  59. InitInputSystem();
  60. #endif
  61. }
  62. #if ENABLE_INPUT_SYSTEM
  63. public InputCtrlCamera.CameraCtrlActions inputActions;
  64. private void InitInputSystem()
  65. {
  66. inputActions = new InputCtrlCamera().CameraCtrl;
  67. inputActions.Enable();
  68. }
  69. #endif
  70. public void MouseLookInit()
  71. {
  72. m_MouseLook?.Init(transform, m_Camera.transform);
  73. }
  74. public void SetPosition(Vector3 newPosition)
  75. {
  76. m_OriginalCameraPosition = newPosition;
  77. }
  78. // Update is called once per frame
  79. private void Update()
  80. {
  81. if (Input.GetMouseButton(1))//Êó±êÓÒ¼üÐýת
  82. {
  83. RotateView();
  84. //Cursor.visible = false;
  85. //Cursor.lockState = CursorLockMode.Locked;
  86. }
  87. else
  88. {
  89. Cursor.visible = true;
  90. Cursor.lockState = CursorLockMode.None;
  91. }
  92. // the jump state needs to read here to make sure it is not missed
  93. if (!m_Jump)
  94. {
  95. m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
  96. }
  97. if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
  98. {
  99. StartCoroutine(m_JumpBob.DoBobCycle());
  100. PlayLandingSound();
  101. m_MoveDir.y = 0f;
  102. m_Jumping = false;
  103. }
  104. if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
  105. {
  106. m_MoveDir.y = 0f;
  107. }
  108. m_PreviouslyGrounded = m_CharacterController.isGrounded;
  109. }
  110. private void PlayLandingSound()
  111. {
  112. //m_AudioSource.clip = m_LandSound;
  113. //m_AudioSource.Play();
  114. m_NextStep = m_StepCycle + .5f;
  115. }
  116. private void FixedUpdate()
  117. {
  118. float speed;
  119. GetInput(out speed);
  120. // always move along the camera forward as it is the direction that it being aimed at
  121. Vector3 desiredMove = transform.forward * m_Input.y + transform.right * m_Input.x;
  122. // get a normal for the surface that is being touched to move along it
  123. RaycastHit hitInfo;
  124. Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
  125. m_CharacterController.height / 2f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
  126. desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
  127. m_MoveDir.x = desiredMove.x * speed;
  128. m_MoveDir.z = desiredMove.z * speed;
  129. if (m_CharacterController.isGrounded)
  130. {
  131. m_MoveDir.y = -m_StickToGroundForce;
  132. if (m_Jump)
  133. {
  134. m_MoveDir.y = m_JumpSpeed;
  135. PlayJumpSound();
  136. m_Jump = false;
  137. m_Jumping = true;
  138. }
  139. }
  140. else
  141. {
  142. m_MoveDir += Physics.gravity * m_GravityMultiplier * Time.fixedDeltaTime;
  143. }
  144. m_CollisionFlags = m_CharacterController.Move(m_MoveDir * Time.fixedDeltaTime);
  145. ProgressStepCycle(speed);
  146. UpdateCameraPosition(speed);
  147. m_MouseLook.UpdateCursorLock();
  148. }
  149. private void PlayJumpSound()
  150. {
  151. //m_AudioSource.clip = m_JumpSound;
  152. //m_AudioSource.Play();
  153. }
  154. private void ProgressStepCycle(float speed)
  155. {
  156. if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
  157. {
  158. m_StepCycle += (m_CharacterController.velocity.magnitude + (speed * (m_IsWalking ? 1f : m_RunstepLenghten))) *
  159. Time.fixedDeltaTime;
  160. }
  161. if (!(m_StepCycle > m_NextStep))
  162. {
  163. return;
  164. }
  165. m_NextStep = m_StepCycle + m_StepInterval;
  166. PlayFootStepAudio();
  167. }
  168. private void PlayFootStepAudio()
  169. {
  170. if (!m_CharacterController.isGrounded)
  171. {
  172. return;
  173. }
  174. // pick & play a random footstep sound from the array,
  175. // excluding sound at index 0
  176. //int n = Random.Range(1, m_FootstepSounds.Length);
  177. //m_AudioSource.clip = m_FootstepSounds[n];
  178. //m_AudioSource.PlayOneShot(m_AudioSource.clip);
  179. //// move picked sound to index 0 so it's not picked next time
  180. //m_FootstepSounds[n] = m_FootstepSounds[0];
  181. //m_FootstepSounds[0] = m_AudioSource.clip;
  182. }
  183. private void UpdateCameraPosition(float speed)
  184. {
  185. Vector3 newCameraPosition;
  186. if (!m_UseHeadBob)
  187. {
  188. return;
  189. }
  190. if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
  191. {
  192. m_Camera.transform.localPosition =
  193. m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
  194. (speed * (m_IsWalking ? 1f : m_RunstepLenghten)));
  195. newCameraPosition = m_Camera.transform.localPosition;
  196. newCameraPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
  197. }
  198. else
  199. {
  200. newCameraPosition = m_Camera.transform.localPosition;
  201. newCameraPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
  202. }
  203. m_Camera.transform.localPosition = newCameraPosition;
  204. }
  205. private void GetInput(out float speed)
  206. {
  207. #if ENABLE_INPUT_SYSTEM
  208. var vec2 = inputActions.Move.ReadValue<Vector2>();
  209. float horizontal = vec2.x;
  210. float vertical = vec2.y;
  211. #else
  212. // Read input
  213. float horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
  214. float vertical = CrossPlatformInputManager.GetAxis("Vertical");
  215. #endif
  216. bool waswalking = m_IsWalking;
  217. #if !MOBILE_INPUT
  218. // On standalone builds, walk/run speed is modified by a key press.
  219. // keep track of whether or not the character is walking or running
  220. m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
  221. #endif
  222. // set the desired speed to be walking or running
  223. speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
  224. m_Input = new Vector2(horizontal, vertical);
  225. // normalize input if it exceeds 1 in combined length:
  226. if (m_Input.sqrMagnitude > 1)
  227. {
  228. m_Input.Normalize();
  229. }
  230. // handle speed change to give an fov kick
  231. // only if the player is going to a run, is running and the fovkick is to be used
  232. if (m_IsWalking != waswalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0)
  233. {
  234. StopAllCoroutines();
  235. StartCoroutine(!m_IsWalking ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
  236. }
  237. }
  238. private void RotateView()
  239. {
  240. if (!UnityCommon.Utility.IsPointerOverUIObject())
  241. m_MouseLook.LookRotation(transform, m_Camera.transform);
  242. }
  243. private void OnControllerColliderHit(ControllerColliderHit hit)
  244. {
  245. Rigidbody body = hit.collider.attachedRigidbody;
  246. //dont move the rigidbody if the character is on top of it
  247. if (m_CollisionFlags == CollisionFlags.Below)
  248. {
  249. return;
  250. }
  251. if (body == null || body.isKinematic)
  252. {
  253. return;
  254. }
  255. body.AddForceAtPosition(m_CharacterController.velocity * 0.1f, hit.point, ForceMode.Impulse);
  256. }
  257. }
  258. }