PlayerController.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using UnityEngine;
  2. namespace Mirror.Examples.AdditiveLevels
  3. {
  4. [RequireComponent(typeof(CapsuleCollider))]
  5. [RequireComponent(typeof(CharacterController))]
  6. [RequireComponent(typeof(NetworkTransformReliable))]
  7. [RequireComponent(typeof(Rigidbody))]
  8. public class PlayerController : NetworkBehaviour
  9. {
  10. public enum GroundState : byte { Jumping, Falling, Grounded }
  11. [Header("Avatar Components")]
  12. public CharacterController characterController;
  13. [Header("Movement")]
  14. [Range(1, 20)]
  15. public float moveSpeedMultiplier = 8f;
  16. [Header("Turning")]
  17. [Range(1f, 200f)]
  18. public float maxTurnSpeed = 100f;
  19. [Range(.5f, 5f)]
  20. public float turnDelta = 3f;
  21. [Header("Jumping")]
  22. [Range(0.1f, 1f)]
  23. public float initialJumpSpeed = 0.2f;
  24. [Range(1f, 10f)]
  25. public float maxJumpSpeed = 5f;
  26. [Range(0.1f, 1f)]
  27. public float jumpDelta = 0.2f;
  28. [Header("Diagnostics - Do Not Modify")]
  29. public GroundState groundState = GroundState.Grounded;
  30. [Range(-1f, 1f)]
  31. public float horizontal;
  32. [Range(-1f, 1f)]
  33. public float vertical;
  34. [Range(-200f, 200f)]
  35. public float turnSpeed;
  36. [Range(-10f, 10f)]
  37. public float jumpSpeed;
  38. [Range(-1.5f, 1.5f)]
  39. public float animVelocity;
  40. [Range(-1.5f, 1.5f)]
  41. public float animRotation;
  42. public Vector3Int velocity;
  43. public Vector3 direction;
  44. protected override void OnValidate()
  45. {
  46. base.OnValidate();
  47. if (characterController == null)
  48. characterController = GetComponent<CharacterController>();
  49. // Override CharacterController default values
  50. characterController.enabled = false;
  51. characterController.skinWidth = 0.02f;
  52. characterController.minMoveDistance = 0f;
  53. GetComponent<Rigidbody>().isKinematic = true;
  54. this.enabled = false;
  55. }
  56. public override void OnStartAuthority()
  57. {
  58. characterController.enabled = true;
  59. this.enabled = true;
  60. }
  61. public override void OnStopAuthority()
  62. {
  63. this.enabled = false;
  64. characterController.enabled = false;
  65. }
  66. void Update()
  67. {
  68. if (!characterController.enabled)
  69. return;
  70. HandleTurning();
  71. HandleJumping();
  72. HandleMove();
  73. // Reset ground state
  74. if (characterController.isGrounded)
  75. groundState = GroundState.Grounded;
  76. else if (groundState != GroundState.Jumping)
  77. groundState = GroundState.Falling;
  78. // Diagnostic velocity...FloorToInt for display purposes
  79. velocity = Vector3Int.FloorToInt(characterController.velocity);
  80. }
  81. // TODO: Turning works while airborne...feature?
  82. void HandleTurning()
  83. {
  84. // Q and E cancel each other out, reducing the turn to zero.
  85. if (Input.GetKey(KeyCode.Q))
  86. turnSpeed = Mathf.MoveTowards(turnSpeed, -maxTurnSpeed, turnDelta);
  87. if (Input.GetKey(KeyCode.E))
  88. turnSpeed = Mathf.MoveTowards(turnSpeed, maxTurnSpeed, turnDelta);
  89. // If both pressed, reduce turning speed toward zero.
  90. if (Input.GetKey(KeyCode.Q) && Input.GetKey(KeyCode.E))
  91. turnSpeed = Mathf.MoveTowards(turnSpeed, 0, turnDelta);
  92. // If neither pressed, reduce turning speed toward zero.
  93. if (!Input.GetKey(KeyCode.Q) && !Input.GetKey(KeyCode.E))
  94. turnSpeed = Mathf.MoveTowards(turnSpeed, 0, turnDelta);
  95. transform.Rotate(0f, turnSpeed * Time.deltaTime, 0f);
  96. }
  97. void HandleJumping()
  98. {
  99. // Handle variable force jumping.
  100. // Jump starts with initial power on takeoff, and jumps higher / longer
  101. // as player holds spacebar. Jump power is increased by a diminishing amout
  102. // every frame until it reaches maxJumpSpeed, or player releases the spacebar,
  103. // and then changes to the falling state until it gets grounded.
  104. if (groundState != GroundState.Falling && Input.GetKey(KeyCode.Space))
  105. {
  106. if (groundState != GroundState.Jumping)
  107. {
  108. // Start jump at initial power.
  109. groundState = GroundState.Jumping;
  110. jumpSpeed = initialJumpSpeed;
  111. }
  112. else
  113. // Jumping has already started...increase power toward maxJumpSpeed over time.
  114. jumpSpeed = Mathf.MoveTowards(jumpSpeed, maxJumpSpeed, jumpDelta);
  115. // If power has reached maxJumpSpeed, change to falling until grounded.
  116. // This prevents over-applying jump power while already in the air.
  117. if (jumpSpeed == maxJumpSpeed)
  118. groundState = GroundState.Falling;
  119. }
  120. else if (groundState != GroundState.Grounded)
  121. {
  122. // handles running off a cliff and/or player released Spacebar.
  123. groundState = GroundState.Falling;
  124. jumpSpeed = Mathf.Min(jumpSpeed, maxJumpSpeed);
  125. jumpSpeed += Physics.gravity.y * Time.deltaTime;
  126. }
  127. else
  128. jumpSpeed = Physics.gravity.y * Time.deltaTime;
  129. }
  130. // TODO: Directional input works while airborne...feature?
  131. void HandleMove()
  132. {
  133. // Capture inputs
  134. horizontal = Input.GetAxis("Horizontal");
  135. vertical = Input.GetAxis("Vertical");
  136. // Create initial direction vector without jumpSpeed (y-axis).
  137. direction = new Vector3(horizontal, 0f, vertical);
  138. // Clamp so diagonal strafing isn't a speed advantage.
  139. direction = Vector3.ClampMagnitude(direction, 1f);
  140. // Transforms direction from local space to world space.
  141. direction = transform.TransformDirection(direction);
  142. // Multiply for desired ground speed.
  143. direction *= moveSpeedMultiplier;
  144. // Add jumpSpeed to direction as last step.
  145. direction.y = jumpSpeed;
  146. // Finally move the character.
  147. characterController.Move(direction * Time.deltaTime);
  148. }
  149. }
  150. }