123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.Demos {
- /// <summary>
- /// The base abstract class for all character controllers, provides common functionality.
- /// </summary>
- public abstract class CharacterBase: MonoBehaviour {
- [Header("Base Parameters")]
- [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.")]
- public Transform gravityTarget;
- [Tooltip("Multiplies gravity applied to the character even if 'Individual Gravity' is unchecked.")]
- public float gravityMultiplier = 2f; // gravity modifier - often higher than natural gravity feels right for game characters
- public float airborneThreshold = 0.6f; // Height from ground after which the character is considered airborne
- public float slopeStartAngle = 50f; // The start angle of velocity dampering on slopes
- public float slopeEndAngle = 85f; // The end angle of velocity dampering on slopes
- public float spherecastRadius = 0.1f; // The radius of sperecasting
- public LayerMask groundLayers; // The walkable layers
- private PhysicMaterial zeroFrictionMaterial;
- private PhysicMaterial highFrictionMaterial;
- protected Rigidbody r;
- protected const float half = 0.5f;
- protected float originalHeight;
- protected Vector3 originalCenter;
- protected CapsuleCollider capsule;
- public abstract void Move(Vector3 deltaPosition, Quaternion deltaRotation);
- protected Vector3 GetGravity() {
- if (gravityTarget != null) {
- return (gravityTarget.position - transform.position).normalized * Physics.gravity.magnitude;
- }
- return Physics.gravity;
- }
- protected virtual void Start() {
- capsule = GetComponent<Collider>() as CapsuleCollider;
- r = GetComponent<Rigidbody>();
- // Store the collider volume
- originalHeight = capsule.height;
- originalCenter = capsule.center;
- // Physics materials
- zeroFrictionMaterial = new PhysicMaterial();
- zeroFrictionMaterial.dynamicFriction = 0f;
- zeroFrictionMaterial.staticFriction = 0f;
- zeroFrictionMaterial.frictionCombine = PhysicMaterialCombine.Minimum;
- zeroFrictionMaterial.bounciness = 0f;
- zeroFrictionMaterial.bounceCombine = PhysicMaterialCombine.Minimum;
- highFrictionMaterial = new PhysicMaterial();
- // Making sure rigidbody rotation is fixed
- r.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
- }
- // Spherecast from the root to find ground height
- protected virtual RaycastHit GetSpherecastHit() {
- Vector3 up = transform.up;
- Ray ray = new Ray (r.position + up * airborneThreshold, -up);
- RaycastHit h = new RaycastHit();
- h.point = transform.position - transform.transform.up * airborneThreshold;
- h.normal = transform.up;
- Physics.SphereCast(ray, spherecastRadius, out h, airborneThreshold * 2f, groundLayers);
- return h;
- }
- // Gets angle around y axis from a world space direction
- public float GetAngleFromForward(Vector3 worldDirection) {
- Vector3 local = transform.InverseTransformDirection(worldDirection);
- return Mathf.Atan2 (local.x, local.z) * Mathf.Rad2Deg;
- }
- // Rotate a rigidbody around a point and axis by angle
- protected void RigidbodyRotateAround(Vector3 point, Vector3 axis, float angle) {
- Quaternion rotation = Quaternion.AngleAxis(angle, axis);
- Vector3 d = transform.position - point;
- r.MovePosition(point + rotation * d);
- r.MoveRotation(rotation * transform.rotation);
- }
- // Scale the capsule collider to 'mlp' of the initial value
- protected void ScaleCapsule (float mlp) {
- if (capsule.height != originalHeight * mlp) {
- capsule.height = Mathf.MoveTowards (capsule.height, originalHeight * mlp, Time.deltaTime * 4);
- capsule.center = Vector3.MoveTowards (capsule.center, originalCenter * mlp, Time.deltaTime * 2);
- }
- }
- // Set the collider to high friction material
- protected void HighFriction() {
- capsule.material = highFrictionMaterial;
- }
- // Set the collider to zero friction material
- protected void ZeroFriction() {
- capsule.material = zeroFrictionMaterial;
- }
- // Get the damper of velocity on the slopes
- protected float GetSlopeDamper(Vector3 velocity, Vector3 groundNormal) {
- float angle = 90f - Vector3.Angle(velocity, groundNormal);
- angle -= slopeStartAngle;
- float range = slopeEndAngle - slopeStartAngle;
- return 1f - Mathf.Clamp(angle / range, 0f, 1f);
- }
- }
- }
|