/Assets/EleetTools/CharacterMotor.cs

https://bitbucket.org/bbuck/finalproject_csc490 · C# · 163 lines · 129 code · 31 blank · 3 comment · 29 complexity · 2e082bb625e9b19bf16571a12047b863 MD5 · raw file

  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. public enum MovementState
  5. {
  6. Grounded,
  7. InAir,
  8. OnWall
  9. }
  10. [RequireComponent(typeof(Rigidbody))]
  11. public class CharacterMotor : MonoBehaviour {
  12. public float maxVelocityChange = 1.0f;
  13. public float jumpHeight = 1.0f;
  14. public bool canJump = true;
  15. public bool canWallJump = true;
  16. public float airSpeed = 0.1f;
  17. public float wallSpeedAdjustment = 0.1f;
  18. public bool canMoveOnY = false;
  19. [HideInInspector]
  20. public Vector3 targetVelocity = Vector3.zero;
  21. [HideInInspector]
  22. public MovementState State { get; private set; }
  23. public bool OnGround
  24. {
  25. get
  26. {
  27. return State == MovementState.Grounded;
  28. }
  29. }
  30. public bool AbleToJump
  31. {
  32. get
  33. {
  34. return (State == MovementState.Grounded && canJump) || (State == MovementState.OnWall && canWallJump);
  35. }
  36. }
  37. public bool InAir
  38. {
  39. get
  40. {
  41. return State == MovementState.InAir || (!canWallJump && State == MovementState.OnWall);
  42. }
  43. }
  44. private const float OnGroundValue = .9f;
  45. private const float OnWallValue = 0.005f;
  46. private bool jumpQueued = false;
  47. private Vector3 lastContactNormal;
  48. void FixedUpdate()
  49. {
  50. Vector3 velocity = rigidbody.velocity;
  51. velocity = (targetVelocity - velocity);
  52. velocity = velocity.normalized * Mathf.Clamp(velocity.magnitude, 0, maxVelocityChange);
  53. if (!canMoveOnY)
  54. velocity.y = 0;
  55. if (State != MovementState.Grounded)
  56. velocity = velocity * airSpeed;
  57. if (State == MovementState.OnWall)
  58. velocity.x *= wallSpeedAdjustment;
  59. if (jumpQueued && AbleToJump)
  60. {
  61. ExecuteJump();
  62. jumpQueued = false;
  63. }
  64. rigidbody.AddForce(velocity, ForceMode.VelocityChange);
  65. //print(string.Format("Current State: {0}", Enum.GetName(typeof(MovementState), State)));
  66. State = MovementState.InAir;
  67. }
  68. void OnCollisionStay(Collision collision)
  69. {
  70. if (State == MovementState.Grounded)
  71. return;
  72. lastContactNormal = collision.contacts[0].normal;
  73. float totalDot = 0f;
  74. foreach (ContactPoint point in collision.contacts)
  75. {
  76. totalDot += Vector3.Dot(point.normal, Vector3.up);
  77. }
  78. float avgDot = totalDot / collision.contacts.Length;
  79. //print(string.Format("Average DOT: {0}", avgDot));
  80. if (Approximately(avgDot, OnGroundValue))
  81. State = MovementState.Grounded;
  82. else if (avgDot >= 0)
  83. State = MovementState.OnWall;
  84. }
  85. #region helper functions
  86. void ExecuteJump()
  87. {
  88. float jumpSpeed = Mathf.Sqrt(2 * jumpHeight * -Physics.gravity.y);
  89. rigidbody.velocity = new Vector3(rigidbody.velocity.x, jumpSpeed, rigidbody.velocity.z);
  90. if (State == MovementState.OnWall)
  91. {
  92. float xVel = rigidbody.velocity.x;
  93. xVel = lastContactNormal.x * 5f;
  94. rigidbody.AddForce(new Vector3(xVel, 0, 0), ForceMode.VelocityChange);
  95. }
  96. }
  97. // HACK: Mathf.Approximately didn't suit my needs
  98. bool Approximately(float a, float b) {
  99. float rangeMax, rangeMin;
  100. if (a >= 0.1)
  101. {
  102. rangeMax = a + 0.1f;
  103. rangeMin = a - 0.1f;
  104. }
  105. else if (a > 0.01)
  106. {
  107. rangeMax = a + 0.01f;
  108. rangeMin = a - 0.01f;
  109. }
  110. else // a > 0.001f
  111. {
  112. rangeMax = a + 0.001f;
  113. rangeMin = a - 0.001f;
  114. }
  115. return b > rangeMin && b < rangeMax;
  116. }
  117. #endregion helper functions
  118. #region public functions
  119. public void Impulse(Vector3 direction)
  120. {
  121. rigidbody.AddForce(direction, ForceMode.VelocityChange);
  122. }
  123. public void Jump()
  124. {
  125. jumpQueued = true;
  126. }
  127. public void CancelJump()
  128. {
  129. jumpQueued = false;
  130. }
  131. #endregion public functions
  132. }