CharacterBase.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using UnityEngine;
  2. using System.Collections;
  3. namespace RootMotion.Demos {
  4. /// <summary>
  5. /// The base abstract class for all character controllers, provides common functionality.
  6. /// </summary>
  7. public abstract class CharacterBase: MonoBehaviour {
  8. [Header("Base Parameters")]
  9. [Tooltip("If specified, will use the direction from the character to this Transform as the gravity vector instead of Physics.gravity. Physics.gravity.magnitude will be used as the magnitude of the gravity vector.")]
  10. public Transform gravityTarget;
  11. [Tooltip("Multiplies gravity applied to the character even if 'Individual Gravity' is unchecked.")]
  12. public float gravityMultiplier = 2f; // gravity modifier - often higher than natural gravity feels right for game characters
  13. public float airborneThreshold = 0.6f; // Height from ground after which the character is considered airborne
  14. public float slopeStartAngle = 50f; // The start angle of velocity dampering on slopes
  15. public float slopeEndAngle = 85f; // The end angle of velocity dampering on slopes
  16. public float spherecastRadius = 0.1f; // The radius of sperecasting
  17. public LayerMask groundLayers; // The walkable layers
  18. private PhysicMaterial zeroFrictionMaterial;
  19. private PhysicMaterial highFrictionMaterial;
  20. protected Rigidbody r;
  21. protected const float half = 0.5f;
  22. protected float originalHeight;
  23. protected Vector3 originalCenter;
  24. protected CapsuleCollider capsule;
  25. public abstract void Move(Vector3 deltaPosition, Quaternion deltaRotation);
  26. protected Vector3 GetGravity() {
  27. if (gravityTarget != null) {
  28. return (gravityTarget.position - transform.position).normalized * Physics.gravity.magnitude;
  29. }
  30. return Physics.gravity;
  31. }
  32. protected virtual void Start() {
  33. capsule = GetComponent<Collider>() as CapsuleCollider;
  34. r = GetComponent<Rigidbody>();
  35. // Store the collider volume
  36. originalHeight = capsule.height;
  37. originalCenter = capsule.center;
  38. // Physics materials
  39. zeroFrictionMaterial = new PhysicMaterial();
  40. zeroFrictionMaterial.dynamicFriction = 0f;
  41. zeroFrictionMaterial.staticFriction = 0f;
  42. zeroFrictionMaterial.frictionCombine = PhysicMaterialCombine.Minimum;
  43. zeroFrictionMaterial.bounciness = 0f;
  44. zeroFrictionMaterial.bounceCombine = PhysicMaterialCombine.Minimum;
  45. highFrictionMaterial = new PhysicMaterial();
  46. // Making sure rigidbody rotation is fixed
  47. r.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
  48. }
  49. // Spherecast from the root to find ground height
  50. protected virtual RaycastHit GetSpherecastHit() {
  51. Vector3 up = transform.up;
  52. Ray ray = new Ray (r.position + up * airborneThreshold, -up);
  53. RaycastHit h = new RaycastHit();
  54. h.point = transform.position - transform.transform.up * airborneThreshold;
  55. h.normal = transform.up;
  56. Physics.SphereCast(ray, spherecastRadius, out h, airborneThreshold * 2f, groundLayers);
  57. return h;
  58. }
  59. // Gets angle around y axis from a world space direction
  60. public float GetAngleFromForward(Vector3 worldDirection) {
  61. Vector3 local = transform.InverseTransformDirection(worldDirection);
  62. return Mathf.Atan2 (local.x, local.z) * Mathf.Rad2Deg;
  63. }
  64. // Rotate a rigidbody around a point and axis by angle
  65. protected void RigidbodyRotateAround(Vector3 point, Vector3 axis, float angle) {
  66. Quaternion rotation = Quaternion.AngleAxis(angle, axis);
  67. Vector3 d = transform.position - point;
  68. r.MovePosition(point + rotation * d);
  69. r.MoveRotation(rotation * transform.rotation);
  70. }
  71. // Scale the capsule collider to 'mlp' of the initial value
  72. protected void ScaleCapsule (float mlp) {
  73. if (capsule.height != originalHeight * mlp) {
  74. capsule.height = Mathf.MoveTowards (capsule.height, originalHeight * mlp, Time.deltaTime * 4);
  75. capsule.center = Vector3.MoveTowards (capsule.center, originalCenter * mlp, Time.deltaTime * 2);
  76. }
  77. }
  78. // Set the collider to high friction material
  79. protected void HighFriction() {
  80. capsule.material = highFrictionMaterial;
  81. }
  82. // Set the collider to zero friction material
  83. protected void ZeroFriction() {
  84. capsule.material = zeroFrictionMaterial;
  85. }
  86. // Get the damper of velocity on the slopes
  87. protected float GetSlopeDamper(Vector3 velocity, Vector3 groundNormal) {
  88. float angle = 90f - Vector3.Angle(velocity, groundNormal);
  89. angle -= slopeStartAngle;
  90. float range = slopeEndAngle - slopeStartAngle;
  91. return 1f - Mathf.Clamp(angle / range, 0f, 1f);
  92. }
  93. }
  94. }