You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			119 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			119 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								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);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |