742 lines
19 KiB
C#
742 lines
19 KiB
C#
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
public class climbDetectionCollisionSystem : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
[Header ("Main Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxSpeed = 10f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxVerticalClimbSpeed = 4f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxHorizontalClimbSpeed = 4;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxDiagonalUpClimbSpeed = 4;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxDiagonalDownClimbSpeed = 4;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxSlideDownClimbSpeed = 6;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxBoostClimbSpeedMultiplier = 1.5f;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxAcceleration = 10f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxAirAcceleration = 1f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxClimbAcceleration = 40f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0, 90)]
|
|||
|
|
float maxGroundAngle = 25f, maxStairsAngle = 50f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (90, 170)]
|
|||
|
|
float maxClimbAngle = 140f;
|
|||
|
|
|
|||
|
|
[SerializeField, Range (0f, 100f)]
|
|||
|
|
float maxSnapSpeed = 100f;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
[SerializeField]
|
|||
|
|
float probeDistance = 1f;
|
|||
|
|
|
|||
|
|
[SerializeField]
|
|||
|
|
LayerMask probeMask = -1, stairsMask = -1, climbMask = -1;
|
|||
|
|
|
|||
|
|
[SerializeField]
|
|||
|
|
float sphereRadius = 0.5f;
|
|||
|
|
|
|||
|
|
[SerializeField]
|
|||
|
|
float sphereAlignSpeed = 45;
|
|||
|
|
|
|||
|
|
[SerializeField]
|
|||
|
|
float sphereAirRotation = 0.5f;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Curve Speed Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool useCurveSpeedEnabled = true;
|
|||
|
|
|
|||
|
|
public float horizontalCurveSpeed = 0.1f;
|
|||
|
|
public float verticalCurveSpeed = 0.1f;
|
|||
|
|
public float diagonalUpCurveSpeed = 0.1f;
|
|||
|
|
public float diagonalDownCurveSpeed = 0.1f;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public AnimationCurve climbSpeedCurve;
|
|||
|
|
public AnimationCurve climbBoostSpeedCurve;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Debug")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool anyOnGround;
|
|||
|
|
|
|||
|
|
public int climbContactCount;
|
|||
|
|
|
|||
|
|
public int groundContactCount;
|
|||
|
|
|
|||
|
|
public int steepContactCount;
|
|||
|
|
|
|||
|
|
public int stepsSinceLastGrounded;
|
|||
|
|
|
|||
|
|
public bool climbDetectionActive;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public Vector3 velocity;
|
|||
|
|
|
|||
|
|
public Vector3 contactNormal;
|
|||
|
|
|
|||
|
|
public Vector3 climbNormal;
|
|||
|
|
|
|||
|
|
public Vector3 steepNormal;
|
|||
|
|
public Vector3 lastClimbNormal;
|
|||
|
|
|
|||
|
|
public float currentCurveValue = 0;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Movement Debug")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool movingHorizontal;
|
|||
|
|
public bool movingVertical;
|
|||
|
|
public bool movingDiagonalUp;
|
|||
|
|
public bool movingDiagonalDown;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Components")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public freeClimbSystem mainFreeClimbSystem;
|
|||
|
|
|
|||
|
|
public Rigidbody mainRigidbody;
|
|||
|
|
|
|||
|
|
public Transform mainCameraTransform;
|
|||
|
|
|
|||
|
|
public Collider mainCollider;
|
|||
|
|
|
|||
|
|
public Collider mainPlayerCollider;
|
|||
|
|
|
|||
|
|
public Transform sphereTransform;
|
|||
|
|
|
|||
|
|
|
|||
|
|
Vector3 moveInput;
|
|||
|
|
|
|||
|
|
Rigidbody connectedBody;
|
|||
|
|
Rigidbody previousConnectedBody;
|
|||
|
|
|
|||
|
|
Vector3 connectionVelocity;
|
|||
|
|
|
|||
|
|
Vector3 connectionWorldPosition;
|
|||
|
|
Vector3 connectionLocalPosition;
|
|||
|
|
|
|||
|
|
Vector3 upAxis, rightAxis, forwardAxis;
|
|||
|
|
|
|||
|
|
Vector3 lastContactNormal;
|
|||
|
|
|
|||
|
|
Vector3 lastSteepNormal;
|
|||
|
|
|
|||
|
|
Vector3 lastConnectionVelocity;
|
|||
|
|
|
|||
|
|
float minGroundDotProduct, minStairsDotProduct, minClimbDotProduct;
|
|||
|
|
|
|||
|
|
Coroutine updateCoroutine;
|
|||
|
|
|
|||
|
|
float currentCurveSpeed = 0;
|
|||
|
|
|
|||
|
|
|
|||
|
|
public void updateObjectPosition (Vector3 newPosition)
|
|||
|
|
{
|
|||
|
|
transform.position = newPosition;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void enableOrDisableClimbDetection (bool state)
|
|||
|
|
{
|
|||
|
|
climbDetectionActive = state;
|
|||
|
|
|
|||
|
|
groundContactCount = 1;
|
|||
|
|
|
|||
|
|
mainRigidbody.isKinematic = !state;
|
|||
|
|
|
|||
|
|
mainCollider.enabled = state;
|
|||
|
|
|
|||
|
|
if (climbDetectionActive) {
|
|||
|
|
minGroundDotProduct = Mathf.Cos (maxGroundAngle * Mathf.Deg2Rad);
|
|||
|
|
|
|||
|
|
minStairsDotProduct = Mathf.Cos (maxStairsAngle * Mathf.Deg2Rad);
|
|||
|
|
|
|||
|
|
minClimbDotProduct = Mathf.Cos (maxClimbAngle * Mathf.Deg2Rad);
|
|||
|
|
|
|||
|
|
Physics.IgnoreCollision (mainCollider, mainPlayerCollider, true);
|
|||
|
|
|
|||
|
|
mainFreeClimbSystem.mainPlayerController.setIgnoreCollisionOnExternalColliderOnlyWithExtraColliderList (mainCollider, true);
|
|||
|
|
|
|||
|
|
Vector3 climbPosition = mainPlayerCollider.transform.position;
|
|||
|
|
|
|||
|
|
Vector3 climbDetectionCollisionPositionOffset = mainFreeClimbSystem.climbDetectionCollisionPositionOffset;
|
|||
|
|
|
|||
|
|
if (climbDetectionCollisionPositionOffset != Vector3.zero) {
|
|||
|
|
climbPosition += mainPlayerCollider.transform.right * climbDetectionCollisionPositionOffset.x;
|
|||
|
|
climbPosition += mainPlayerCollider.transform.up * climbDetectionCollisionPositionOffset.y;
|
|||
|
|
climbPosition += mainPlayerCollider.transform.forward * climbDetectionCollisionPositionOffset.z;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
transform.position = climbPosition;
|
|||
|
|
} else {
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mainPlayerCollider.isTrigger = state;
|
|||
|
|
|
|||
|
|
if (climbDetectionActive) {
|
|||
|
|
updateCoroutine = StartCoroutine (updateSystemCoroutine ());
|
|||
|
|
} else {
|
|||
|
|
stopUpdateCoroutine ();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void stopUpdateCoroutine ()
|
|||
|
|
{
|
|||
|
|
if (updateCoroutine != null) {
|
|||
|
|
StopCoroutine (updateCoroutine);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IEnumerator updateSystemCoroutine ()
|
|||
|
|
{
|
|||
|
|
var waitTime = new WaitForFixedUpdate ();
|
|||
|
|
|
|||
|
|
while (true) {
|
|||
|
|
updateSystem ();
|
|||
|
|
|
|||
|
|
yield return waitTime;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void updateSystem ()
|
|||
|
|
{
|
|||
|
|
moveInput.x = mainFreeClimbSystem.currentHorizontalMovement;
|
|||
|
|
moveInput.z = mainFreeClimbSystem.currentVerticalMovement;
|
|||
|
|
moveInput.y = 0;
|
|||
|
|
moveInput = Vector3.ClampMagnitude (moveInput, 1f);
|
|||
|
|
|
|||
|
|
|
|||
|
|
rightAxis = projectDirectionOnPlane (mainCameraTransform.right, upAxis);
|
|||
|
|
|
|||
|
|
forwardAxis = projectDirectionOnPlane (mainCameraTransform.forward, upAxis);
|
|||
|
|
|
|||
|
|
movingHorizontal = false;
|
|||
|
|
movingVertical = false;
|
|||
|
|
movingDiagonalUp = false;
|
|||
|
|
movingDiagonalDown = false;
|
|||
|
|
|
|||
|
|
if (moveInput.x != 0) {
|
|||
|
|
movingHorizontal = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (moveInput.z != 0) {
|
|||
|
|
movingVertical = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (movingHorizontal && movingVertical) {
|
|||
|
|
if (moveInput.z < 0) {
|
|||
|
|
movingDiagonalUp = false;
|
|||
|
|
movingDiagonalDown = true;
|
|||
|
|
} else {
|
|||
|
|
movingDiagonalUp = true;
|
|||
|
|
movingDiagonalDown = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
updateSphereState ();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
void FixedUpdate ()
|
|||
|
|
{
|
|||
|
|
if (climbDetectionActive) {
|
|||
|
|
anyOnGround = isOnGround ();
|
|||
|
|
|
|||
|
|
upAxis = mainFreeClimbSystem.getCurrentNormal ();
|
|||
|
|
|
|||
|
|
Vector3 gravity = -upAxis;
|
|||
|
|
//* mainVehicleGravityControl.getGravityForce ();
|
|||
|
|
|
|||
|
|
fixedUpdateSphereState ();
|
|||
|
|
|
|||
|
|
adjustVelocity ();
|
|||
|
|
|
|||
|
|
if (climbSurfaceDetected ()) {
|
|||
|
|
velocity -= contactNormal * (maxClimbAcceleration * 0.9f * Time.deltaTime);
|
|||
|
|
|
|||
|
|
} else if (isOnGround () && velocity.sqrMagnitude < 0.01f) {
|
|||
|
|
velocity += contactNormal * (Vector3.Dot (gravity, contactNormal) * Time.deltaTime);
|
|||
|
|
|
|||
|
|
} else if (climbDetectionActive && isOnGround ()) {
|
|||
|
|
velocity += (gravity - contactNormal * (maxClimbAcceleration * 0.9f)) * Time.deltaTime;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
velocity += gravity * Time.deltaTime;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
mainRigidbody.linearVelocity = velocity;
|
|||
|
|
|
|||
|
|
mainFreeClimbSystem.updateClimbContactCount (climbContactCount);
|
|||
|
|
|
|||
|
|
mainFreeClimbSystem.updateContactNormal (contactNormal);
|
|||
|
|
|
|||
|
|
mainFreeClimbSystem.updateLastClimbNormal (lastClimbNormal);
|
|||
|
|
|
|||
|
|
clearState ();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void updateSphereState ()
|
|||
|
|
{
|
|||
|
|
Vector3 rotationPlaneNormal = lastContactNormal;
|
|||
|
|
|
|||
|
|
float rotationFactor = 1f;
|
|||
|
|
|
|||
|
|
if (climbSurfaceDetected ()) {
|
|||
|
|
|
|||
|
|
} else if (!isOnGround ()) {
|
|||
|
|
if (isOnSteep ()) {
|
|||
|
|
rotationPlaneNormal = lastSteepNormal;
|
|||
|
|
} else {
|
|||
|
|
rotationFactor = sphereAirRotation;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Vector3 movement = (mainRigidbody.linearVelocity - lastConnectionVelocity) * Time.deltaTime;
|
|||
|
|
|
|||
|
|
movement -= rotationPlaneNormal * Vector3.Dot (movement, rotationPlaneNormal);
|
|||
|
|
|
|||
|
|
float distance = movement.magnitude;
|
|||
|
|
|
|||
|
|
Quaternion rotation = sphereTransform.localRotation;
|
|||
|
|
|
|||
|
|
if (connectedBody != null && connectedBody == previousConnectedBody) {
|
|||
|
|
rotation = Quaternion.Euler (connectedBody.angularVelocity * (Mathf.Rad2Deg * Time.deltaTime)) * rotation;
|
|||
|
|
|
|||
|
|
if (distance < 0.001f) {
|
|||
|
|
sphereTransform.localRotation = rotation;
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
} else if (distance < 0.001f) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float angle = distance * rotationFactor * (180f / Mathf.PI) / sphereRadius;
|
|||
|
|
|
|||
|
|
Vector3 rotationAxis = Vector3.Cross (rotationPlaneNormal, movement).normalized;
|
|||
|
|
|
|||
|
|
rotation = Quaternion.Euler (rotationAxis * angle) * rotation;
|
|||
|
|
|
|||
|
|
if (sphereAlignSpeed > 0f) {
|
|||
|
|
rotation = alignSphereRotation (rotationAxis, rotation, distance);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sphereTransform.localRotation = rotation;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Quaternion alignSphereRotation (Vector3 rotationAxis, Quaternion rotation, float traveledDistance)
|
|||
|
|
{
|
|||
|
|
Vector3 sphereAxis = sphereTransform.up;
|
|||
|
|
|
|||
|
|
float dot = Mathf.Clamp (Vector3.Dot (sphereAxis, rotationAxis), -1f, 1f);
|
|||
|
|
|
|||
|
|
float angle = Mathf.Acos (dot) * Mathf.Rad2Deg;
|
|||
|
|
|
|||
|
|
float maxAngle = sphereAlignSpeed * traveledDistance;
|
|||
|
|
|
|||
|
|
Quaternion newAlignment = Quaternion.FromToRotation (sphereAxis, rotationAxis) * rotation;
|
|||
|
|
|
|||
|
|
if (angle <= maxAngle) {
|
|||
|
|
return newAlignment;
|
|||
|
|
} else {
|
|||
|
|
return Quaternion.SlerpUnclamped (rotation, newAlignment, maxAngle / angle);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void clearState ()
|
|||
|
|
{
|
|||
|
|
lastContactNormal = contactNormal;
|
|||
|
|
|
|||
|
|
lastSteepNormal = steepNormal;
|
|||
|
|
|
|||
|
|
lastConnectionVelocity = connectionVelocity;
|
|||
|
|
|
|||
|
|
groundContactCount = steepContactCount = climbContactCount = 0;
|
|||
|
|
|
|||
|
|
contactNormal = steepNormal = climbNormal = Vector3.zero;
|
|||
|
|
|
|||
|
|
connectionVelocity = Vector3.zero;
|
|||
|
|
|
|||
|
|
previousConnectedBody = connectedBody;
|
|||
|
|
|
|||
|
|
connectedBody = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void fixedUpdateSphereState ()
|
|||
|
|
{
|
|||
|
|
stepsSinceLastGrounded += 1;
|
|||
|
|
|
|||
|
|
velocity = mainRigidbody.linearVelocity;
|
|||
|
|
|
|||
|
|
if (checkClimbing () ||
|
|||
|
|
isOnGround () ||
|
|||
|
|
snapToGround () ||
|
|||
|
|
checkSteepContacts ()) {
|
|||
|
|
|
|||
|
|
stepsSinceLastGrounded = 0;
|
|||
|
|
|
|||
|
|
if (groundContactCount > 1) {
|
|||
|
|
contactNormal.Normalize ();
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
contactNormal = upAxis;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (connectedBody != null) {
|
|||
|
|
if (connectedBody.isKinematic || connectedBody.mass >= mainRigidbody.mass) {
|
|||
|
|
updateConnectionState ();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void updateConnectionState ()
|
|||
|
|
{
|
|||
|
|
if (connectedBody == previousConnectedBody) {
|
|||
|
|
Vector3 connectionMovement = connectedBody.transform.TransformPoint (connectionLocalPosition) - connectionWorldPosition;
|
|||
|
|
|
|||
|
|
connectionVelocity = connectionMovement / Time.deltaTime;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
connectionWorldPosition = mainRigidbody.position;
|
|||
|
|
|
|||
|
|
connectionLocalPosition = connectedBody.transform.InverseTransformPoint (connectionWorldPosition);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool checkClimbing ()
|
|||
|
|
{
|
|||
|
|
if (climbSurfaceDetected ()) {
|
|||
|
|
if (climbContactCount > 1) {
|
|||
|
|
climbNormal.Normalize ();
|
|||
|
|
|
|||
|
|
float upDot = Vector3.Dot (upAxis, climbNormal);
|
|||
|
|
|
|||
|
|
if (upDot >= minGroundDotProduct) {
|
|||
|
|
climbNormal = lastClimbNormal;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
groundContactCount = 1;
|
|||
|
|
|
|||
|
|
contactNormal = climbNormal;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool snapToGround ()
|
|||
|
|
{
|
|||
|
|
if (stepsSinceLastGrounded > 1) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float speed = velocity.magnitude;
|
|||
|
|
|
|||
|
|
if (speed > maxSnapSpeed) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
RaycastHit hit;
|
|||
|
|
|
|||
|
|
if (!Physics.Raycast (mainRigidbody.position, -upAxis, out hit, probeDistance, probeMask, QueryTriggerInteraction.Ignore)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Vector3 hitNormal = hit.normal;
|
|||
|
|
|
|||
|
|
float upDot = Vector3.Dot (upAxis, hitNormal);
|
|||
|
|
|
|||
|
|
if (upDot < getMinDot (hit.collider.gameObject.layer)) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
groundContactCount = 1;
|
|||
|
|
|
|||
|
|
contactNormal = hitNormal;
|
|||
|
|
|
|||
|
|
float dot = Vector3.Dot (velocity, hitNormal);
|
|||
|
|
|
|||
|
|
if (dot > 0f) {
|
|||
|
|
velocity = (velocity - hitNormal * dot).normalized * speed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
connectedBody = hit.rigidbody;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool checkSteepContacts ()
|
|||
|
|
{
|
|||
|
|
if (steepContactCount > 1) {
|
|||
|
|
steepNormal.Normalize ();
|
|||
|
|
|
|||
|
|
float upDot = Vector3.Dot (upAxis, steepNormal);
|
|||
|
|
|
|||
|
|
if (upDot >= minGroundDotProduct) {
|
|||
|
|
steepContactCount = 0;
|
|||
|
|
|
|||
|
|
groundContactCount = 1;
|
|||
|
|
|
|||
|
|
contactNormal = steepNormal;
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void adjustVelocity ()
|
|||
|
|
{
|
|||
|
|
float acceleration, speed;
|
|||
|
|
|
|||
|
|
Vector3 xAxis, zAxis;
|
|||
|
|
|
|||
|
|
float boostInput = mainFreeClimbSystem.getCurrentClimbTurboSpeed ();
|
|||
|
|
|
|||
|
|
bool usingBoost = mainFreeClimbSystem.isTurboActive () && !mainFreeClimbSystem.isPauseTurboActive ();
|
|||
|
|
|
|||
|
|
bool isSlidingDownActive = mainFreeClimbSystem.isSlidingDownActive ();
|
|||
|
|
|
|||
|
|
float currentMaxSpeed = maxSpeed;
|
|||
|
|
|
|||
|
|
if (climbSurfaceDetected ()) {
|
|||
|
|
acceleration = maxClimbAcceleration;
|
|||
|
|
|
|||
|
|
speed = maxHorizontalClimbSpeed;
|
|||
|
|
|
|||
|
|
if (movingDiagonalDown) {
|
|||
|
|
speed = maxDiagonalDownClimbSpeed;
|
|||
|
|
} else if (movingDiagonalUp) {
|
|||
|
|
speed = maxDiagonalUpClimbSpeed;
|
|||
|
|
} else if (movingVertical) {
|
|||
|
|
speed = maxVerticalClimbSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isSlidingDownActive) {
|
|||
|
|
speed = maxSlideDownClimbSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (usingBoost) {
|
|||
|
|
speed *= maxBoostClimbSpeedMultiplier;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
xAxis = Vector3.Cross (contactNormal, upAxis);
|
|||
|
|
|
|||
|
|
zAxis = upAxis;
|
|||
|
|
} else {
|
|||
|
|
acceleration = isOnGround () ? maxAcceleration : maxAirAcceleration;
|
|||
|
|
|
|||
|
|
float currentClimbSpeed = maxHorizontalClimbSpeed; ;
|
|||
|
|
|
|||
|
|
if (movingDiagonalDown) {
|
|||
|
|
currentClimbSpeed = maxDiagonalDownClimbSpeed;
|
|||
|
|
} else if (movingDiagonalUp) {
|
|||
|
|
currentClimbSpeed = maxDiagonalUpClimbSpeed;
|
|||
|
|
} else if (movingVertical) {
|
|||
|
|
currentClimbSpeed = maxVerticalClimbSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isSlidingDownActive) {
|
|||
|
|
speed = maxSlideDownClimbSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (usingBoost) {
|
|||
|
|
currentClimbSpeed *= maxBoostClimbSpeedMultiplier;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
speed = isOnGround () && climbDetectionActive ? currentClimbSpeed : currentMaxSpeed;
|
|||
|
|
|
|||
|
|
xAxis = rightAxis;
|
|||
|
|
zAxis = forwardAxis;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
xAxis = projectDirectionOnPlane (xAxis, contactNormal);
|
|||
|
|
zAxis = projectDirectionOnPlane (zAxis, contactNormal);
|
|||
|
|
|
|||
|
|
if (useCurveSpeedEnabled) {
|
|||
|
|
|
|||
|
|
currentCurveSpeed = 0;
|
|||
|
|
|
|||
|
|
if (movingDiagonalDown) {
|
|||
|
|
currentCurveSpeed = diagonalDownCurveSpeed;
|
|||
|
|
} else if (movingDiagonalUp) {
|
|||
|
|
currentCurveSpeed = diagonalUpCurveSpeed;
|
|||
|
|
} else if (movingVertical) {
|
|||
|
|
currentCurveSpeed = verticalCurveSpeed;
|
|||
|
|
} else if (movingHorizontal) {
|
|||
|
|
currentCurveSpeed = horizontalCurveSpeed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (isSlidingDownActive) {
|
|||
|
|
currentCurveSpeed = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (currentCurveSpeed != 0) {
|
|||
|
|
var time = Mathf.Repeat ((float)Time.time, 1.0F);
|
|||
|
|
|
|||
|
|
if (usingBoost) {
|
|||
|
|
currentCurveValue = climbBoostSpeedCurve.Evaluate (time) * currentCurveSpeed;
|
|||
|
|
} else {
|
|||
|
|
currentCurveValue = climbSpeedCurve.Evaluate (time) * currentCurveSpeed;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (currentCurveValue != 0) {
|
|||
|
|
speed *= currentCurveValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Vector3 relativeVelocity = velocity - connectionVelocity;
|
|||
|
|
|
|||
|
|
Vector3 adjustment;
|
|||
|
|
|
|||
|
|
adjustment.x = moveInput.x * speed - Vector3.Dot (relativeVelocity, xAxis);
|
|||
|
|
adjustment.z = moveInput.z * speed - Vector3.Dot (relativeVelocity, zAxis);
|
|||
|
|
adjustment.y = 0f;
|
|||
|
|
|
|||
|
|
adjustment = Vector3.ClampMagnitude (adjustment, acceleration * Time.deltaTime);
|
|||
|
|
|
|||
|
|
velocity += (xAxis * adjustment.x + zAxis * adjustment.z) * boostInput;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool isOnGround ()
|
|||
|
|
{
|
|||
|
|
return groundContactCount > 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool isOnSteep ()
|
|||
|
|
{
|
|||
|
|
return steepContactCount > 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool climbSurfaceDetected ()
|
|||
|
|
{
|
|||
|
|
return climbContactCount > 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OnCollisionEnter (Collision collision)
|
|||
|
|
{
|
|||
|
|
EvaluateCollision (collision);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OnCollisionStay (Collision collision)
|
|||
|
|
{
|
|||
|
|
EvaluateCollision (collision);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void EvaluateCollision (Collision collision)
|
|||
|
|
{
|
|||
|
|
int layer = collision.gameObject.layer;
|
|||
|
|
|
|||
|
|
float minDot = getMinDot (layer);
|
|||
|
|
|
|||
|
|
for (int i = 0; i < collision.contacts.Length; i++) {
|
|||
|
|
Vector3 normal = collision.contacts [i].normal;
|
|||
|
|
|
|||
|
|
float upDot = Vector3.Dot (upAxis, normal);
|
|||
|
|
|
|||
|
|
if (upDot >= minDot) {
|
|||
|
|
groundContactCount += 1;
|
|||
|
|
|
|||
|
|
contactNormal += normal;
|
|||
|
|
|
|||
|
|
connectedBody = collision.rigidbody;
|
|||
|
|
} else {
|
|||
|
|
if (upDot > -0.01f) {
|
|||
|
|
steepContactCount += 1;
|
|||
|
|
|
|||
|
|
steepNormal += normal;
|
|||
|
|
|
|||
|
|
if (groundContactCount == 0) {
|
|||
|
|
connectedBody = collision.rigidbody;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (climbDetectionActive && upDot >= minClimbDotProduct && (climbMask & (1 << layer)) != 0) {
|
|||
|
|
|
|||
|
|
climbContactCount += 1;
|
|||
|
|
|
|||
|
|
climbNormal += normal;
|
|||
|
|
|
|||
|
|
lastClimbNormal = normal;
|
|||
|
|
|
|||
|
|
connectedBody = collision.rigidbody;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Vector3 projectDirectionOnPlane (Vector3 direction, Vector3 normal)
|
|||
|
|
{
|
|||
|
|
return (direction - normal * Vector3.Dot (direction, normal)).normalized;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float getMinDot (int layer)
|
|||
|
|
{
|
|||
|
|
if ((stairsMask & (1 << layer)) == 0) {
|
|||
|
|
return minGroundDotProduct;
|
|||
|
|
} else {
|
|||
|
|
return minStairsDotProduct;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public Vector3 getMainRigidbodyVelocity ()
|
|||
|
|
{
|
|||
|
|
return mainRigidbody.linearVelocity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public Vector3 getMainRigidbodyPosition ()
|
|||
|
|
{
|
|||
|
|
return mainRigidbody.position;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public Vector3 getLastClimbNormal ()
|
|||
|
|
{
|
|||
|
|
return lastClimbNormal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public Vector3 getContactNormal ()
|
|||
|
|
{
|
|||
|
|
return contactNormal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setNewParent (Transform newParent)
|
|||
|
|
{
|
|||
|
|
transform.SetParent (newParent);
|
|||
|
|
}
|
|||
|
|
}
|