Files
FueraDeEscala/Assets/Game Kit Controller/Scripts/Player/Extra Movements/freeClimbSystem.cs
Robii Aragon fd87a6ffd5 add ckg
plantilla base para movimiento básico
2026-02-05 05:07:55 -08:00

3337 lines
107 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class freeClimbSystem : externalControllerBehavior
{
[Header ("Main Settings")]
[Space]
public bool climbEnabled = true;
public bool climbCheckCanBeUsed = true;
public float minDistanceToSurfaceToGrabSurfaceOnGround = 0.8f;
public float minDistanceToSurfaceToGrabSurfaceOnAir = 1;
public bool activateClimbStateDirectlyOnPressInput;
public bool canActivateClimbOnPlayerOnGround = true;
public bool ignoreActivateClimbStateOnNextSurfaceDetectedActive;
public float surfaceOffset = 0.05f;
public float minWaitTimeSinceLastTimeActionActiveToClimb = 0.6f;
[Space]
[Header ("Climb Method Settings")]
[Space]
public bool useRaycastDetectionToClimb = true;
public climbDetectionCollisionSystem mainClimbDetectionCollisionSystem;
public Vector3 climbDetectionCollisionPositionOffset;
public bool updateRigidbodyPositionSmoothlyOnDetectionCollision = true;
public float minDelayToAdjustDetectionCollision = 1;
public float adjustToFoundSurfaceSpeed = 4;
public float adjustToFoundSurfaceOffset = 0.3f;
[Space]
[Header ("Reset Rotation Settings")]
[Space]
public float resetPlayerRotationSpeed = 5;
public bool rotateCameraToPlayerRotationOnClimbActiveEnabled = true;
[Space]
public bool useCameraOffsetOnClimbActiveEnabled;
public Vector3 cameraOffsetOnClimbActive;
public float cameraOffsetOnClimbActiveLerpSpeed;
[Space]
[Header ("Stop Climb Settings")]
[Space]
public float offsetToCheckIfStopClimbStateOnRaycast = 1;
public float minTimeToStopClimbIfNotSurfaceFound = 0.3f;
public float maxRaycastDistanceToStopClimb = 0.75f;
[Space]
[Header ("Surface Detection Settings")]
[Space]
public LayerMask raycastLayermask;
public float raycastDistance = 0.6f;
public float raycastDistanceToCheckToActivateClimbOnGround = 0.9f;
public float raycastDistanceToCheckToActivateClimbOnAir = 0.9f;
public float verticalRaycastOffset = 1;
[Space]
public bool useClimbZoneDetectionRaycast;
public float upOffsetToDetectSurfaceOnMovementInput = 0.5f;
public float downOffsetToDetectSurfaceOnMovementInput = 0.2f;
public float rightOffsetToDetectSurfaceOnMovementInput = 0.2f;
public float leftOffsetToDetectSurfaceOnMovementInput = 0.2f;
[Space]
[Header ("Surface To Ignore Settings")]
[Space]
public bool useSurfacesToIgnoreTags;
public List<string> surfacesToIgnoreTagsList = new List<string> ();
[Space]
public bool useSurfacesToCheckTagsOnClimbByInput;
public List<string> surfacesToCheckTagsOnClimbByInputList = new List<string> ();
public bool checkForClimbSurfaceZoneSystemOnClimbInput;
[Space]
public bool avoidMovementTowardSurfacesToIgnore;
public bool stopClimbIfSurfaceToIgnoreDetected;
public bool avoidMovementTowardNoClimbZones;
public bool ignoreRigidbodies;
[Space]
[Header ("Surface In Front Detection Settings")]
[Space]
public bool checkSurfaceForLowerBodyEnabled = true;
public bool useHangStateOnNoSurfaceOnLowerBody = true;
public float lowerBodyRaycastOffset = 0.5f;
public float upperBodyRaycastOffset = 1.5f;
[Space]
[Header ("Surface In Top And Bottom Detection Settings")]
[Space]
public bool checkSurfaceAbovePlayerEnabled = true;
public float abovePlayerRaycastOffset = 0.5f;
public bool checkSurfaceBelowPlayerEnabled = true;
public float belowPlayerRaycastOffset = -0.2f;
[Space]
[Header ("Surface Sides Detection Settings")]
[Space]
public bool checkSidesEnabled = true;
public float raycastDistanceToCheckSides = 0.8f;
public bool checkCloseSidesEnabled = true;
public float raycastDistanceToCheckCloseSides = 0.7f;
[Space]
[Header ("Slide Down Settings")]
[Space]
public bool slideDownEnabled = true;
public float slideDownSpeedThirdPerson = 10;
public float SlideDownSpeedFirstPerson = 10;
[Space]
[Header ("Other Settings")]
[Space]
public bool useMovementCurve = true;
public AnimationCurve mainMovementCurve;
public bool useVelocityCurve = true;
public AnimationCurve mainVelocityCurve;
public bool stopClimbAtMinAngleOnSurface = true;
public float minAngleToStopClimb = -50;
public bool stopClimbAtMaxAngleOnSurface = true;
public float maxAngleToStopClimb = 50;
public float minTimeAngleLimitReachedToStopClimb = 1;
public bool disableClimbStateOnDamageReceivedEnabled;
[Space]
[Header ("Climb Settings")]
[Space]
public float climbMovementSpeedThirdPerson = 5;
public float climbMovementSpeedFirstPerson = 5;
public float climbVelocityThirdPerson = 5;
public float climbVelocityFirstPerson = 5;
public float climbRotationSpeedThirdPerson = 200;
public float climbRotationSpeedFirstPerson = 100;
[Space]
[Header ("Speed Settings")]
[Space]
public float climbTurboSpeed = 2;
public Vector3 impulseOnJump;
public float maxVelocityChangeSlide;
public float jumpRotationSpeedThirdPerson = 1;
public float jumpRotationSpeedFirstPerson = 0.5f;
[Space]
[Header ("Weapons Settings")]
[Space]
public bool keepWeapons;
public bool drawWeaponsIfCarriedPreviously;
[Space]
[Header ("Third Person Settings")]
[Space]
public int actionID = 5654231;
public string freeClimbAnimatorName = "Free Climb";
public bool checkIfClimbHangOnAirForAction = true;
public int freeClimbHangFromAirActionID = 5654232;
public bool checkIfClimbHangOnGroundForAction = true;
public int freeClimbHangFromGroundActionID = 5654233;
public float minDelayToUseMovementInputOnClimbStart = 0.5f;
public string externalControlleBehaviorActiveAnimatorName = "External Behavior Active";
public string actionIDAnimatorName = "Action ID";
public string horizontalAnimatorName = "Horizontal Action";
public string verticalAnimatorName = "Vertical Action";
public float inputLerpSpeed = 3;
[Space]
[Header ("Third Person Camera State Settings")]
[Space]
public bool setNewCameraStateOnThirdPerson;
public string newCameraStateOnThirdPerson;
[Space]
[Header ("Climb Top Part Settings")]
[Space]
public Transform climbSurfaceActionSystemTransform;
public float maxAngleDifferenceOnSurfaceToClimb = 20;
public float checkTopSurfaceRaycastOffset = 1.3f;
public float climbSurfaceTopSpeed = 2;
[Space]
[Space]
public eventParameters.eventToCallWithGameObject eventToActivateClimbSurfaceActionSystem;
[Space]
[Header ("Debug")]
[Space]
public bool showDebugPrint;
public bool checkIfDetectClimbActive;
public bool climbActive;
public bool isFirstPersonActive;
public bool carryingWeaponsPreviously;
public bool climbPaused;
public bool activateClimbStateOnNextSurfaceDetectedActive;
public bool slidingDownActive;
public bool activateAutoSlideDownOnSurface;
public bool slidingDownResult;
public bool playerParentAssigned;
public bool adjustingPlayerToSurfaceCollisionDetection;
[Space]
[Header ("Surfaces Detected Debug")]
[Space]
public float surfaceAngle;
public bool surfaceFoundOnSide;
public bool surfaceFoundOnCloseSide;
public bool surfaceFoundOnRegularRaycast;
public bool upperBodySurfaceDetected;
public bool lowerBodySurfaceDetected;
public bool surfaceDetectedAbovePlayer;
public bool surfafeDetectedBelowPlayer;
public int climbContactCount;
public Vector3 contactNormal;
public Vector3 lastClimbNormal;
public float angleDifferenceWithSurface;
public bool surfaceDetectedOnMovementInputRaycast;
[Space]
[Header ("Movement Input Debug")]
[Space]
public float currentVerticalMovement;
public float currentHorizontalMovement;
public Vector2 rawAxisValues;
public bool moving;
public bool movementInputPressed;
public bool climbStateActivatedByInput;
public bool movementInputPausedActive;
public bool movementInputDisabledOnSurface;
public bool cancelMovementInputActive;
public bool turboActive;
public bool pauseTurboActive;
[Space]
[Header ("Gizmo Settings")]
[Space]
public bool showGizmo;
[Space]
[Header ("First Person Events Settings")]
[Space]
public bool useEventsOnFirstPerson;
public UnityEvent eventOnStartFirstPerson;
public UnityEvent eventOnEndFirstPerson;
[Space]
[Header ("Third Person Events Settings")]
[Space]
public bool useEventsOnThirdPerson;
public UnityEvent eventOnStartThirdPerson;
public UnityEvent eventOnEndThirdPerson;
[Space]
[Header ("Other Events")]
[Space]
public UnityEvent eventOnCheckForClimbStateActive;
public UnityEvent eventOnStopCheckForClimbStateActive;
[Space]
[Space]
public UnityEvent eventOnClimbStateActive;
public UnityEvent eventOnStopClimbStateActive;
[Space]
public UnityEvent eventBeforeCheckingForClimbStateActive;
[Space]
[Header ("Turbo Events")]
[Space]
public bool useEventOnTurbo;
public UnityEvent eventOnStartTurbo;
public UnityEvent eventOnEndTurbo;
public UnityEvent eventOnRegularClimbSpeed;
[Space]
[Header ("Components")]
[Space]
public playerController mainPlayerController;
public Transform playerTransform;
public Rigidbody mainRigidbody;
public Transform playerCameraTransform;
public playerCamera mainPlayerCamera;
public playerWeaponsManager mainPlayerWeaponsManager;
public Animator mainAnimator;
public headTrack mainHeadTrack;
Coroutine resetPlayerCoroutine;
Coroutine resetCameraCoroutine;
bool originalClimbEnabled;
Vector3 playerTransformUp;
Vector3 playerTransformForward;
RaycastHit hit;
Vector3 velocityChange;
int externalControlleBehaviorActiveAnimatorID;
int actionIDAnimatorID;
int horizontalAnimatorID;
int verticalAnimatorID;
int freeClimbAnimatorID;
bool jumpInputUsed;
Coroutine jumpCoroutine;
float currentClimbRotationSpeed;
float currentClimbMovementSpeed;
float currentClimbVelocity;
float currentClimbTurboSpeed;
string previousCameraState = "";
bool cameraOnThirdPersonOnLastClimbActiveState;
float lastTimeMinAngleOnSurfaceReached;
float lastTimeMaxAngleOnSurfaceReached;
Vector3 lastSideDirection;
Vector3 lastSideNormal;
bool resetAnimatorIDValue;
float lastTimeClimbActive;
RaycastHit currentSurfaceHit;
GameObject currentSurfaceDetected;
GameObject previousSurfaceDetected;
bool checkTagsToIgnoreOnManualClimbInputActive;
int currentIDValue = -1;
bool firstPersonChecked;
bool thirdPersonChecked;
float lastTimeActivateClimbStateOnNextSurfaceDetectedActive;
Coroutine checkIfSurfaceDetectedInFrontCoroutine;
float lastTimeSurfaceNotFound = 0;
bool climbingOnTopInProcess;
float lastTimeCollisionDetectionWithSurfaceNotFound = 0;
Vector3 positionToAdjustPlayerToSurfaceCollision = Vector3.zero;
bool isPlayerMovingOn3dWorld;
bool increaseClimbSpeedActive;
void Start ()
{
originalClimbEnabled = climbEnabled;
externalControlleBehaviorActiveAnimatorID = Animator.StringToHash (externalControlleBehaviorActiveAnimatorName);
actionIDAnimatorID = Animator.StringToHash (actionIDAnimatorName);
horizontalAnimatorID = Animator.StringToHash (horizontalAnimatorName);
verticalAnimatorID = Animator.StringToHash (verticalAnimatorName);
freeClimbAnimatorID = Animator.StringToHash (freeClimbAnimatorName);
}
public override void checkChangeCameraViewStateOnExternalControllerBehavior ()
{
if (climbActive) {
isFirstPersonActive = mainPlayerController.isPlayerOnFirstPerson ();
bool isFullBodyAwarenessActive = mainPlayerCamera.isFullBodyAwarenessActive ();
if (isFullBodyAwarenessActive) {
mainPlayerCamera.setIgnorePlayerRotationToCameraOnFBAState (true);
mainPlayerCamera.setPivotCameraTransformParentCurrentTransformToFollow ();
} else {
if (isFirstPersonActive) {
} else {
if (mainPlayerCamera.isFullBodyAwarenessEnabled ()) {
mainPlayerCamera.setIgnorePlayerRotationToCameraOnFBAState (false);
mainPlayerCamera.setPivotCameraTransformOriginalParent ();
mainPlayerCamera.resetPivotCameraTransformLocalRotation ();
setCameraState (true);
}
}
}
}
}
void setCameraState (bool state)
{
if (useCameraOffsetOnClimbActiveEnabled) {
mainPlayerCamera.setCameraPositionOffsetActiveState (state, cameraOffsetOnClimbActive, cameraOffsetOnClimbActiveLerpSpeed);
mainPlayerCamera.setUpdatePlayerCameraPositionOnFixedUpdateActiveState (state);
}
if (setNewCameraStateOnThirdPerson && !isFirstPersonActive) {
if (state) {
if (previousCameraState == "") {
previousCameraState = mainPlayerCamera.getCurrentStateName ();
cameraOnThirdPersonOnLastClimbActiveState = !mainPlayerCamera.isFullBodyAwarenessActive ();
}
mainPlayerCamera.setCameraStateOnlyOnThirdPerson (newCameraStateOnThirdPerson);
} else {
if (previousCameraState != "") {
if (previousCameraState != newCameraStateOnThirdPerson) {
if (cameraOnThirdPersonOnLastClimbActiveState) {
if (mainPlayerCamera.isFullBodyAwarenessActive ()) {
previousCameraState = "";
}
} else {
if (!mainPlayerCamera.isFullBodyAwarenessActive ()) {
previousCameraState = mainPlayerCamera.getDefaultThirdPersonStateName ();
}
}
if (previousCameraState != "") {
mainPlayerCamera.setCameraStateOnlyOnThirdPerson (previousCameraState);
}
}
previousCameraState = "";
}
}
}
}
public override void updateControllerBehavior ()
{
if (climbActive) {
if (resetAnimatorIDValue) {
if (Time.time > lastTimeClimbActive + 0.3f) {
mainAnimator.SetInteger (actionIDAnimatorID, 0);
resetAnimatorIDValue = false;
}
}
if (movementInputPausedActive) {
if (Time.time > lastTimeClimbActive + minDelayToUseMovementInputOnClimbStart) {
movementInputPausedActive = false;
}
}
float currentFixedUpdateDeltaTime = Time.fixedDeltaTime;
playerTransformUp = playerTransform.up;
playerTransformForward = playerTransform.forward;
Vector3 currentRaycastPosition = playerTransform.position + playerTransformUp;
Vector3 currentRaycastDirection = playerTransformForward;
currentVerticalMovement = mainPlayerController.getVerticalInput ();
currentHorizontalMovement = mainPlayerController.getHorizontalInput ();
isPlayerMovingOn3dWorld = mainPlayerController.isPlayerMovingOn3dWorld ();
if (movementInputPausedActive || movementInputDisabledOnSurface || adjustingPlayerToSurfaceCollisionDetection) {
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
}
if (!isPlayerMovingOn3dWorld) {
currentHorizontalMovement = 0;
}
rawAxisValues = mainPlayerController.getRawAxisValues ();
if (rawAxisValues.x == 0) {
if (Mathf.Abs (currentHorizontalMovement) > 0.001f) {
currentHorizontalMovement = 0;
}
}
if (rawAxisValues.y == 0) {
if (Mathf.Abs (currentVerticalMovement) > 0.001f) {
currentVerticalMovement = 0;
}
}
if (useRaycastDetectionToClimb) {
if (!updateRaycastDetectionState (currentRaycastPosition, currentRaycastDirection, currentFixedUpdateDeltaTime)) {
return;
}
}
//##################################################################################################
//Update climb state by collision detection
else {
if (!updateCollisionDetectionState (currentRaycastDirection, currentFixedUpdateDeltaTime)) {
return;
}
}
checkSurfaceAngleToStopClimb ();
if (!surfaceFoundOnSide && !adjustingPlayerToSurfaceCollisionDetection) {
checkIfTopSurfaceReached ();
}
checkTopBottomAndFrontSurfaces ();
}
}
//COLLISION DETECTION METHOD
bool updateCollisionDetectionState (Vector3 currentRaycastDirection, float currentFixedUpdateDeltaTime)
{
updateCheckCameraViewState ();
currentClimbMovementSpeed = climbMovementSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbMovementSpeed = climbMovementSpeedFirstPerson;
}
currentClimbRotationSpeed = climbRotationSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbRotationSpeed = climbRotationSpeedFirstPerson;
}
currentClimbVelocity = climbVelocityThirdPerson;
if (isFirstPersonActive) {
currentClimbVelocity = climbVelocityFirstPerson;
}
if (slidingDownActive || activateAutoSlideDownOnSurface) {
currentClimbVelocity = slideDownSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbVelocity = SlideDownSpeedFirstPerson;
}
}
if (movementInputPausedActive || movementInputDisabledOnSurface || adjustingPlayerToSurfaceCollisionDetection) {
rawAxisValues = Vector2.zero;
}
checkCurrentSurfaceDetected ();
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (!movementInputPausedActive && !cancelMovementInputActive && surfaceDetectedOnMovementInputRaycast) {
currentVerticalMovement = -1;
rawAxisValues.y = currentVerticalMovement;
if (currentHorizontalMovement != 0) {
currentHorizontalMovement /= 2;
}
}
}
if (cancelMovementInputActive) {
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
rawAxisValues = Vector2.zero;
}
if (surfaceDetectedAbovePlayer) {
currentVerticalMovement = Mathf.Clamp (currentVerticalMovement, -1, 0);
rawAxisValues.y = Mathf.Clamp (rawAxisValues.y, -1, 0);
}
if (surfafeDetectedBelowPlayer) {
currentVerticalMovement = Mathf.Clamp (currentVerticalMovement, 0, 1);
rawAxisValues.y = Mathf.Clamp (rawAxisValues.y, 0, 1);
}
slidingDownResult = false;
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (currentVerticalMovement != 0) {
if (currentIDValue != 1) {
currentIDValue = 1;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
slidingDownResult = true;
} else {
if (currentIDValue != 0) {
currentIDValue = 0;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
}
} else {
if (currentIDValue != 0) {
currentIDValue = 0;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
}
moving = (Mathf.Abs (currentVerticalMovement) > 0.01f || Mathf.Abs (currentHorizontalMovement) > 0.01f);
movementInputPressed = rawAxisValues != Vector2.zero;
currentClimbTurboSpeed = 1;
pauseTurboActive = false;
bool enougMovementInput = (Mathf.Abs (currentVerticalMovement) > 0.7f || Mathf.Abs (currentHorizontalMovement) > 0.7f);
if (increaseClimbSpeedActive && movementInputPressed && enougMovementInput && !slidingDownActive && !activateAutoSlideDownOnSurface) {
if (surfaceDetectedOnMovementInputRaycast && angleDifferenceWithSurface < 3) {
currentClimbTurboSpeed = climbTurboSpeed;
} else {
pauseTurboActive = true;
}
if (!turboActive) {
mainPlayerController.setCurrentAirSpeedValue (2);
turboActive = true;
checkEventsOnTurbo (true);
}
} else {
if (turboActive) {
mainPlayerController.setCurrentAirSpeedValue (1);
turboActive = false;
mainPlayerController.stopShakeCamera ();
checkEventsOnTurbo (false);
eventOnRegularClimbSpeed.Invoke ();
}
}
if (adjustingPlayerToSurfaceCollisionDetection) {
//adjust player to surface before moving
if (positionToAdjustPlayerToSurfaceCollision == Vector3.zero) {
Vector3 mainRaycastPosition = playerTransform.position + playerTransform.up - playerTransform.forward * 0.3f;
if (Physics.Raycast (mainRaycastPosition, currentRaycastDirection, out hit, 2, raycastLayermask)) {
Vector3 targetPosition = hit.point + adjustToFoundSurfaceOffset * hit.normal;
float currentPlayerAngleWithSurface = Vector3.SignedAngle (playerTransform.forward, -hit.normal, playerTransform.right);
float currentPlayerAngleWithSurfaceABS = Mathf.Abs (currentPlayerAngleWithSurface);
// print (currentPlayerAngleWithSurface);
if (currentPlayerAngleWithSurfaceABS > 8) {
Vector3 playerTransformDown = -playerTransform.up;
playerTransformDown = Quaternion.AngleAxis (currentPlayerAngleWithSurface, playerTransform.right) * playerTransformDown;
playerTransformDown.Normalize ();
// print (playerTransformDown);
targetPosition += playerTransformDown;
Debug.DrawRay (hit.point + adjustToFoundSurfaceOffset * hit.normal, playerTransformDown * 10000, Color.black, 5);
// print (currentPlayerAngleWithSurface);
} else {
targetPosition -= playerTransform.up;
}
positionToAdjustPlayerToSurfaceCollision = targetPosition;
}
} else {
mainRigidbody.position =
Vector3.MoveTowards (mainRigidbody.position, positionToAdjustPlayerToSurfaceCollision,
adjustToFoundSurfaceSpeed * currentFixedUpdateDeltaTime);
bool closeToSurfaceDetected = GKC_Utils.distance (mainRigidbody.position, positionToAdjustPlayerToSurfaceCollision) < 0.01f;
if (Time.time > lastTimeClimbActive + minDelayToAdjustDetectionCollision && closeToSurfaceDetected) {
adjustingPlayerToSurfaceCollisionDetection = false;
positionToAdjustPlayerToSurfaceCollision = Vector3.zero;
Vector3 newPosition = mainRigidbody.position;
if (climbDetectionCollisionPositionOffset != Vector3.zero) {
newPosition += climbDetectionCollisionPositionOffset.x * (-playerTransform.right);
newPosition += climbDetectionCollisionPositionOffset.y * (-playerTransform.up);
newPosition += climbDetectionCollisionPositionOffset.z * (-playerTransform.forward);
}
mainClimbDetectionCollisionSystem.updateObjectPosition (newPosition);
}
}
} else {
Vector3 climbPosition = mainClimbDetectionCollisionSystem.getMainRigidbodyPosition ();
if (climbDetectionCollisionPositionOffset != Vector3.zero) {
climbPosition += climbDetectionCollisionPositionOffset.x * playerTransform.right;
climbPosition += climbDetectionCollisionPositionOffset.y * playerTransform.up;
climbPosition += climbDetectionCollisionPositionOffset.z * playerTransform.forward;
}
if (updateRigidbodyPositionSmoothlyOnDetectionCollision) {
if (useMovementCurve) {
currentClimbMovementSpeed = mainMovementCurve.Evaluate (currentClimbMovementSpeed);
}
mainRigidbody.position = Vector3.Lerp (mainRigidbody.position, climbPosition, currentClimbTurboSpeed * currentClimbMovementSpeed * currentFixedUpdateDeltaTime);
} else {
mainRigidbody.position = climbPosition;
}
}
//mainRigidbody.velocity = mainClimbDetectionCollisionSystem.getMainRigidbodyVelocity ();
//mainAnimator.velocity could be used to move it with root motion used as velocity
if (movementInputPressed) {
mainPlayerController.setCurrentVelocityValue (mainRigidbody.linearVelocity);
} else {
mainPlayerController.setCurrentVelocityValue (Vector3.zero);
}
float currentHorizontalMovementAnimatorValue = currentHorizontalMovement;
float currentVerticalMovementAnimatorValue = currentVerticalMovement;
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (slidingDownResult) {
currentVerticalMovementAnimatorValue = 0;
}
}
//update player animation states
mainAnimator.SetFloat (horizontalAnimatorID, currentHorizontalMovementAnimatorValue, inputLerpSpeed, currentFixedUpdateDeltaTime);
mainAnimator.SetFloat (verticalAnimatorID, currentVerticalMovementAnimatorValue, inputLerpSpeed, currentFixedUpdateDeltaTime);
RaycastHit currentClimbCollisionHit = new RaycastHit ();
Vector3 collisionDetectionDirection = -mainClimbDetectionCollisionSystem.getLastClimbNormal ();
if (lastClimbNormalValue != -Vector3.one) {
if (!moving) {
collisionDetectionDirection = lastClimbNormalValue;
}
}
if (moving) {
lastClimbNormalValue = -mainClimbDetectionCollisionSystem.getLastClimbNormal ();
}
if (Physics.Raycast (mainClimbDetectionCollisionSystem.getMainRigidbodyPosition (), collisionDetectionDirection, out currentClimbCollisionHit, 3, raycastLayermask)) {
collisionDetectionDirection = -currentClimbCollisionHit.normal;
} else {
collisionDetectionDirection = playerTransform.forward;
if (Physics.Raycast (mainClimbDetectionCollisionSystem.getMainRigidbodyPosition (), collisionDetectionDirection, out currentClimbCollisionHit, 3, raycastLayermask)) {
collisionDetectionDirection = -currentClimbCollisionHit.normal;
}
}
bool setRotationOnPlayerResult = true;
angleDifferenceWithSurface = Vector3.Angle (playerTransform.forward, collisionDetectionDirection);
if (angleDifferenceWithSurface < 3) {
if (!moving) {
currentClimbRotationSpeed *= 0.8f;
}
}
if (angleDifferenceWithSurface < 1) {
setRotationOnPlayerResult = false;
}
if (setRotationOnPlayerResult) {
Quaternion targetRotation = Quaternion.LookRotation (collisionDetectionDirection);
playerTransform.rotation = Quaternion.Lerp (playerTransform.rotation, targetRotation, currentClimbRotationSpeed * currentFixedUpdateDeltaTime);
}
if (rotateCameraToPlayerRotationOnClimbActiveEnabled) {
Vector3 myForwardCamera = Vector3.Cross (playerCameraTransform.right, playerTransform.up);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, playerTransform.up);
playerCameraTransform.rotation = Quaternion.Lerp (playerCameraTransform.rotation, dstRotCamera, currentClimbRotationSpeed * currentFixedUpdateDeltaTime);
}
if (Time.time > lastTimeClimbActive + 0.5f && !adjustingPlayerToSurfaceCollisionDetection) {
if (climbContactCount > 0) {
lastTimeCollisionDetectionWithSurfaceNotFound = 0;
// print ("DETECTED " + climbContactCount);
} else {
// print ("NO DETECTED " + climbContactCount);
if (lastTimeCollisionDetectionWithSurfaceNotFound == 0) {
lastTimeCollisionDetectionWithSurfaceNotFound = Time.time;
} else {
if (lastTimeCollisionDetectionWithSurfaceNotFound != 0 && Time.time > lastTimeCollisionDetectionWithSurfaceNotFound + 1.2f) {
Vector3 lastContactNormal = contactNormal;
if (lastContactNormal == Vector3.zero) {
lastContactNormal = mainClimbDetectionCollisionSystem.getLastClimbNormal ();
}
if (lastContactNormal == Vector3.zero) {
lastContactNormal = Vector3.up;
}
Vector3 currentNormal = getCurrentNormal ();
float topSurfaceAngle = Vector3.Angle (currentNormal, lastContactNormal);
float topSurfaceAngleABS = Mathf.Abs (topSurfaceAngle);
if (showDebugPrint) {
print ("stop climb due to collision dropped, checking surface on top" + topSurfaceAngleABS + " " + lastContactNormal);
}
bool groundLocated = false;
if (topSurfaceAngleABS < 20) {
if (topSurfaceAngleABS > 10) {
groundLocated = true;
}
}
if (!groundLocated) {
if (Physics.Raycast (mainClimbDetectionCollisionSystem.getMainRigidbodyPosition (), -getCurrentNormal (), out currentClimbCollisionHit, 1, raycastLayermask)) {
groundLocated = true;
if (showDebugPrint) {
print ("ground detected");
}
}
}
if (groundLocated) {
stopClimbToWalkOnSurfaceActive = true;
mainAnimator.CrossFadeInFixedTime (stopClimbToWalkOnSurfaceActionName, 0.1f);
}
lastTimeSurfaceNotFound = 0;
stopClimbAndDetectState ();
return false;
}
}
}
}
return true;
}
Vector3 lastClimbNormalValue = -Vector3.one;
public void updateClimbContactCount (int newValue)
{
climbContactCount = newValue;
}
public void updateContactNormal (Vector3 newValue)
{
contactNormal = newValue;
}
public void updateLastClimbNormal (Vector3 newValue)
{
lastClimbNormal = newValue;
}
void updateCheckCameraViewState ()
{
//check change of view state
bool isPlayerOnFirstPerson = mainPlayerController.isPlayerOnFirstPerson ();
if (isPlayerOnFirstPerson) {
if (!firstPersonChecked) {
if (showDebugPrint) {
print ("checking swim state on first person");
}
if (thirdPersonChecked) {
// mainPlayerController.resetAnimator ();
if (showDebugPrint) {
print ("reset animator state for first person");
}
}
firstPersonChecked = true;
thirdPersonChecked = false;
mainPlayerController.setPausePlayerRotateToCameraDirectionOnFirstPersonActiveState (true);
}
} else {
if (!thirdPersonChecked) {
if (showDebugPrint) {
print ("checking swim state on third person");
}
if (firstPersonChecked) {
// mainPlayerController.resetAnimator ();
if (showDebugPrint) {
print ("reset animator state for first person");
}
mainPlayerController.setOnGroundState (false);
mainPlayerController.setOnGroundAnimatorIDValueWithoutCheck (false);
mainPlayerController.setFootStepManagerState (true);
mainAnimator.Play (freeClimbAnimatorID);
// mainAnimator.SetInteger (actionIDAnimatorID, actionID);
mainAnimator.SetBool (externalControlleBehaviorActiveAnimatorID, true);
lastTimeClimbActive = Time.time;
resetAnimatorIDValue = true;
}
thirdPersonChecked = true;
firstPersonChecked = false;
mainPlayerController.setPausePlayerRotateToCameraDirectionOnFirstPersonActiveState (false);
}
}
}
void checkSurfaceAngleToStopClimb ()
{
if (useRaycastDetectionToClimb) {
//check surface angle to stop the climb
surfaceAngle = 0;
Vector3 currentRaycastPosition = playerTransform.position + playerTransform.up;
Vector3 currentRaycastDirection = playerTransform.forward;
if (Physics.Raycast (currentRaycastPosition, currentRaycastDirection, raycastDistance, raycastLayermask)) {
surfaceAngle = Vector3.SignedAngle (playerTransform.up, getCurrentNormal (), playerTransform.right);
}
if (surfaceAngle != 0 && !surfaceFoundOnSide && !surfaceFoundOnCloseSide) {
if (stopClimbAtMinAngleOnSurface) {
if (surfaceAngle < 0) {
if (surfaceAngle < minAngleToStopClimb) {
if (lastTimeMinAngleOnSurfaceReached == 0) {
lastTimeMinAngleOnSurfaceReached = Time.time;
}
} else {
lastTimeMinAngleOnSurfaceReached = 0;
}
}
}
if (stopClimbAtMaxAngleOnSurface) {
if (surfaceAngle > 0) {
if (surfaceAngle > maxAngleToStopClimb) {
if (lastTimeMaxAngleOnSurfaceReached == 0) {
lastTimeMaxAngleOnSurfaceReached = Time.time;
}
} else {
lastTimeMaxAngleOnSurfaceReached = 0;
}
}
}
if (lastTimeMinAngleOnSurfaceReached != 0) {
if (Time.time > lastTimeMinAngleOnSurfaceReached + minTimeAngleLimitReachedToStopClimb) {
stopClimbAndDetectState ();
return;
}
}
if (lastTimeMaxAngleOnSurfaceReached != 0) {
if (Time.time > lastTimeMaxAngleOnSurfaceReached + minTimeAngleLimitReachedToStopClimb) {
stopClimbAndDetectState ();
return;
}
}
}
} else {
}
}
public bool isSlidingDownActive ()
{
return slidingDownActive;
}
public bool isPlayerMoving ()
{
return moving;
}
public float getCurrentClimbTurboSpeed ()
{
return currentClimbTurboSpeed;
}
public bool isTurboActive ()
{
return turboActive;
}
public bool isPauseTurboActive ()
{
return pauseTurboActive;
}
public Vector3 getCurrentNormal ()
{
return mainPlayerController.getCurrentNormal ();
}
void checkTopBottomAndFrontSurfaces ()
{
if (useRaycastDetectionToClimb) {
if (checkSurfaceForLowerBodyEnabled) {
Vector3 raycastPosition = playerTransform.position + (lowerBodyRaycastOffset * playerTransform.up);
Vector3 raycastDirection = playerTransform.forward;
if (useHangStateOnNoSurfaceOnLowerBody) {
if (Physics.Raycast (raycastPosition, raycastDirection, 1.1f, raycastLayermask)) {
if (!lowerBodySurfaceDetected) {
mainPlayerController.setCurrentAirIDValue (-1);
lowerBodySurfaceDetected = true;
}
if (showGizmo) {
Debug.DrawRay (raycastPosition, 2 * raycastDirection, Color.green);
}
} else {
if (lowerBodySurfaceDetected) {
mainPlayerController.setCurrentAirIDValue (0);
lowerBodySurfaceDetected = false;
}
if (showGizmo) {
Debug.DrawRay (raycastPosition, 2 * raycastDirection, Color.black);
}
}
} else {
if (!lowerBodySurfaceDetected) {
mainPlayerController.setCurrentAirIDValue (-1);
lowerBodySurfaceDetected = true;
}
}
raycastPosition = playerTransform.position + (upperBodyRaycastOffset * playerTransform.up);
raycastDirection = playerTransform.forward;
upperBodySurfaceDetected = false;
if (Physics.Raycast (raycastPosition, raycastDirection, 1.1f, raycastLayermask)) {
upperBodySurfaceDetected = true;
if (showGizmo) {
Debug.DrawRay (raycastPosition, 2 * raycastDirection, Color.green);
}
} else {
if (showGizmo) {
Debug.DrawRay (raycastPosition, 2 * raycastDirection, Color.black);
}
}
}
if (checkSurfaceAbovePlayerEnabled) {
Vector3 raycastPosition = playerTransform.position + (abovePlayerRaycastOffset * playerTransform.up);
Vector3 raycastDirection = playerTransform.up;
RaycastHit abovePlayerHit;
if (Physics.Raycast (raycastPosition, raycastDirection, out abovePlayerHit, 0.9f, raycastLayermask)) {
float currentAngle = Vector3.SignedAngle (abovePlayerHit.normal, -playerTransform.up, playerTransform.right);
if (Mathf.Abs (currentAngle) < 25) {
surfaceDetectedAbovePlayer = true;
} else {
surfaceDetectedAbovePlayer = false;
}
} else {
surfaceDetectedAbovePlayer = false;
}
}
if (checkSurfaceBelowPlayerEnabled) {
Vector3 raycastPosition = playerTransform.position + (belowPlayerRaycastOffset * playerTransform.up);
Vector3 raycastDirection = -playerTransform.up;
RaycastHit belowPlayerHit;
if (Physics.Raycast (raycastPosition, raycastDirection, out belowPlayerHit, 0.9f, raycastLayermask)) {
float currentAngle = Vector3.SignedAngle (belowPlayerHit.normal, playerTransform.up, playerTransform.right);
if (Mathf.Abs (currentAngle) < 25) {
surfafeDetectedBelowPlayer = true;
} else {
surfafeDetectedBelowPlayer = false;
}
} else {
surfafeDetectedBelowPlayer = false;
}
}
}
}
void checkIfTopSurfaceReached ()
{
Vector3 currentNormal = getCurrentNormal ();
Vector3 raycastPosition = playerTransform.position + (checkTopSurfaceRaycastOffset * playerTransform.up);
Vector3 playerForwardDirection = playerTransform.forward;
float currentPlayerAngleWithSurface = Vector3.SignedAngle (playerTransform.up, getCurrentNormal (), playerTransform.right);
float currentPlayerAngleWithSurfaceABS = Mathf.Abs (currentPlayerAngleWithSurface);
if (currentPlayerAngleWithSurfaceABS > 5) {
playerForwardDirection = Quaternion.AngleAxis (currentPlayerAngleWithSurface, playerTransform.right) * playerForwardDirection;
Debug.DrawRay (raycastPosition, playerForwardDirection * 1000, Color.red);
// print (currentPlayerAngleWithSurface);
}
Vector3 raycastDirection = playerForwardDirection;
// print (raycastDirection);
Vector3 climbSurfaceTargetPosition = Vector3.zero;
RaycastHit upperHit = new RaycastHit ();
RaycastHit lowerHit = new RaycastHit ();
bool surfaceToLedgeDetected = false;
Debug.DrawRay (raycastPosition, raycastDirection, Color.green);
if (!Physics.Raycast (raycastPosition, raycastDirection, out upperHit, 2, raycastLayermask) &&
Physics.Raycast (playerTransform.position, raycastDirection, out lowerHit, 2, raycastLayermask)) {
//if not surface is found, then
if (showGizmo) {
Debug.DrawRay (raycastPosition, raycastDirection, Color.green);
}
//search for the closest point surface of that ledge, by lowering the raycast position until a surface is found
surfaceToLedgeDetected = false;
RaycastHit newHit = new RaycastHit ();
RaycastHit previousHit = new RaycastHit ();
int numberOfLoops = 0;
Vector3 newRaycastPosition = playerTransform.position + (0.5f * playerTransform.up) - 0.6f * playerTransform.forward;
// raycastDirection = Vector3.Cross (playerTransform.right, currentNormal);
RaycastHit topSurfaceHit = new RaycastHit ();
float topSurfaceAngle = -1;
float currentRaycastDistance = 2.6f;
if (currentPlayerAngleWithSurface < -8) {
//print ("looking down");
currentRaycastDistance = 2;
}
raycastDirection = playerTransform.forward;
while (!surfaceToLedgeDetected && numberOfLoops < 80) {
if (Physics.Raycast (newRaycastPosition, raycastDirection, out newHit, currentRaycastDistance, raycastLayermask)) {
previousHit = newHit;
newRaycastPosition += 0.04f * playerTransform.up;
if (currentPlayerAngleWithSurface < -8) {
if (currentRaycastDistance > 1.5f) {
currentRaycastDistance -= 0.05f;
}
} else {
if (currentRaycastDistance > 2) {
if (newHit.distance > 2) {
currentRaycastDistance -= 0.06f;
}
}
}
} else {
if (previousHit.point == Vector3.zero) {
print ("NO LOCATED");
} else {
climbSurfaceTargetPosition = previousHit.point + 0.04f * playerTransform.up;
surfaceToLedgeDetected = true;
if (Physics.Raycast (climbSurfaceTargetPosition + 0.2f * currentNormal, raycastDirection - playerTransform.up, out topSurfaceHit, 3.3f, raycastLayermask)) {
topSurfaceAngle = Vector3.Angle (currentNormal, topSurfaceHit.normal);
}
}
}
numberOfLoops++;
}
if (surfaceToLedgeDetected) {
float angleWithSurface = Vector3.SignedAngle (currentNormal, previousHit.normal, playerTransform.right);
bool surfaceAngleNotValid = false;
float angleWithSurfaceAux = Mathf.Abs (Mathf.Abs (angleWithSurface) - 90);
// if (showDebugPrint) {
// print ("angle with surface " + angleWithSurface + " " + angleWithSurfaceAux);
// }
if (angleWithSurfaceAux > maxAngleDifferenceOnSurfaceToClimb) {
surfaceAngleNotValid = true;
}
if (topSurfaceAngle != -1) {
// print ("top surface angle " + topSurfaceAngle);
if (Mathf.Abs (topSurfaceAngle) > maxAngleDifferenceOnSurfaceToClimb) {
surfaceAngleNotValid = true;
}
}
if (!useRaycastDetectionToClimb) {
if (showDebugPrint) {
print ("surface valid to climb on top " + topSurfaceAngle + " " + angleWithSurface + " " + previousHit.normal);
}
if (topSurfaceAngle != -1) {
float topSurfaceAngleABS = Mathf.Abs (topSurfaceAngle);
if (showDebugPrint) {
print ("Top surface angle is " + topSurfaceAngle);
}
bool stopClimbToWalkNormallyResult = false;
if (topSurfaceAngleABS > 30) {
surfaceAngleNotValid = true;
} else if (topSurfaceAngleABS < 20 && topSurfaceAngleABS > 10) {
stopClimbToWalkNormallyResult = true;
}
if (currentPlayerAngleWithSurfaceABS < 30) {
if (showDebugPrint) {
print ("checking if climb on top on low player rotation");
}
if (climbSurfaceTargetPosition != Vector3.zero) {
if (showDebugPrint) {
print ("surface to climb target position by raycast located");
}
if (Mathf.Abs (topSurfaceAngle) <= maxAngleDifferenceOnSurfaceToClimb) {
if (showDebugPrint) {
print ("climb on top on low rotation checked properly, activating");
}
stopClimbToWalkNormallyResult = false;
surfaceAngleNotValid = false;
}
}
}
if (stopClimbToWalkNormallyResult) {
if (showDebugPrint) {
print ("stop climb to walk normally");
}
stopClimbToWalkOnSurfaceActive = true;
mainAnimator.CrossFadeInFixedTime (stopClimbToWalkOnSurfaceActionName, 0.1f);
lastTimeSurfaceNotFound = 0;
stopClimbAndDetectState ();
surfaceAngleNotValid = true;
}
} else {
surfaceAngleNotValid = true;
}
}
if (climbSurfaceTargetPosition == Vector3.zero) {
surfaceAngleNotValid = true;
}
if (!surfaceAngleNotValid) {
if (showGizmo) {
Debug.DrawRay (newRaycastPosition, 4 * raycastDirection, Color.blue, 4);
}
isFirstPersonActive = mainPlayerController.isPlayerOnFirstPerson ();
Transform climbSurfaceActionSystemTransformParent = null;
if (mainPlayerController.isPlayerSetAsChildOfParent ()) {
climbSurfaceActionSystemTransformParent = mainPlayerController.getCurrentTemporalPlayerParent ();
}
climbSurfaceActionSystemTransform.SetParent (climbSurfaceActionSystemTransformParent);
actionSystem climbactionSystem = climbSurfaceActionSystemTransform.GetComponent<actionSystem> ();
if (climbactionSystem != null) {
climbactionSystem.setPlayerParentDuringActionActiveValues (climbSurfaceActionSystemTransformParent != null,
climbSurfaceActionSystemTransformParent);
if (isFirstPersonActive) {
climbactionSystem.setUseMovingPlayerToPositionTargetValues (true, climbSurfaceTopSpeed, 0);
} else {
// if (climbSurfaceActionSystemTransformParent != null) {
// climbactionSystem.setUseMovingPlayerToPositionTargetValues (true, climbSurfaceTopSpeed, 1);
// } else {
climbactionSystem.setUseMovingPlayerToPositionTargetValues (false, 0, 0);
// }
}
}
climbingOnTopInProcess = true;
stopClimbAndDetectState ();
climbSurfaceActionSystemTransform.position = climbSurfaceTargetPosition;
Quaternion targetRotation = Quaternion.LookRotation (-previousHit.normal);
climbSurfaceActionSystemTransform.rotation = targetRotation;
float extraAngleX = 0;
if (climbSurfaceActionSystemTransform.up != currentNormal) {
extraAngleX = Vector3.SignedAngle (climbSurfaceActionSystemTransform.up, currentNormal, climbSurfaceActionSystemTransform.right);
}
if (extraAngleX != 0) {
climbSurfaceActionSystemTransform.Rotate (new Vector3 (extraAngleX, 0, 0));
}
float extraAngleY = Vector3.SignedAngle (climbSurfaceActionSystemTransform.forward, playerForwardDirection, climbSurfaceActionSystemTransform.up);
if (Mathf.Abs (extraAngleY) > 5) {
climbSurfaceActionSystemTransform.Rotate (new Vector3 (0, extraAngleY, 0));
}
climbSurfaceActionSystemTransform.gameObject.SetActive (true);
eventToActivateClimbSurfaceActionSystem.Invoke (playerTransform.gameObject);
if (showDebugPrint) {
print ("surface to climb detected");
}
}
} else {
if (showDebugPrint) {
print ("surface to climb not detected");
}
}
} else {
if (!useRaycastDetectionToClimb) {
Vector3 lastContactNormal = contactNormal;
if (climbContactCount > 0) {
lastContactNormal = mainClimbDetectionCollisionSystem.getLastClimbNormal ();
}
float topSurfaceAngle = Vector3.Angle (currentNormal, lastContactNormal);
float topSurfaceAngleABS = Mathf.Abs (topSurfaceAngle);
if (topSurfaceAngleABS < 20) {
if (topSurfaceAngleABS > 10) {
if (showDebugPrint) {
print ("surface valid to climb on top by stopping climb" + topSurfaceAngleABS + " " + lastContactNormal);
}
stopClimbToWalkOnSurfaceActive = true;
mainAnimator.CrossFadeInFixedTime (stopClimbToWalkOnSurfaceActionName, 0.1f);
lastTimeSurfaceNotFound = 0;
stopClimbAndDetectState ();
print ("stop climb to walk normally");
}
}
}
}
}
public string stopClimbToWalkOnSurfaceActionName = "Stop Climb To Walk On Surface";
bool stopClimbToWalkOnSurfaceActive;
public override void setExtraImpulseForce (Vector3 forceAmount, bool useCameraDirection)
{
setClimbImpulseForce (forceAmount, useCameraDirection);
}
public void setClimbImpulseForce (Vector3 forceAmount, bool useCameraDirection)
{
Vector3 impulseForce = forceAmount;
if (maxVelocityChangeSlide > 0) {
velocityChange = impulseForce - mainRigidbody.linearVelocity;
velocityChange = Vector3.ClampMagnitude (velocityChange, maxVelocityChangeSlide);
} else {
velocityChange = impulseForce;
}
mainPlayerController.setVelocityChangeValue (velocityChange);
mainRigidbody.AddForce (velocityChange, ForceMode.VelocityChange);
}
void checkCurrentSurfaceDetected ()
{
if (!useClimbZoneDetectionRaycast) {
return;
}
Vector3 currentRaycastPosition = playerTransform.position + playerTransform.up - (0.3f * playerTransform.forward);
Vector3 currentRaycastDirection = playerTransform.forward;
Vector2 movementInput = rawAxisValues;
if (slidingDownResult) {
movementInput.y = -1;
}
if (movementInput.x > 0) {
currentRaycastPosition += movementInput.x * rightOffsetToDetectSurfaceOnMovementInput * playerTransform.right;
} else if (movementInput.x < 0) {
currentRaycastPosition += movementInput.x * leftOffsetToDetectSurfaceOnMovementInput * playerTransform.right;
}
if (movementInput.y > 0) {
currentRaycastPosition += movementInput.y * upOffsetToDetectSurfaceOnMovementInput * playerTransform.up;
} else if (movementInput.y < 0) {
currentRaycastPosition += movementInput.y * downOffsetToDetectSurfaceOnMovementInput * playerTransform.up;
}
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, 2 * currentRaycastDirection, Color.white);
}
if (Physics.Raycast (currentRaycastPosition, currentRaycastDirection, out currentSurfaceHit, raycastDistance + 0.3f, raycastLayermask)) {
currentSurfaceDetected = currentSurfaceHit.collider.gameObject;
surfaceDetectedOnMovementInputRaycast = true;
if (currentSurfaceDetected != previousSurfaceDetected) {
previousSurfaceDetected = currentSurfaceDetected;
if (avoidMovementTowardNoClimbZones) {
freeClimbZoneSystem currentFreeClimbZoneSystem = currentSurfaceDetected.GetComponent<freeClimbZoneSystem> ();
if (currentFreeClimbZoneSystem != null) {
cancelMovementInputActive = false;
} else {
cancelMovementInputActive = true;
}
}
if (avoidMovementTowardSurfacesToIgnore) {
if (surfacesToIgnoreTagsList.Contains (currentSurfaceDetected.tag)) {
if (stopClimbIfSurfaceToIgnoreDetected) {
stopClimbAndDetectState ();
} else {
cancelMovementInputActive = true;
}
} else {
cancelMovementInputActive = false;
}
}
}
} else {
if (currentSurfaceDetected != null) {
currentSurfaceDetected = null;
previousSurfaceDetected = null;
cancelMovementInputActive = false;
}
surfaceDetectedOnMovementInputRaycast = false;
}
if (avoidMovementTowardSurfacesToIgnore) {
if (!cancelMovementInputActive) {
currentRaycastPosition = playerTransform.position + playerTransform.up - (0.3f * playerTransform.forward);
movementInput = rawAxisValues;
if (slidingDownResult) {
movementInput.y = -1;
}
if (movementInput.x > 0) {
currentRaycastDirection = movementInput.x * playerTransform.right;
} else if (movementInput.x < 0) {
currentRaycastPosition = movementInput.x * playerTransform.right;
}
if (movementInput.y > 0) {
currentRaycastPosition = movementInput.y * playerTransform.up;
} else if (movementInput.y < 0) {
currentRaycastPosition = movementInput.y * playerTransform.up;
}
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, 2 * currentRaycastDirection, Color.white);
}
if (Physics.Raycast (currentRaycastPosition, currentRaycastDirection, out currentSurfaceHit, raycastDistance + 0.3f, raycastLayermask)) {
currentSurfaceDetected = currentSurfaceHit.collider.gameObject;
surfaceDetectedOnMovementInputRaycast = true;
if (currentSurfaceDetected != previousSurfaceDetected) {
previousSurfaceDetected = currentSurfaceDetected;
if (avoidMovementTowardNoClimbZones) {
freeClimbZoneSystem currentFreeClimbZoneSystem = currentSurfaceDetected.GetComponent<freeClimbZoneSystem> ();
if (currentFreeClimbZoneSystem == null) {
cancelMovementInputActive = true;
}
}
if (surfacesToIgnoreTagsList.Contains (currentSurfaceDetected.tag)) {
if (stopClimbIfSurfaceToIgnoreDetected) {
stopClimbAndDetectState ();
} else {
cancelMovementInputActive = true;
}
}
}
}
}
}
}
public void stopClimbFromDamageReceived ()
{
if (!disableClimbStateOnDamageReceivedEnabled) {
return;
}
if (!climbActive) {
return;
}
stopClimbAndDetectState ();
}
void stopClimbAndDetectState ()
{
setClimbActiveState (false);
if (climbStateActivatedByInput) {
setCheckIfDetectClimbActiveState (false);
}
}
//Traversal movement functions
public override void setJumpActiveForExternalForce ()
{
setJumpActive (impulseOnJump);
}
public void setJumpActive (Vector3 newImpulseOnJumpAmount)
{
if (climbActive) {
if (adjustingPlayerToSurfaceCollisionDetection) {
return;
}
jumpInputUsed = true;
setClimbActiveState (false);
Vector3 totalForce = newImpulseOnJumpAmount.y * playerTransform.up + newImpulseOnJumpAmount.z * playerTransform.forward;
mainPlayerController.useJumpPlatform (totalForce, ForceMode.Impulse);
if (climbStateActivatedByInput) {
setCheckIfDetectClimbActiveState (false);
}
rotateCharacterOnJump ();
if (rotateCameraToPlayerRotationOnClimbActiveEnabled) {
resetCameraRotation ();
}
}
}
public override void setExternalForceActiveState (bool state)
{
setClimbActiveState (state);
}
public void setMovementInputDisabledOnSurfaceState (bool state)
{
movementInputDisabledOnSurface = state;
}
public void setCheckIfDetectClimbActiveState (bool state)
{
if (!climbEnabled) {
return;
}
if (!climbCheckCanBeUsed) {
return;
}
if (checkIfDetectClimbActive == state) {
return;
}
if (mainPlayerController.isUseExternalControllerBehaviorPaused ()) {
return;
}
if (state) {
externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
if (currentExternalControllerBehavior != null && currentExternalControllerBehavior != this) {
if (canBeActivatedIfOthersBehaviorsActive && checkIfCanEnableBehavior (currentExternalControllerBehavior.behaviorName)) {
currentExternalControllerBehavior.disableExternalControllerState ();
} else {
return;
}
}
eventBeforeCheckingForClimbStateActive.Invoke ();
}
bool checkIfDetectClimbActivePrevioulsy = checkIfDetectClimbActive;
checkIfDetectClimbActive = state;
if (checkIfDetectClimbActive) {
// externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
//
// if (currentExternalControllerBehavior != null && currentExternalControllerBehavior != this) {
// currentExternalControllerBehavior.disableExternalControllerState ();
// }
//
mainPlayerController.setExternalControllerBehavior (this);
} else {
if (checkIfDetectClimbActivePrevioulsy) {
externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
if (currentExternalControllerBehavior == null || currentExternalControllerBehavior == this) {
mainPlayerController.setExternalControllerBehavior (null);
}
}
}
mainPlayerController.setFallDamageCheckPausedState (state);
if (!checkIfDetectClimbActive) {
setClimbActiveState (false);
}
if (checkIfDetectClimbActive) {
eventOnCheckForClimbStateActive.Invoke ();
} else {
eventOnStopCheckForClimbStateActive.Invoke ();
}
if (!checkIfDetectClimbActive) {
climbStateActivatedByInput = false;
}
// if (checkIfDetectClimbActive) {
// if (activateClimbStateOnEnterTriggerClimbZone) {
// if (!ignoreActivateClimbStateOnEnterTriggerClimbZone) {
// setClimbActiveState (true);
//
// climbStateActivatedByInput = true;
// }
//
// activateClimbStateOnEnterTriggerClimbZone = false;
// }
// }
}
public void setClimbActiveState (bool state)
{
if (!climbEnabled) {
return;
}
if (climbActive == state) {
return;
}
if (state && climbPaused) {
return;
}
climbActive = state;
mainPlayerController.setAddExtraRotationPausedState (state);
mainPlayerController.setExternalControlBehaviorForAirTypeActiveState (state);
mainPlayerController.setFreeClimbActiveState (state);
setBehaviorCurrentlyActiveState (state);
setCurrentPlayerActionSystemCustomActionCategoryID ();
bool playerOnGround = mainPlayerController.isPlayerOnGround ();
if (state) {
mainPlayerController.setCheckOnGroungPausedState (true);
mainPlayerController.setPlayerOnGroundState (false);
mainPlayerController.setPlayerOnGroundAnimatorStateOnOverrideOnGroundWithTime (false);
mainPlayerController.overrideOnGroundAnimatorValue (0);
mainPlayerController.setPlayerOnGroundAnimatorStateOnOverrideOnGround (false);
mainPlayerController.setOnGroundAnimatorIDValue (false);
mainPlayerController.setPlayerVelocityToZero ();
} else {
mainPlayerController.setCheckOnGroungPausedState (false);
mainPlayerController.setPlayerOnGroundState (false);
mainPlayerController.setPlayerOnGroundAnimatorStateOnOverrideOnGroundWithTime (true);
mainPlayerController.disableOverrideOnGroundAnimatorValue ();
mainPlayerController.setPauseResetAnimatorStateFOrGroundAnimatorState (true);
if (jumpInputUsed) {
mainPlayerController.setOnGroundAnimatorIDValue (false);
} else {
if (mainPlayerController.getCurrentSurfaceBelowPlayer () != null || stopClimbToWalkOnSurfaceActive) {
mainPlayerController.setPlayerOnGroundState (true);
mainPlayerController.setOnGroundAnimatorIDValue (true);
}
}
stopClimbToWalkOnSurfaceActive = false;
}
mainPlayerController.setFootStepManagerState (state);
if (showDebugPrint) {
print ("Climb active state " + state);
}
isFirstPersonActive = mainPlayerController.isPlayerOnFirstPerson ();
if (climbActive) {
checkEventsOnStateChange (true);
if (!isFirstPersonActive) {
bool playMainAction = true;
if (checkIfClimbHangOnAirForAction) {
if (!playerOnGround) {
mainAnimator.SetInteger (actionIDAnimatorID, freeClimbHangFromAirActionID);
playMainAction = false;
}
}
if (checkIfClimbHangOnGroundForAction) {
if (playerOnGround) {
mainAnimator.SetInteger (actionIDAnimatorID, freeClimbHangFromGroundActionID);
playMainAction = false;
}
}
if (playMainAction) {
mainAnimator.SetInteger (actionIDAnimatorID, actionID);
}
}
mainAnimator.SetBool (externalControlleBehaviorActiveAnimatorID, state);
mainPlayerController.setJumpsAmountValue (0);
// mainPlayerCamera.enableOrDisableChangeCameraView (false);
if (!isFirstPersonActive) {
if (keepWeapons) {
carryingWeaponsPreviously = mainPlayerWeaponsManager.isPlayerCarringWeapon ();
if (carryingWeaponsPreviously) {
mainPlayerWeaponsManager.checkIfDisableCurrentWeapon ();
}
mainPlayerWeaponsManager.setGeneralWeaponsInputActiveState (false);
}
}
} else {
checkEventsOnStateChange (false);
if (!isFirstPersonActive) {
mainAnimator.SetBool (externalControlleBehaviorActiveAnimatorID, state);
mainAnimator.SetInteger (actionIDAnimatorID, 0);
}
// mainPlayerCamera.setOriginalchangeCameraViewEnabledValue ();
if (keepWeapons) {
mainPlayerWeaponsManager.setGeneralWeaponsInputActiveState (true);
}
if (carryingWeaponsPreviously) {
if (!drawWeaponsIfCarriedPreviously) {
carryingWeaponsPreviously = false;
}
}
}
if (mainHeadTrack != null) {
mainHeadTrack.setHeadTrackSmoothPauseState (climbActive);
}
// mainPlayerCamera.setPausePlayerCameraViewChangeState (climbActive);
mainPlayerController.setLastTimeFalling ();
mainPlayerCamera.stopShakeCamera ();
mainPlayerController.setPauseCameraShakeFromGravityActiveState (state);
if (!climbActive) {
if (!jumpInputUsed) {
if (playerTransform.up != getCurrentNormal ()) {
if (!climbingOnTopInProcess || isFirstPersonActive) {
resetPlayerRotation ();
}
if (rotateCameraToPlayerRotationOnClimbActiveEnabled) {
resetCameraRotation ();
}
}
}
}
climbingOnTopInProcess = false;
setCameraState (state);
jumpInputUsed = false;
surfaceFoundOnSide = false;
surfaceFoundOnCloseSide = false;
lastClimbNormalValue = -Vector3.one;
if (state) {
eventOnClimbStateActive.Invoke ();
} else {
eventOnStopClimbStateActive.Invoke ();
}
if (state) {
eventOnRegularClimbSpeed.Invoke ();
} else {
if (turboActive || increaseClimbSpeedActive) {
mainPlayerController.setCurrentAirSpeedValue (1);
turboActive = false;
increaseClimbSpeedActive = false;
}
mainPlayerController.setOriginalAirIDValue ();
}
lowerBodySurfaceDetected = false;
upperBodySurfaceDetected = false;
surfaceDetectedAbovePlayer = false;
surfafeDetectedBelowPlayer = false;
lastTimeClimbActive = Time.time;
resetAnimatorIDValue = state;
if (activateClimbStateOnNextSurfaceDetectedActive) {
setActivateClimbStateOnNextSurfaceDetectedActiveState (false);
}
if (state) {
movementInputPausedActive = true;
positionToAdjustPlayerToSurfaceCollision = Vector3.zero;
if (!useRaycastDetectionToClimb) {
adjustingPlayerToSurfaceCollisionDetection = true;
}
lastTimeCollisionDetectionWithSurfaceNotFound = 0;
RaycastHit temporalHit;
if (Physics.Raycast (playerTransform.position + playerTransform.up, playerTransform.forward, out temporalHit, raycastDistance, raycastLayermask)) {
freeClimbZoneSystem currentFreeClimbZoneSystem = temporalHit.collider.GetComponent<freeClimbZoneSystem> ();
if (currentFreeClimbZoneSystem != null) {
Transform newParent = currentFreeClimbZoneSystem.checkPlayerParentState ();
if (newParent != null) {
mainPlayerController.setPlayerAndCameraParent (newParent);
if (!useRaycastDetectionToClimb) {
mainClimbDetectionCollisionSystem.setNewParent (newParent);
}
playerParentAssigned = true;
}
}
}
} else {
if (playerParentAssigned) {
mainPlayerController.setPlayerAndCameraParent (null);
mainClimbDetectionCollisionSystem.setNewParent (null);
}
playerParentAssigned = false;
movementInputDisabledOnSurface = false;
adjustingPlayerToSurfaceCollisionDetection = false;
}
if (slidingDownActive || activateAutoSlideDownOnSurface) {
slidingDownActive = false;
activateAutoSlideDownOnSurface = false;
currentIDValue = -1;
mainPlayerController.setCurrentIdleIDValue (0);
mainPlayerController.updateIdleIDOnAnimator ();
}
if (state) {
firstPersonChecked = isFirstPersonActive;
thirdPersonChecked = !isFirstPersonActive;
} else {
firstPersonChecked = false;
thirdPersonChecked = false;
}
mainPlayerController.setPausePlayerRotateToCameraDirectionOnFirstPersonActiveState (firstPersonChecked);
if (!useRaycastDetectionToClimb) {
mainClimbDetectionCollisionSystem.enableOrDisableClimbDetection (state);
}
bool isFullBodyAwarenessActive = mainPlayerCamera.isFullBodyAwarenessActive ();
if (isFullBodyAwarenessActive) {
mainPlayerCamera.setIgnorePlayerRotationToCameraOnFBAState (state);
if (state) {
mainPlayerCamera.setPivotCameraTransformParentCurrentTransformToFollow ();
} else {
mainPlayerCamera.setPivotCameraTransformOriginalParent ();
mainPlayerCamera.resetPivotCameraTransformLocalRotation ();
}
}
}
public override void setExternalForceEnabledState (bool state)
{
setClimbEnabledState (state);
}
public void setClimbEnabledState (bool state)
{
if (!state) {
stopClimbAndDetectState ();
}
climbEnabled = state;
}
public void setClimbCheckCanBeUsedState (bool state)
{
climbCheckCanBeUsed = state;
}
public void setClimbEnabledState ()
{
setClimbEnabledState (originalClimbEnabled);
}
public void setOriginalClimbEnabledState ()
{
if (climbActive) {
setCheckIfDetectClimbActiveState (false);
}
setClimbEnabledState (originalClimbEnabled);
}
// public void setClimbDownSpeedMultiplier (float newValue)
// {
// slideDownSpeedMultiplier = newValue;
// }
// public void setForceSlowDownOnSurfaceActiveState (bool state)
// {
// forceSlowDownOnSurfaceActive = state;
// }
public void enableCheckIfDetectClimbActiveStateExternally ()
{
if (checkIfDetectClimbActive) {
return;
}
setCheckIfDetectClimbActiveState (true);
}
public void disableCheckIfDetectClimbActiveStateExternally ()
{
if (!checkIfDetectClimbActive) {
return;
}
setCheckIfDetectClimbActiveState (false);
}
public override void checkIfResumeExternalControllerState ()
{
if (checkIfDetectClimbActive) {
if (showDebugPrint) {
print ("resuming free climb state");
}
externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
if (currentExternalControllerBehavior != null && currentExternalControllerBehavior != this) {
currentExternalControllerBehavior.disableExternalControllerState ();
}
checkIfDetectClimbActive = false;
setCheckIfDetectClimbActiveState (true);
}
}
public override void disableExternalControllerState ()
{
setCheckIfDetectClimbActiveState (false);
}
public void checkEventsOnStateChange (bool state)
{
if (isFirstPersonActive) {
if (useEventsOnFirstPerson) {
if (state) {
eventOnStartFirstPerson.Invoke ();
} else {
eventOnEndFirstPerson.Invoke ();
}
}
} else {
if (useEventsOnThirdPerson) {
if (state) {
eventOnStartThirdPerson.Invoke ();
} else {
eventOnEndThirdPerson.Invoke ();
}
}
}
}
public void setClimbPausedState (bool state)
{
if (state) {
if (climbActive) {
stopClimbAndDetectState ();
}
}
climbPaused = state;
}
public void rotateCharacterOnJump ()
{
stopRotateCharacterOnJumpCoroutine ();
jumpCoroutine = StartCoroutine (rotateCharacterOnJumpCoroutine ());
}
void stopRotateCharacterOnJumpCoroutine ()
{
if (jumpCoroutine != null) {
StopCoroutine (jumpCoroutine);
}
}
public IEnumerator rotateCharacterOnJumpCoroutine ()
{
bool targetReached = false;
float movementTimer = 0;
float t = 0;
float duration = 0;
if (isFirstPersonActive) {
duration = 0.5f / jumpRotationSpeedFirstPerson;
} else {
duration = 0.5f / jumpRotationSpeedThirdPerson;
}
float angleDifference = 0;
Transform objectToRotate = playerTransform;
if (isFirstPersonActive) {
objectToRotate = playerCameraTransform;
}
Quaternion targetRotation = Quaternion.identity;
if (playerTransform.up != getCurrentNormal ()) {
Vector3 currentNormal = getCurrentNormal ();
Quaternion currentPlayerRotation = playerTransform.rotation;
Vector3 currentPlayerForward = Vector3.Cross (-playerTransform.right, currentNormal);
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, currentNormal);
targetRotation = playerTargetRotation;
} else {
targetRotation = Quaternion.LookRotation (-objectToRotate.forward, objectToRotate.up);
}
while (!targetReached) {
t += Time.deltaTime / duration;
objectToRotate.rotation = Quaternion.Lerp (objectToRotate.rotation, targetRotation, t);
angleDifference = Quaternion.Angle (objectToRotate.rotation, targetRotation);
movementTimer += Time.deltaTime;
if (angleDifference < 0.2f || movementTimer > (duration + 1)) {
targetReached = true;
}
yield return null;
}
}
public override void setCurrentPlayerActionSystemCustomActionCategoryID ()
{
if (behaviorCurrentlyActive) {
if (customActionCategoryID > -1) {
mainPlayerController.setCurrentCustomActionCategoryID (customActionCategoryID);
}
} else {
if (regularActionCategoryID > -1) {
mainPlayerController.setCurrentCustomActionCategoryID (regularActionCategoryID);
}
}
}
public void resetPlayerRotation ()
{
stopResetPlayerRotationCoroutine ();
resetPlayerCoroutine = StartCoroutine (resetPlayerRotationCoroutine ());
}
void stopResetPlayerRotationCoroutine ()
{
if (resetPlayerCoroutine != null) {
StopCoroutine (resetPlayerCoroutine);
}
}
IEnumerator resetPlayerRotationCoroutine ()
{
if (showDebugPrint) {
print ("reset player rotation");
}
float movementTimer = 0;
float t = 0;
float duration = 1.5f;
float angleDifference = 0;
Vector3 currentNormal = getCurrentNormal ();
Quaternion currentPlayerRotation = playerTransform.rotation;
Vector3 currentPlayerForward = Vector3.Cross (playerTransform.right, currentNormal);
Quaternion playerTargetRotation = Quaternion.LookRotation (currentPlayerForward, currentNormal);
bool targetReached = false;
while (!targetReached) {
t += (Time.deltaTime / duration) * resetPlayerRotationSpeed;
playerTransform.rotation = Quaternion.Slerp (playerTransform.rotation, playerTargetRotation, t);
angleDifference = Quaternion.Angle (playerTransform.rotation, playerTargetRotation);
movementTimer += Time.deltaTime;
if (angleDifference < 0.01f || movementTimer > (duration + 1)) {
targetReached = true;
}
yield return null;
}
}
public void resetCameraRotation ()
{
stopResetCameraRotationCoroutine ();
resetCameraCoroutine = StartCoroutine (resetCameraRotationCoroutine ());
}
void stopResetCameraRotationCoroutine ()
{
if (resetCameraCoroutine != null) {
StopCoroutine (resetCameraCoroutine);
}
}
IEnumerator resetCameraRotationCoroutine ()
{
if (showDebugPrint) {
print ("reset camera rotation");
}
float movementTimer = 0;
float t = 0;
float duration = 1;
float angleDifference = 0;
Vector3 currentNormal = getCurrentNormal ();
Quaternion currentCameraRotation = playerCameraTransform.rotation;
Vector3 currentCameraForward = Vector3.Cross (playerCameraTransform.right, currentNormal);
Quaternion cameraTargetRotation = Quaternion.LookRotation (currentCameraForward, currentNormal);
bool targetReached = false;
while (!targetReached) {
t += (Time.deltaTime / duration) * resetPlayerRotationSpeed;
playerCameraTransform.rotation = Quaternion.Slerp (playerCameraTransform.rotation, cameraTargetRotation, t);
angleDifference = Quaternion.Angle (playerCameraTransform.rotation, cameraTargetRotation);
movementTimer += Time.deltaTime;
if (angleDifference < 0.01f || movementTimer > (duration + 1)) {
targetReached = true;
}
yield return null;
}
}
bool checkIfCanActivateClimbState ()
{
activateAutoSlideDownOnSurface = false;
bool isPlayerOnGround = mainPlayerController.isPlayerOnGround ();
if (!canActivateClimbOnPlayerOnGround) {
if (isPlayerOnGround) {
return false;
}
}
float currentRaycastDistance = raycastDistanceToCheckToActivateClimbOnGround;
if (!isPlayerOnGround) {
currentRaycastDistance = raycastDistanceToCheckToActivateClimbOnAir;
}
Vector3 currentRaycastPosition = playerTransform.position + playerTransform.up;
RaycastHit temporalHit;
if (Physics.Raycast (currentRaycastPosition, playerTransform.forward, out temporalHit, currentRaycastDistance, raycastLayermask)) {
bool surfaceDistanceTooFar = false;
if (isPlayerOnGround) {
if (temporalHit.distance > minDistanceToSurfaceToGrabSurfaceOnGround) {
surfaceDistanceTooFar = true;
}
} else {
if (temporalHit.distance > minDistanceToSurfaceToGrabSurfaceOnAir) {
surfaceDistanceTooFar = true;
}
}
if (surfaceDistanceTooFar) {
if (showDebugPrint) {
print ("surface to climb too far");
}
return false;
} else {
if (useSurfacesToIgnoreTags) {
if (surfacesToIgnoreTagsList.Contains (temporalHit.collider.gameObject.tag)) {
if (showDebugPrint) {
print ("surface to ignore by tag found");
}
return false;
}
}
freeClimbZoneSystem currentFreeClimbZoneSystem = temporalHit.collider.GetComponent<freeClimbZoneSystem> ();
if (checkTagsToIgnoreOnManualClimbInputActive) {
checkTagsToIgnoreOnManualClimbInputActive = false;
if (useSurfacesToCheckTagsOnClimbByInput) {
if (!surfacesToCheckTagsOnClimbByInputList.Contains (temporalHit.collider.gameObject.tag)) {
if (showDebugPrint) {
print ("surface to check by tag not found " + temporalHit.collider.gameObject.tag);
}
if (checkForClimbSurfaceZoneSystemOnClimbInput) {
if (currentFreeClimbZoneSystem != null) {
if (!currentFreeClimbZoneSystem.isAllowClimbSurfaceOnInputEnabled ()) {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
}
}
if (ignoreRigidbodies) {
if (temporalHit.collider.attachedRigidbody != null) {
return false;
}
}
if (currentFreeClimbZoneSystem != null) {
if (currentFreeClimbZoneSystem.isIgnoreSurfaceToClimbEnabled ()) {
return false;
}
if (currentFreeClimbZoneSystem.activateAutoSlideDownOnSurface) {
activateAutoSlideDownOnSurface = true;
}
}
if (currentFreeClimbZoneSystem != null) {
movementInputDisabledOnSurface = currentFreeClimbZoneSystem.movementInputDisabledOnSurface;
}
}
} else {
if (showDebugPrint) {
print ("surface to climb not found");
}
return false;
}
if (Physics.Raycast (currentRaycastPosition, playerTransform.forward, out temporalHit, currentRaycastDistance, raycastLayermask)) {
surfaceAngle = Vector3.SignedAngle (temporalHit.normal, -playerTransform.forward, playerTransform.right);
}
if (showDebugPrint) {
print ("surface angle to check before activate climb " + surfaceAngle);
}
if (surfaceAngle != 0) {
if (stopClimbAtMinAngleOnSurface) {
if (surfaceAngle < 0) {
if (surfaceAngle < minAngleToStopClimb) {
return false;
}
}
}
if (stopClimbAtMaxAngleOnSurface) {
if (surfaceAngle > 0) {
if (surfaceAngle > maxAngleToStopClimb) {
return false;
}
}
}
}
return true;
}
public void setActivateClimbStateOnNextSurfaceDetectedActiveState (bool state)
{
if (ignoreActivateClimbStateOnNextSurfaceDetectedActive) {
return;
}
activateClimbStateOnNextSurfaceDetectedActive = state;
if (showDebugPrint) {
print ("setting activateClimbStateOnNextSurfaceDetectedActive " + activateClimbStateOnNextSurfaceDetectedActive);
}
stopCheckIfSurfaceDetectedInFrontCoroutine ();
if (activateClimbStateOnNextSurfaceDetectedActive) {
lastTimeActivateClimbStateOnNextSurfaceDetectedActive = Time.time;
checkIfSurfaceDetectedInFrontCoroutine = StartCoroutine (updateCheckIfSurfaceDetectedInFrontCoroutine ());
}
}
public void stopCheckIfSurfaceDetectedInFrontCoroutine ()
{
if (checkIfSurfaceDetectedInFrontCoroutine != null) {
StopCoroutine (checkIfSurfaceDetectedInFrontCoroutine);
}
}
IEnumerator updateCheckIfSurfaceDetectedInFrontCoroutine ()
{
var waitTime = new WaitForSeconds (0.00001f);
while (true) {
if (Time.time > lastTimeActivateClimbStateOnNextSurfaceDetectedActive + 0.5f) {
if (mainPlayerController.isPlayerOnGround ()) {
stopCheckIfSurfaceDetectedInFrontCoroutine ();
activateClimbStateOnNextSurfaceDetectedActive = false;
if (showDebugPrint) {
print ("disabling activateClimbStateOnNextSurfaceDetectedActive");
}
}
if (climbActive) {
stopCheckIfSurfaceDetectedInFrontCoroutine ();
activateClimbStateOnNextSurfaceDetectedActive = false;
if (showDebugPrint) {
print ("disabling activateClimbStateOnNextSurfaceDetectedActive");
}
}
}
if (Time.time > lastTimeActivateClimbStateOnNextSurfaceDetectedActive + 5) {
if (showDebugPrint) {
print ("disabling activateClimbStateOnNextSurfaceDetectedActive from too much time on air");
}
stopCheckIfSurfaceDetectedInFrontCoroutine ();
activateClimbStateOnNextSurfaceDetectedActive = false;
}
if (Physics.Raycast (playerTransform.position + (verticalRaycastOffset * playerTransformUp),
playerTransform.forward, minDistanceToSurfaceToGrabSurfaceOnAir, raycastLayermask)) {
inputGrabSurface ();
stopCheckIfSurfaceDetectedInFrontCoroutine ();
activateClimbStateOnNextSurfaceDetectedActive = false;
if (showDebugPrint) {
print ("activating climb from detecting next surface");
}
}
yield return waitTime;
}
}
public void activateGrabSurface ()
{
if (checkIfDetectClimbActive) {
if (!climbActive) {
if (!checkIfCanActivateClimbState ()) {
return;
}
}
if (activateClimbStateOnNextSurfaceDetectedActive) {
setActivateClimbStateOnNextSurfaceDetectedActiveState (false);
}
setClimbActiveState (!climbActive);
}
}
void checkEventsOnTurbo (bool state)
{
if (useEventOnTurbo) {
if (state) {
eventOnStartTurbo.Invoke ();
} else {
eventOnEndTurbo.Invoke ();
}
}
}
#region UpdateRaycastDetection
//REGULAR RAYCAST DETECTION METHOD
bool updateRaycastDetectionState (Vector3 currentRaycastPosition, Vector3 currentRaycastDirection, float currentFixedUpdateDeltaTime)
{
surfaceFoundOnRegularRaycast = false;
float currentRaycastDistance = raycastDistance;
if (surfaceFoundOnSide || surfaceFoundOnCloseSide) {
Vector3 heading = lastSideDirection - (playerTransform.position + playerTransformUp);
float distance = heading.magnitude;
currentRaycastDirection = heading / distance;
currentRaycastDistance = raycastDistance * 2;
}
float regularRaycastDistance = currentRaycastDistance;
if (movementInputPausedActive) {
regularRaycastDistance += 1;
}
if (Physics.Raycast (playerTransform.position + (verticalRaycastOffset * playerTransformUp),
currentRaycastDirection, regularRaycastDistance, raycastLayermask)) {
surfaceFoundOnRegularRaycast = true;
}
Vector3 mainRaycastPosition = playerTransform.position + playerTransformUp;
Physics.Raycast (mainRaycastPosition, currentRaycastDirection, out hit, regularRaycastDistance, raycastLayermask);
//check sides with raycast
if (checkSidesEnabled) {
RaycastHit temporalHit;
if (!surfaceFoundOnCloseSide && !upperBodySurfaceDetected) {
if (!surfaceFoundOnSide) {
if (!Physics.Raycast (currentRaycastPosition, currentRaycastDirection, out temporalHit,
raycastDistanceToCheckSides, raycastLayermask)) {
bool movingRight = currentHorizontalMovement > 0;
bool movingLeft = currentHorizontalMovement < 0;
Vector3 newRaycastDirection = playerTransform.forward;
if (movingRight || movingLeft) {
if (movingRight) {
newRaycastDirection = Quaternion.AngleAxis (-45, Vector3.up) * newRaycastDirection;
currentRaycastPosition = playerTransform.position + playerTransform.right + playerTransformUp;
} else {
newRaycastDirection = Quaternion.AngleAxis (45, Vector3.up) * newRaycastDirection;
currentRaycastPosition = playerTransform.position - playerTransform.right + playerTransformUp;
}
}
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, 4 * newRaycastDirection, Color.red, 5);
}
if (Physics.Raycast (currentRaycastPosition, newRaycastDirection, out hit, raycastDistance * 3, raycastLayermask)) {
surfaceFoundOnRegularRaycast = true;
surfaceFoundOnSide = true;
lastSideDirection = hit.point;
lastSideNormal = hit.normal;
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, 20 * newRaycastDirection, Color.black, 5);
}
}
}
}
}
}
//check close sides with raycast
if (checkCloseSidesEnabled) {
if (!surfaceFoundOnCloseSide) {
bool movingRight = currentHorizontalMovement > 0;
bool movingLeft = currentHorizontalMovement < 0;
if (movingRight) {
currentRaycastDirection = playerTransform.right;
} else {
currentRaycastDirection = -playerTransform.right;
}
if (movingLeft || movingRight) {
currentRaycastPosition = playerTransform.position + playerTransformUp;
RaycastHit temporalHit;
if (Physics.Raycast (currentRaycastPosition, currentRaycastDirection, out temporalHit, raycastDistanceToCheckCloseSides, raycastLayermask)) {
surfaceFoundOnRegularRaycast = true;
surfaceFoundOnCloseSide = true;
lastSideDirection = temporalHit.point;
lastSideNormal = temporalHit.normal;
hit = temporalHit;
surfaceFoundOnSide = false;
}
}
}
}
//check change of view state
updateCheckCameraViewState ();
currentClimbMovementSpeed = climbMovementSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbMovementSpeed = climbMovementSpeedFirstPerson;
}
currentClimbRotationSpeed = climbRotationSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbRotationSpeed = climbRotationSpeedFirstPerson;
}
currentClimbVelocity = climbVelocityThirdPerson;
if (isFirstPersonActive) {
currentClimbVelocity = climbVelocityFirstPerson;
}
if (slidingDownActive || activateAutoSlideDownOnSurface) {
currentClimbVelocity = slideDownSpeedThirdPerson;
if (isFirstPersonActive) {
currentClimbVelocity = SlideDownSpeedFirstPerson;
}
}
if (movementInputPausedActive || movementInputDisabledOnSurface) {
rawAxisValues = Vector2.zero;
}
checkCurrentSurfaceDetected ();
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (!movementInputPausedActive && !cancelMovementInputActive && lowerBodySurfaceDetected && surfaceDetectedOnMovementInputRaycast) {
currentVerticalMovement = -1;
rawAxisValues.y = currentVerticalMovement;
if (currentHorizontalMovement != 0) {
currentHorizontalMovement /= 2;
}
}
}
if (cancelMovementInputActive) {
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
rawAxisValues = Vector2.zero;
}
if (!lowerBodySurfaceDetected) {
if (!surfaceDetectedOnMovementInputRaycast) {
currentVerticalMovement = 0;
rawAxisValues.y = 0;
}
}
if (surfaceDetectedAbovePlayer) {
currentVerticalMovement = Mathf.Clamp (currentVerticalMovement, -1, 0);
rawAxisValues.y = Mathf.Clamp (rawAxisValues.y, -1, 0);
}
if (surfafeDetectedBelowPlayer) {
currentVerticalMovement = Mathf.Clamp (currentVerticalMovement, 0, 1);
rawAxisValues.y = Mathf.Clamp (rawAxisValues.y, 0, 1);
}
slidingDownResult = false;
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (currentVerticalMovement != 0) {
if (currentIDValue != 1) {
currentIDValue = 1;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
slidingDownResult = true;
} else {
if (currentIDValue != 0) {
currentIDValue = 0;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
}
} else {
if (currentIDValue != 0) {
currentIDValue = 0;
mainPlayerController.setCurrentIdleIDValue (currentIDValue);
mainPlayerController.updateIdleIDOnAnimator ();
}
}
moving = (Mathf.Abs (currentVerticalMovement) > 0.01f || Mathf.Abs (currentHorizontalMovement) > 0.01f);
movementInputPressed = rawAxisValues != Vector2.zero;
currentClimbTurboSpeed = 1;
bool enougMovementInput = (Mathf.Abs (currentVerticalMovement) > 0.7f || Mathf.Abs (currentHorizontalMovement) > 0.7f);
if (increaseClimbSpeedActive && movementInputPressed && enougMovementInput && !slidingDownActive && !activateAutoSlideDownOnSurface) {
currentClimbTurboSpeed = climbTurboSpeed;
if (!turboActive) {
mainPlayerController.setCurrentAirSpeedValue (2);
turboActive = true;
checkEventsOnTurbo (true);
}
} else {
if (turboActive) {
mainPlayerController.setCurrentAirSpeedValue (1);
turboActive = false;
mainPlayerController.stopShakeCamera ();
checkEventsOnTurbo (false);
eventOnRegularClimbSpeed.Invoke ();
}
}
//update player velocity
if (surfaceFoundOnRegularRaycast) {
Vector3 targetPosition = hit.point + surfaceOffset * hit.normal;
targetPosition -= playerTransformUp;
if (useMovementCurve) {
currentClimbMovementSpeed = mainMovementCurve.Evaluate (currentClimbMovementSpeed);
}
bool closeToSurfaceDetected = GKC_Utils.distance (mainRigidbody.position, targetPosition) > 0.01f;
if (movementInputPressed || closeToSurfaceDetected || movementInputPausedActive) {
mainRigidbody.position = Vector3.Lerp (mainRigidbody.position, targetPosition, currentClimbTurboSpeed * currentClimbMovementSpeed * currentFixedUpdateDeltaTime);
}
}
if (surfaceFoundOnRegularRaycast || surfaceFoundOnSide || surfaceFoundOnCloseSide) {
Vector2 axisValues = new Vector2 (currentHorizontalMovement, currentVerticalMovement);
if (useVelocityCurve) {
currentClimbVelocity = mainVelocityCurve.Evaluate (currentClimbVelocity);
}
if (movementInputPressed) {
mainRigidbody.linearVelocity = currentClimbVelocity * currentClimbTurboSpeed * playerTransform.TransformDirection (axisValues);
}
}
if (movementInputPressed || surfaceFoundOnSide || surfaceFoundOnCloseSide) {
mainPlayerController.setCurrentVelocityValue (mainRigidbody.linearVelocity);
} else {
mainPlayerController.setCurrentVelocityValue (Vector3.zero);
}
if (slidingDownActive || activateAutoSlideDownOnSurface) {
if (slidingDownResult) {
currentVerticalMovement = 0;
}
}
//update player animation states
mainAnimator.SetFloat (horizontalAnimatorID, currentHorizontalMovement, inputLerpSpeed, currentFixedUpdateDeltaTime);
mainAnimator.SetFloat (verticalAnimatorID, currentVerticalMovement, inputLerpSpeed, currentFixedUpdateDeltaTime);
//update player rotation
currentRaycastPosition = playerTransform.position + playerTransformUp;
currentRaycastDirection = playerTransform.forward;
currentRaycastDistance = raycastDistance;
if (surfaceFoundOnSide || surfaceFoundOnCloseSide) {
currentRaycastDirection = lastSideDirection - (playerTransform.position + playerTransformUp);
if (currentRaycastDirection.magnitude > 1) {
currentRaycastDirection.Normalize ();
}
float currentClimbAngle = Vector3.SignedAngle (playerTransform.up, getCurrentNormal (), playerTransform.right);
if (Mathf.Abs (currentClimbAngle) > 3) {
currentRaycastDistance += 4;
} else {
currentRaycastDistance += 2;
}
}
if (Physics.Raycast (currentRaycastPosition, currentRaycastDirection, out hit, currentRaycastDistance, raycastLayermask)) {
Quaternion targetRotation = Quaternion.LookRotation (-hit.normal);
playerTransform.rotation = Quaternion.Lerp (playerTransform.rotation, targetRotation, currentClimbRotationSpeed * currentFixedUpdateDeltaTime);
if (rotateCameraToPlayerRotationOnClimbActiveEnabled) {
Vector3 myForwardCamera = Vector3.Cross (playerCameraTransform.right, playerTransform.up);
Quaternion dstRotCamera = Quaternion.LookRotation (myForwardCamera, playerTransform.up);
playerCameraTransform.rotation = Quaternion.Lerp (playerCameraTransform.rotation, dstRotCamera, currentClimbRotationSpeed * currentFixedUpdateDeltaTime);
}
if (surfaceFoundOnSide) {
float temporalAngle = Vector3.SignedAngle (lastSideNormal, -playerTransform.forward, playerTransform.up);
if (Mathf.Abs (temporalAngle) < 2) {
surfaceFoundOnSide = false;
}
}
if (surfaceFoundOnCloseSide) {
float temporalAngle = Vector3.SignedAngle (lastSideNormal, -playerTransform.forward, playerTransform.up);
if (Mathf.Abs (temporalAngle) < 2) {
surfaceFoundOnCloseSide = false;
}
}
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, currentRaycastDistance * currentRaycastDirection, Color.gray, 5);
}
} else {
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, currentRaycastDistance * currentRaycastDirection, Color.magenta, 5);
}
}
//check if surface not found, to stop the climb action
if (!surfaceFoundOnSide && !surfaceFoundOnCloseSide && !movementInputPausedActive) {
currentRaycastPosition = playerTransform.position + offsetToCheckIfStopClimbStateOnRaycast * playerTransformUp;
if (!Physics.Raycast (currentRaycastPosition, playerTransform.forward, maxRaycastDistanceToStopClimb, raycastLayermask)) {
if (lastTimeSurfaceNotFound == 0) {
lastTimeSurfaceNotFound = Time.time;
}
} else {
if (showGizmo) {
Debug.DrawRay (currentRaycastPosition, 2 * playerTransform.forward, Color.yellow);
}
lastTimeSurfaceNotFound = 0;
}
if (lastTimeSurfaceNotFound > 0) {
if (Time.time > lastTimeSurfaceNotFound + minTimeToStopClimbIfNotSurfaceFound) {
lastTimeSurfaceNotFound = 0;
stopClimbAndDetectState ();
return false;
}
}
}
return true;
}
#endregion
//Input functions
public void inputSetSlideDownState (bool state)
{
if (!climbActive) {
return;
}
if (!slideDownEnabled) {
return;
}
if (!canUseInput ()) {
return;
}
if (activateAutoSlideDownOnSurface) {
return;
}
if (adjustingPlayerToSurfaceCollisionDetection) {
return;
}
if (slidingDownActive == state) {
return;
}
slidingDownActive = state;
currentIDValue = -1;
}
public void inputGrabSurface ()
{
if (!canUseInput ()) {
if (showDebugPrint) {
print ("can't use input grab surface");
}
return;
}
if (climbPaused) {
return;
}
if (!climbActive) {
if (Time.time < mainPlayerController.getLastTimeActionActive () + minWaitTimeSinceLastTimeActionActiveToClimb) {
return;
}
}
if (adjustingPlayerToSurfaceCollisionDetection) {
return;
}
if (activateClimbStateDirectlyOnPressInput) {
if (checkIfDetectClimbActive) {
setCheckIfDetectClimbActiveState (false);
climbStateActivatedByInput = false;
} else {
checkTagsToIgnoreOnManualClimbInputActive = true;
if (checkIfCanActivateClimbState ()) {
setCheckIfDetectClimbActiveState (true);
activateGrabSurface ();
climbStateActivatedByInput = true;
}
checkTagsToIgnoreOnManualClimbInputActive = false;
}
} else {
activateGrabSurface ();
}
}
public void inpuSetIncreaseClimbSpeedState (bool state)
{
if (!climbActive) {
return;
}
if (!slideDownEnabled) {
return;
}
if (!canUseInput ()) {
return;
}
if (adjustingPlayerToSurfaceCollisionDetection) {
return;
}
if (activateAutoSlideDownOnSurface) {
return;
}
if (increaseClimbSpeedActive == state) {
return;
}
increaseClimbSpeedActive = state;
}
bool canUseInput ()
{
if (mainPlayerController.isGravityPowerActive ()) {
return false;
}
if (mainPlayerController.isPlayerUsingPowers ()) {
return false;
}
if (mainPlayerController.isUsingDevice ()) {
return false;
}
if (mainPlayerController.isPlayerDead ()) {
return false;
}
if (mainPlayerController.isPlayerMenuActive ()) {
return false;
}
if (mainPlayerController.isUsingSubMenu ()) {
return false;
}
if (mainPlayerController.isActionActive ()) {
return false;
}
if (mainPlayerController.isPlayerDriving ()) {
return false;
}
return true;
}
public void setClimbEnabledStateFromEditor (bool state)
{
setClimbEnabledState (state);
updateComponent ();
}
void updateComponent ()
{
GKC_Utils.updateComponent (this);
GKC_Utils.updateDirtyScene ("Update Free Climb System", gameObject);
}
}