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

1696 lines
53 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class swimSystem : externalControllerBehavior
{
[Header ("Main Settings")]
[Space]
public bool swimSystemEnabled = true;
public LayerMask layerForGroundDetection;
public float groundDetectionRaycastDistance = 1;
public float groundDetectionRaycastDistanceOnWater = 0.1f;
public float maxDistanceToWalkOnWater = 1;
[Space]
[Header ("Animation Settings")]
[Space]
public int swimID;
public int regularID = 1;
public int swimStateID = 0;
public int diveStateID = 1;
public int movingUpStateID = 1;
public int movingDownStateID = 1;
public float movingUpForwardStateID = 1.5f;
public float movingDownForwardStateID = 2.5f;
public int regularIdleID = 0;
[Space]
[Header ("Physics Settings")]
[Space]
public bool useForceMode;
public ForceMode swimForceMode;
public bool moveUpAndDownEnabled;
public bool turboEnabled;
public float waterFriction;
public float maxSwimVelocity;
public float swimTurboSpeed;
public float swimForce;
public float swimMoveUpSpeed;
public float swimMoveDownSpeed;
public float swimSpeedOnAimMultiplier;
public float autoAdjustDistanceToSwimSurfaceSpeed = 2;
public float autoAdjustDistanceToSwimSurface = 1.6f;
public float firstPersonSpeedMultiplier = 1;
[Space]
public bool addForceIfDeadOnWater;
public Vector3 forceDirectionIfDeadOnWater = -Vector3.up;
public float forceAmountIfDeadOnWater = 5;
[Space]
[Header ("Return To Surface On Enter Water Settings")]
[Space]
public bool setInitialStateOnSurfaceOnEnterWater = true;
public bool useMaxSpeedToMoveToSurfaceOnSwimEnabled;
public float maxSpeedToMoveToSurfaceOnSwimEnabled = 20;
public float minSpeedToSetSwimOnSurfaceState = 5;
public bool cancelReturnToSurfaceIfInputPressed;
[Space]
[Header ("Other Settings")]
[Space]
public float minDistanceForSwimSurface = 0.2f;
public float delayToResetVelocityWhenReachingSurfaceFromMovingInput = 0.4f;
public bool keepSwimStateActiveOnDeath;
public bool checkGroundDistanceOnSwimOnSurface = true;
public float raycastDistanceToCheckOnSwimOnSurface = 1;
public bool checkIfPlayerIsOnWaterInsideVehicles;
[Space]
[Header ("Jump Settings")]
[Space]
public bool canJumpWhenSwimmingOnSurface;
public float jumpForceOnSurface;
public bool onlyClimbOnCloseSurfaces;
public float maxAngleDifferenceOnSurfaceToClimb = 90;
public float maxClimbSurfaceHeight = 4;
public bool allowJumpOnSwimIfNoCloseSurfaceToClimbFound;
public Transform climbSurfaceActionSystemTransform;
[Space]
[Space]
public eventParameters.eventToCallWithGameObject eventToActivateClimbSurfaceActionSystem;
[Space]
[Header ("Swim Settings")]
[Space]
public float swimVerticalSpeedMultiplier;
public float swimHorizontalSpeedMultiplier;
[Space]
[Header ("Dive Settings")]
[Space]
public float diveVerticalSpeedMultiplier;
public float diveHorizontalSpeedMultiplier;
[Space]
[Header ("Third Person Camera State Settings")]
[Space]
public bool setNewCameraStateOnThirdPerson;
public string newCameraStateOnThirdPerson;
public bool returnToPreviuosViewOnSwimEnd = true;
[Space]
[Header ("Debug")]
[Space]
public bool showDebugPrint;
public bool swimSystemActive;
public bool turboActive;
public bool movingUp;
public bool movingDown;
public bool currentlyOnSurface;
public bool currentlyDiving;
public bool overridingMovementToSurfaceActive;
public Vector3 targetDirection;
public float currentHorizontalMovement;
public float currentVerticalMovement;
public bool checkIfCloseToSurface;
public bool playerIsMoving;
public float currentDistanceToSurface;
public bool checkingToActivateMovementToSurfaceAutomaticallyActive;
public float currentStatID;
public bool walkingOnWater;
public Vector3 totalForce;
public Vector3 extraForce;
public bool cameraBelowWater;
public bool swimForcesPaused;
public float currentLookAngle;
public float lookDirectionAngle;
public bool checkingIfPlayerNotMovingInsideVehicleActive;
[Space]
public List<Collider> swimTriggerList = new List<Collider> ();
[Space]
[Header ("Events Settings")]
[Space]
public UnityEvent eventOnStateEnabled;
public UnityEvent eventOnStateDisabled;
public bool useEventOnWalkingOnWater;
public UnityEvent eventOnWalkingOnWater;
public bool useEventsOnDiveStateChange;
public UnityEvent eventOnStartDive;
public UnityEvent eventOnEndDive;
public bool useEventOnChangeSwimToDive;
public UnityEvent eventOnChangeSwimToDive;
public bool useEventOnChangeDiveToSwim;
public UnityEvent eventOnChangeDiveToSwim;
public UnityEvent eventBeforeActivatingSwimSystem;
public UnityEvent eventBeforeDeactivatingSwimSystem;
public bool useEventOnCameraUnderwaterEffect;
public UnityEvent eventOnCameraUnderWaterStart;
public UnityEvent eventOnCameraUnderWaterEnd;
public bool useEventUseTurboOnSwim;
public UnityEvent eventOnStarTurboOnSwim;
public UnityEvent eventOnEndTurboOnSwim;
[Space]
[Header ("Components")]
[Space]
public playerController mainPlayerController;
public Transform playerTransform;
public Transform mainCameraTransform;
public Transform playerCameraTransform;
public Rigidbody mainRigidbody;
public playerInputManager playerInput;
public headTrack mainHeadTrack;
public Collider mainPlayerCollider;
public Collider swimCollider;
public playerCamera mainPlayerCamera;
public ragdollActivator mainRagdollActivator;
float currentAimSpeedMultipler;
float velocityMagnitude;
Transform currentSwimZoneTransform;
float lastTimeSwimActive;
bool lookingInCameraDirection;
bool turnAndForwardAnimatorValuesPaused;
bool checkingDivingDirection;
bool enteringOnWaterFromWalking;
float lastTimeWalkingOnWaterActive;
bool setMovementToSurfaceOnEnterWaterActive;
bool canUseTurboPausedState;
string previousCameraState = "";
bool reachingSurfaceFromMovingInput;
float lastTimeSurfaceReachedFromMovingInput;
bool firstPersonChecked;
bool thirdPersonChecked;
waterSurfaceSystem currentWaterSurfaceSystem;
bool updateSurfaceTransformDynamically;
Collider currentSwimTrigger;
bool currentSwimTriggerLocated;
Transform currentLockedCameraTransform;
bool isPlayerMovingOn3dWorld;
bool isCameraTypeFree;
Coroutine checkIfPlayerNotOnVehicleCoroutine;
bool ignoreDisableCameraBelowWaterStateActive;
void checkSwimStateOnDeath ()
{
if (cameraBelowWater) {
ignoreDisableCameraBelowWaterStateActive = true;
}
setSwimSystemActivestate (false);
setExtraCharacterStateOnSwim (true);
if (addForceIfDeadOnWater) {
mainRagdollActivator.setCustomForceOnMainHipsRigidbody (forceDirectionIfDeadOnWater * forceAmountIfDeadOnWater);
}
}
void setExtraCharacterStateOnSwim (bool state)
{
if (state) {
mainPlayerCamera.setCustomSmoothReturnSpeed (10);
} else {
mainPlayerCamera.setOriginalSmoothReturnSpeed ();
}
if (mainRagdollActivator != null) {
mainRagdollActivator.setPauseAnimatorStatesToGetUpState (state);
mainRagdollActivator.setStateToGetUpOnAirActive (state);
}
}
public override void updateControllerBehavior ()
{
//if the player is swimming
if (swimSystemActive) {
if (mainPlayerController.isPlayerDead ()) {
checkSwimStateOnDeath ();
return;
}
bool getRegularDistanceToSurface = true;
if (updateSurfaceTransformDynamically) {
float surfacePosition = currentWaterSurfaceSystem.GetWaterLevel (playerTransform.position);
currentDistanceToSurface = Mathf.Abs (playerTransform.position.y - surfacePosition);
if (surfacePosition != -1) {
getRegularDistanceToSurface = false;
}
}
if (getRegularDistanceToSurface) {
currentDistanceToSurface = Mathf.Abs (playerTransform.InverseTransformPoint (currentSwimZoneTransform.position).y);
}
isPlayerMovingOn3dWorld = mainPlayerController.isPlayerMovingOn3dWorld ();
isCameraTypeFree = mainPlayerCamera.isCameraTypeFree ();
if (walkingOnWater) {
if (!mainPlayerController.isPlayerOnGround () && (lastTimeWalkingOnWaterActive == 0 || Time.time > lastTimeWalkingOnWaterActive + 1)) {
enableOrDisableSwimState (true);
walkingOnWater = false;
lastTimeWalkingOnWaterActive = 0;
} else {
if (currentDistanceToSurface > maxDistanceToWalkOnWater) {
enteringOnWaterFromWalking = true;
walkingOnWater = false;
enableOrDisableSwimState (true);
}
}
} else {
updateSwimActiveState ();
checkIfGroundDetectedOnSwimActiveState ();
if (useEventOnCameraUnderwaterEffect) {
if (currentSwimTriggerLocated) {
bool cameraInsideBoundTrigger = false;
if (isPlayerMovingOn3dWorld && isCameraTypeFree) {
cameraInsideBoundTrigger = currentSwimTrigger.bounds.Contains (mainCameraTransform.position);
} else {
cameraInsideBoundTrigger = currentSwimTrigger.bounds.Contains (playerTransform.position + 1.7f * playerCameraTransform.up);
}
if (cameraInsideBoundTrigger) {
if (!cameraBelowWater) {
eventOnCameraUnderWaterStart.Invoke ();
cameraBelowWater = true;
}
} else {
if (cameraBelowWater) {
eventOnCameraUnderWaterEnd.Invoke ();
cameraBelowWater = false;
}
}
} else {
if (mainCameraTransform.position.y < currentSwimZoneTransform.position.y) {
if (!cameraBelowWater) {
eventOnCameraUnderWaterStart.Invoke ();
cameraBelowWater = true;
}
} else {
if (cameraBelowWater) {
eventOnCameraUnderWaterEnd.Invoke ();
cameraBelowWater = false;
}
}
}
}
}
}
}
void updateSwimActiveState ()
{
targetDirection = Vector3.zero;
currentVerticalMovement = mainPlayerController.getVerticalInput ();
currentHorizontalMovement = mainPlayerController.getHorizontalInput ();
if (overridingMovementToSurfaceActive) {
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
checkIfCloseToSurface = true;
playerInput.overrideInputValues (new Vector2 (0, 1), true);
if (cancelReturnToSurfaceIfInputPressed) {
if (playerInput.getRealMovementAxisInputAnyType () != Vector2.zero) {
enableOrDisableVerticalMovementUp (false);
overridingMovementToSurfaceActive = false;
checkIfCloseToSurface = false;
setDivingState (true);
if (showDebugPrint) {
print ("cancel movement to surface");
}
}
}
} else {
if (movingUp) {
checkIfCloseToSurface = true;
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
if (lookingInCameraDirection) {
playerInput.overrideInputValues (new Vector2 (0, 1), true);
} else {
playerInput.overrideInputValues (new Vector2 (0, -1), true);
}
} else {
checkIfCloseToSurface = false;
}
if (movingDown) {
currentVerticalMovement = 0;
currentHorizontalMovement = 0;
if (lookingInCameraDirection) {
playerInput.overrideInputValues (new Vector2 (0, 1), true);
} else {
playerInput.overrideInputValues (new Vector2 (0, -1), true);
}
}
}
if (!checkIfCloseToSurface) {
if (currentlyDiving) {
if (!overridingMovementToSurfaceActive) {
if (!movingUp && !movingDown && playerIsMoving) {
if (currentStatID != movingUpStateID && currentDistanceToSurface < minDistanceForSwimSurface) {
if (currentStatID == diveStateID) {
if (showDebugPrint) {
print ("returning to surface from up axis input");
}
checkIfCloseToSurface = true;
}
}
}
}
}
}
if (checkIfCloseToSurface) {
bool canCheckDistance = true;
if (checkingToActivateMovementToSurfaceAutomaticallyActive) {
if (Time.time > lastTimeSwimActive + 1) {
checkingToActivateMovementToSurfaceAutomaticallyActive = false;
} else {
canCheckDistance = false;
// if (showDebugPrint) {
// print ("waiting to check close to surface");
// }
}
}
if (canCheckDistance && currentDistanceToSurface < minDistanceForSwimSurface) {
if (showDebugPrint) {
print ("close to surface reached");
}
enableOrDisableVerticalMovementUp (false);
overridingMovementToSurfaceActive = false;
checkIfCloseToSurface = false;
setDivingState (false);
lastTimeSurfaceReachedFromMovingInput = Time.time;
reachingSurfaceFromMovingInput = true;
}
}
if (!isPlayerMovingOn3dWorld || !isCameraTypeFree) {
currentLockedCameraTransform = mainPlayerCamera.getLockedCameraTransform ();
}
if (currentlyDiving) {
if (isPlayerMovingOn3dWorld) {
if (isCameraTypeFree) {
targetDirection =
(currentVerticalMovement * diveVerticalSpeedMultiplier) * mainCameraTransform.forward +
(currentHorizontalMovement * diveHorizontalSpeedMultiplier) * mainCameraTransform.right;
} else {
targetDirection =
(currentVerticalMovement * diveVerticalSpeedMultiplier) * currentLockedCameraTransform.forward +
(currentHorizontalMovement * diveHorizontalSpeedMultiplier) * currentLockedCameraTransform.right;
}
} else {
targetDirection =
(currentVerticalMovement * diveVerticalSpeedMultiplier) * currentLockedCameraTransform.up +
(currentHorizontalMovement * diveHorizontalSpeedMultiplier) * currentLockedCameraTransform.right;
}
}
if (currentlyOnSurface) {
if (isPlayerMovingOn3dWorld) {
if (isCameraTypeFree) {
targetDirection =
(currentVerticalMovement * swimVerticalSpeedMultiplier) * playerCameraTransform.forward +
(currentHorizontalMovement * swimHorizontalSpeedMultiplier) * playerCameraTransform.right;
} else {
targetDirection =
(currentVerticalMovement * swimVerticalSpeedMultiplier) * currentLockedCameraTransform.forward +
(currentHorizontalMovement * swimHorizontalSpeedMultiplier) * currentLockedCameraTransform.right;
}
} else {
targetDirection =
(currentVerticalMovement * swimVerticalSpeedMultiplier) * currentLockedCameraTransform.up +
(currentHorizontalMovement * swimHorizontalSpeedMultiplier) * currentLockedCameraTransform.right;
}
}
if (targetDirection.magnitude > 1) {
targetDirection.Normalize ();
}
playerIsMoving = mainPlayerController.isPlayerMoving (0.1f);
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;
}
} 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);
}
thirdPersonChecked = true;
firstPersonChecked = false;
}
}
if (!isPlayerOnFirstPerson && !mainPlayerController.isPlayerRotatingToSurface ()) {
if (playerIsMoving) {
currentLookAngle = 0;
if (!mainPlayerController.isPlayerAiming ()) {
if (currentlyDiving && !movingDown && !movingUp) {
if (isPlayerMovingOn3dWorld) {
if (isCameraTypeFree) {
currentLookAngle = Vector3.SignedAngle (playerCameraTransform.forward, mainCameraTransform.forward, playerCameraTransform.right);
float angleWithCamera = Vector3.SignedAngle (playerCameraTransform.forward, playerTransform.forward, playerCameraTransform.up);
bool playerInCameraDirection = Mathf.Abs (angleWithCamera) < 90;
if (currentLookAngle > 45) {
if (playerInCameraDirection) {
currentStatID = movingDownStateID;
} else {
currentStatID = movingUpStateID;
}
} else if (currentLookAngle < -45) {
if (playerInCameraDirection) {
currentStatID = movingUpStateID;
} else {
currentStatID = movingDownStateID;
}
} else {
currentStatID = diveStateID;
}
} else {
currentStatID = diveStateID;
}
} else {
lookDirectionAngle = Vector3.Angle (playerTransform.forward, currentLockedCameraTransform.right);
bool lookingRight = false;
if (lookDirectionAngle < 90) {
lookingRight = true;
}
if (lookingRight) {
currentLookAngle = Vector3.SignedAngle (targetDirection, currentLockedCameraTransform.right, currentLockedCameraTransform.forward);
} else {
currentLookAngle = Vector3.SignedAngle (targetDirection, -currentLockedCameraTransform.right, -currentLockedCameraTransform.forward);
}
if (currentLookAngle > 70) {
currentStatID = movingDownStateID;
} else if (currentLookAngle < 70 && currentLookAngle > 40) {
currentStatID = movingDownForwardStateID;
} else if (currentLookAngle > -70 && currentLookAngle < -40) {
currentStatID = movingUpForwardStateID;
} else if (currentLookAngle < -70) {
currentStatID = movingUpStateID;
} else {
currentStatID = diveStateID;
}
}
mainPlayerController.setCurrentIdleIDValueFloat (currentStatID);
checkingDivingDirection = true;
if (currentStatID == movingUpStateID && currentDistanceToSurface < minDistanceForSwimSurface) {
setDivingState (false);
lastTimeSurfaceReachedFromMovingInput = Time.time;
reachingSurfaceFromMovingInput = true;
}
} else {
if (currentlyOnSurface && movingUp) {
mainPlayerController.setCurrentIdleIDValueFloat (movingUpStateID);
checkingDivingDirection = true;
}
}
}
} else {
if (currentlyDiving) {
if (checkingDivingDirection) {
updateCurrentStateIDValue ();
}
}
checkingDivingDirection = false;
}
}
currentAimSpeedMultipler = 1;
if (!isPlayerOnFirstPerson && mainPlayerController.isPlayerAiming ()) {
currentAimSpeedMultipler = swimSpeedOnAimMultiplier;
if (!turnAndForwardAnimatorValuesPaused) {
mainPlayerController.setTurnAndForwardAnimatorValuesPausedState (true);
turnAndForwardAnimatorValuesPaused = true;
}
} else {
if (turnAndForwardAnimatorValuesPaused) {
mainPlayerController.setTurnAndForwardAnimatorValuesPausedState (false);
turnAndForwardAnimatorValuesPaused = false;
}
}
totalForce = (swimForce * currentAimSpeedMultipler) * targetDirection;
if (movingUp) {
totalForce += swimMoveUpSpeed * playerTransform.up;
playerIsMoving = true;
}
if (movingDown) {
totalForce -= swimMoveDownSpeed * playerTransform.up;
playerIsMoving = true;
}
extraForce = Vector3.zero;
if (currentlyOnSurface) {
if (setMovementToSurfaceOnEnterWaterActive) {
if (Time.time < lastTimeSwimActive + 1) {
if (!swimForcesPaused) {
mainRigidbody.linearVelocity = Vector3.MoveTowards (mainRigidbody.linearVelocity, Vector3.zero, Time.deltaTime * 10);
}
} else {
setMovementToSurfaceOnEnterWaterActive = false;
}
} else {
if (currentDistanceToSurface < autoAdjustDistanceToSwimSurface) {
extraForce = autoAdjustDistanceToSwimSurfaceSpeed * (-playerTransform.up);
} else {
if (Time.time > lastTimeSwimActive + 3) {
if (currentDistanceToSurface > autoAdjustDistanceToSwimSurface + 0.2f) {
extraForce = autoAdjustDistanceToSwimSurfaceSpeed * playerTransform.up;
}
}
}
}
}
if (playerIsMoving) {
totalForce += extraForce;
if (turboActive) {
totalForce *= swimTurboSpeed;
}
velocityMagnitude = totalForce.magnitude;
if (velocityMagnitude > maxSwimVelocity) {
totalForce = Vector3.ClampMagnitude (totalForce, maxSwimVelocity);
}
velocityMagnitude = totalForce.magnitude;
if (!swimForcesPaused) {
if (isPlayerOnFirstPerson) {
totalForce *= firstPersonSpeedMultiplier;
}
if (useForceMode) {
mainRigidbody.AddForce (totalForce, swimForceMode);
} else {
mainRigidbody.AddForce (totalForce);
}
}
// print ("MOVING " + totalForce);
} else {
velocityMagnitude = mainRigidbody.linearVelocity.magnitude;
if (velocityMagnitude > 0) {
totalForce = (-1 * waterFriction) * mainRigidbody.linearVelocity;
// print ("using water friction");
}
totalForce += extraForce;
if (!swimForcesPaused) {
if (isPlayerOnFirstPerson) {
totalForce *= firstPersonSpeedMultiplier;
}
mainRigidbody.AddForce (totalForce, swimForceMode);
}
// print ("NOT MOVING " + totalForce);
}
if (reachingSurfaceFromMovingInput) {
if (Time.time > lastTimeSurfaceReachedFromMovingInput + delayToResetVelocityWhenReachingSurfaceFromMovingInput) {
mainPlayerController.setPlayerVelocityToZero ();
reachingSurfaceFromMovingInput = false;
}
}
}
void checkIfGroundDetectedOnSwimActiveState ()
{
if (currentDistanceToSurface < maxDistanceToWalkOnWater) {
if (Physics.Raycast (playerTransform.position + (0.05f * playerTransform.up), -playerTransform.up, groundDetectionRaycastDistanceOnWater, layerForGroundDetection)) {
lastTimeWalkingOnWaterActive = Time.time;
enteringOnWaterFromWalking = true;
walkingOnWater = true;
if (useEventOnWalkingOnWater) {
eventOnWalkingOnWater.Invoke ();
}
enableOrDisableSwimState (false);
}
}
if (!walkingOnWater && checkGroundDistanceOnSwimOnSurface) {
if (currentDistanceToSurface < 2) {
if (Physics.Raycast (playerTransform.position + (0.05f * playerTransform.up), -playerTransform.up, raycastDistanceToCheckOnSwimOnSurface, layerForGroundDetection)) {
if (swimCollider.enabled) {
swimCollider.enabled = false;
}
} else {
if (!swimCollider.enabled) {
swimCollider.enabled = true;
}
}
}
}
}
public void stopCheckIfPlayerNotOnVehicleCoroutine ()
{
if (checkIfPlayerNotOnVehicleCoroutine != null) {
StopCoroutine (checkIfPlayerNotOnVehicleCoroutine);
}
}
IEnumerator updateCheckIfPlayerNotOnVehicleCoroutine ()
{
var waitTime = new WaitForSecondsRealtime (0.00001f);
while (true) {
if (!mainPlayerController.isMovingInsideVehicle ()) {
if (currentSwimTriggerLocated) {
setSwimSystemActivestate (true);
}
checkingIfPlayerNotMovingInsideVehicleActive = false;
stopCheckIfPlayerNotOnVehicleCoroutine ();
}
yield return waitTime;
}
}
public void setSwimSystemActivestate (bool state)
{
if (!swimSystemEnabled) {
if (showDebugPrint) {
print ("swim system not eanbled, cancelling");
}
return;
}
if (checkIfPlayerIsOnWaterInsideVehicles) {
if (checkingIfPlayerNotMovingInsideVehicleActive) {
stopCheckIfPlayerNotOnVehicleCoroutine ();
checkingIfPlayerNotMovingInsideVehicleActive = false;
}
}
if (state && mainPlayerController.isMovingInsideVehicle ()) {
if (showDebugPrint) {
print ("moving inside vehicle, cancelling");
}
if (checkIfPlayerIsOnWaterInsideVehicles) {
checkingIfPlayerNotMovingInsideVehicleActive = true;
checkIfPlayerNotOnVehicleCoroutine = StartCoroutine (updateCheckIfPlayerNotOnVehicleCoroutine ());
}
return;
}
if (swimSystemActive == state) {
if (showDebugPrint) {
print ("setting same swim state, cancelling");
}
return;
}
if (state && mainPlayerController.isPlayerDead ()) {
if (showDebugPrint) {
print ("character is dead, cancelling");
}
return;
}
if (state) {
externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
if (currentExternalControllerBehavior != null && currentExternalControllerBehavior != this) {
if (canBeActivatedIfOthersBehaviorsActive && checkIfCanEnableBehavior (currentExternalControllerBehavior.behaviorName)) {
currentExternalControllerBehavior.disableExternalControllerState ();
} else {
if (showDebugPrint) {
print ("can't enable external controller, cancelling");
}
return;
}
}
}
bool swimModeActivePrevioulsy = swimSystemActive;
swimSystemActive = state;
mainPlayerController.removeJumpInputState ();
setBehaviorCurrentlyActiveState (state);
setCurrentPlayerActionSystemCustomActionCategoryID ();
if (swimSystemActive) {
mainPlayerController.setExternalControllerBehavior (this);
} else {
if (swimModeActivePrevioulsy) {
externalControllerBehavior currentExternalControllerBehavior = mainPlayerController.getCurrentExternalControllerBehavior ();
if (currentExternalControllerBehavior == null || currentExternalControllerBehavior == this) {
mainPlayerController.setExternalControllerBehavior (null);
}
}
}
bool canSetSwimState = true;
walkingOnWater = false;
setMovementToSurfaceOnEnterWaterActive = false;
if (state) {
if (Physics.Raycast (playerTransform.position, -playerTransform.up, groundDetectionRaycastDistance, layerForGroundDetection)) {
canSetSwimState = false;
walkingOnWater = true;
if (useEventOnWalkingOnWater) {
eventOnWalkingOnWater.Invoke ();
}
}
} else {
canSetSwimState = true;
}
if (canSetSwimState) {
enableOrDisableSwimState (state);
}
if (swimSystemActive) {
Physics.IgnoreCollision (mainPlayerCollider, swimCollider, true);
mainPlayerController.setIgnoreCollisionOnExternalColliderOnlyWithExtraColliderList (swimCollider, true);
}
swimCollider.enabled = state;
bool isFirstPersonActive = mainPlayerController.isPlayerOnFirstPerson ();
if (setNewCameraStateOnThirdPerson && !isFirstPersonActive && mainPlayerCamera != null) {
if (state) {
previousCameraState = mainPlayerCamera.getCurrentStateName ();
mainPlayerCamera.setCameraStateOnlyOnThirdPerson (newCameraStateOnThirdPerson);
} else {
if (previousCameraState != "") {
if (returnToPreviuosViewOnSwimEnd) {
if (previousCameraState != newCameraStateOnThirdPerson) {
mainPlayerCamera.setCameraStateOnlyOnThirdPerson (previousCameraState);
}
}
previousCameraState = "";
}
}
}
if (state) {
firstPersonChecked = isFirstPersonActive;
thirdPersonChecked = !isFirstPersonActive;
} else {
swimForcesPaused = false;
firstPersonChecked = false;
thirdPersonChecked = false;
}
if (showDebugPrint) {
print ("setSwimSystemActivestate " + state);
}
}
void enableOrDisableSwimState (bool state)
{
if (state) {
eventBeforeActivatingSwimSystem.Invoke ();
} else {
eventBeforeDeactivatingSwimSystem.Invoke ();
}
mainPlayerController.enableOrDisableSwimMode (state);
if (!state) {
mainPlayerController.setLastTimeFalling ();
}
if (state) {
mainPlayerController.setCurrentAirIDValue (swimID);
mainPlayerController.setOnGroundAnimatorIDValue (false);
mainPlayerController.setPreviousValueOnGroundAnimatorStateValue (false);
} else {
mainPlayerController.setCurrentAirIDValue (regularID);
mainPlayerController.setCurrentAirSpeedValue (1);
}
if (swimSystemActive) {
eventOnStateEnabled.Invoke ();
if (mainHeadTrack != null) {
mainHeadTrack.setSmoothHeadTrackDisableState (true);
}
} else {
eventOnStateDisabled.Invoke ();
if (turboActive) {
enableOrDisableTurbo (false);
}
enableOrDisableVerticalMovementUp (false);
enableOrDisableVerticalMovementDown (false);
if (mainHeadTrack != null) {
mainHeadTrack.setSmoothHeadTrackDisableState (false);
}
}
mainPlayerController.stopShakeCamera ();
movingUp = false;
movingDown = false;
if (currentlyDiving) {
setDivingState (false);
}
if (swimSystemActive) {
bool checkIfDivingState = true;
float lastTimeResurrect = mainPlayerController.getLastTimeResurrect ();
bool ignoreDivingCheck = false;
if (lastTimeResurrect > 0 && Time.time < lastTimeResurrect + 3f) {
enteringOnWaterFromWalking = false;
ignoreDivingCheck = true;
}
currentDistanceToSurface = Mathf.Abs (playerTransform.InverseTransformPoint (currentSwimZoneTransform.position).y);
float verticalSpeed = playerTransform.InverseTransformDirection (mainRigidbody.linearVelocity).y;
if (currentDistanceToSurface > 2 && Mathf.Abs (verticalSpeed) < 1) {
enteringOnWaterFromWalking = false;
ignoreDivingCheck = true;
if (showDebugPrint) {
print ("entering on deep water on low speed, setting dive state");
}
}
if (enteringOnWaterFromWalking) {
overridingMovementToSurfaceActive = false;
checkIfCloseToSurface = false;
setDivingState (false);
checkIfDivingState = false;
if (showDebugPrint) {
print ("entering on water while walking");
}
}
bool checkSurfaceOnEnterWaterResult = false;
if (setInitialStateOnSurfaceOnEnterWater) {
if (checkIfDivingState && !ignoreDivingCheck) {
if (useMaxSpeedToMoveToSurfaceOnSwimEnabled) {
verticalSpeed = playerTransform.InverseTransformDirection (mainRigidbody.linearVelocity).y;
float distanceToSurfaceWithSign = playerTransform.InverseTransformPoint (currentSwimZoneTransform.position).y;
if (showDebugPrint) {
print (distanceToSurfaceWithSign);
}
currentDistanceToSurface = Mathf.Abs (distanceToSurfaceWithSign);
if (showDebugPrint) {
print ("vertical speed " + verticalSpeed);
}
checkSurfaceOnEnterWaterResult = true;
if (Mathf.Abs (verticalSpeed) < minSpeedToSetSwimOnSurfaceState && currentDistanceToSurface < 5) {
overridingMovementToSurfaceActive = false;
checkIfCloseToSurface = false;
setDivingState (false);
checkIfDivingState = false;
if (showDebugPrint) {
print ("starting on suface " + verticalSpeed);
}
setMovementToSurfaceOnEnterWaterActive = true;
} else {
if (Mathf.Abs (verticalSpeed) < maxSpeedToMoveToSurfaceOnSwimEnabled &&
currentDistanceToSurface < 5) {
if (showDebugPrint) {
print ("return to surface");
}
checkingToActivateMovementToSurfaceAutomaticallyActive = true;
overridingMovementToSurfaceActive = true;
enableOrDisableVerticalMovementUp (true);
checkIfDivingState = false;
}
}
}
}
}
if (checkIfDivingState) {
verticalSpeed = playerTransform.InverseTransformDirection (mainRigidbody.linearVelocity).y;
if (showDebugPrint) {
print ("checkIfDivingState result " + checkIfDivingState + " " + verticalSpeed);
}
if (Mathf.Abs (verticalSpeed) > maxSpeedToMoveToSurfaceOnSwimEnabled || !checkSurfaceOnEnterWaterResult) {
setDivingState (true);
if (showDebugPrint) {
print ("setting diving state");
}
} else {
currentDistanceToSurface = Mathf.Abs (playerTransform.InverseTransformPoint (currentSwimZoneTransform.position).y);
if (currentDistanceToSurface > 3) {
setDivingState (true);
if (showDebugPrint) {
print ("setting diving state");
}
}
}
}
lastTimeSwimActive = Time.time;
} else {
if (overridingMovementToSurfaceActive) {
playerInput.overrideInputValues (Vector3.zero, false);
}
overridingMovementToSurfaceActive = false;
currentlyOnSurface = false;
}
if (turnAndForwardAnimatorValuesPaused) {
mainPlayerController.setTurnAndForwardAnimatorValuesPausedState (false);
turnAndForwardAnimatorValuesPaused = false;
}
updateCurrentStateIDValue ();
enteringOnWaterFromWalking = false;
if (!swimSystemActive) {
if (useEventOnCameraUnderwaterEffect) {
if (cameraBelowWater) {
if (!ignoreDisableCameraBelowWaterStateActive) {
eventOnCameraUnderWaterEnd.Invoke ();
cameraBelowWater = false;
}
}
}
}
ignoreDisableCameraBelowWaterStateActive = false;
mainPlayerController.setFootStepManagerState (state);
setExtraCharacterStateOnSwim (state);
}
public void enableOrDisableTurbo (bool state)
{
if (turboActive == state) {
return;
}
if (state && canUseTurboPausedState) {
return;
}
turboActive = state;
mainPlayerController.enableOrDisableFlyModeTurbo (turboActive);
if (turboActive) {
mainPlayerController.setCurrentAirSpeedValue (2);
} else {
mainPlayerController.setCurrentAirSpeedValue (1);
}
if (useEventUseTurboOnSwim) {
if (state) {
eventOnStarTurboOnSwim.Invoke ();
} else {
eventOnEndTurboOnSwim.Invoke ();
}
}
}
public void setCanUseTurboPausedState (bool state)
{
if (!state && turboActive) {
enableOrDisableTurbo (false);
}
canUseTurboPausedState = state;
}
public override void disableExternalControllerState ()
{
bool disableSwimStateResult = true;
if (keepSwimStateActiveOnDeath) {
// print (mainPlayerController.checkIfPlayerDeadFromHealthComponent ());
if (mainPlayerController.checkIfPlayerDeadFromHealthComponent ()) {
disableSwimStateResult = false;
}
}
if (disableSwimStateResult) {
setSwimSystemActivestate (false);
}
}
public void inputChangeTurboState (bool state)
{
if (overridingMovementToSurfaceActive) {
return;
}
if (swimSystemActive && turboEnabled) {
enableOrDisableTurbo (state);
}
}
public void inputMoveUp (bool state)
{
if (overridingMovementToSurfaceActive) {
return;
}
if (swimSystemActive && moveUpAndDownEnabled) {
if (currentlyOnSurface && state) {
if (canJumpWhenSwimmingOnSurface) {
bool activateRegularJump = true;
bool surfaceToLedgeDetected = false;
if (onlyClimbOnCloseSurfaces) {
Vector3 raycastPosition = playerTransform.position + (1.5f * playerTransform.up);
Vector3 raycastDirection = playerTransform.forward;
Vector3 climbSurfaceTargetPosition = Vector3.zero;
RaycastHit hit = new RaycastHit ();
if (Physics.Raycast (raycastPosition, raycastDirection, out hit, 0.5f, layerForGroundDetection)) {
float angleWithSurface = Vector3.SignedAngle (playerTransform.up, hit.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 (!surfaceAngleNotValid) {
//if not surface is found, then
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 ();
int numberOfLoops = 0;
Vector3 newRaycastPosition = raycastPosition;
while (!surfaceToLedgeDetected && numberOfLoops < 100) {
Debug.DrawRay (newRaycastPosition, raycastDirection, Color.blue, 4);
if (Physics.Raycast (newRaycastPosition, raycastDirection, out newHit, 2, layerForGroundDetection)) {
hit = newHit;
newRaycastPosition += 0.04f * playerTransform.up;
} else {
climbSurfaceTargetPosition = hit.point + 0.04f * playerTransform.up;
surfaceToLedgeDetected = true;
}
numberOfLoops++;
}
if (GKC_Utils.distance (raycastPosition, climbSurfaceTargetPosition) > maxClimbSurfaceHeight) {
surfaceToLedgeDetected = false;
if (showDebugPrint) {
print ("surface to climb detected too far away");
}
}
if (surfaceToLedgeDetected) {
climbSurfaceActionSystemTransform.position = climbSurfaceTargetPosition;
climbSurfaceActionSystemTransform.rotation = Quaternion.LookRotation (-hit.normal);
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 (showDebugPrint) {
print ("surface to climb not detected");
}
}
if (surfaceToLedgeDetected) {
activateRegularJump = false;
} else {
if (!allowJumpOnSwimIfNoCloseSurfaceToClimbFound) {
activateRegularJump = false;
}
}
}
if (activateRegularJump) {
mainPlayerController.useJumpPlatform (jumpForceOnSurface * playerTransform.up, ForceMode.Impulse);
return;
}
}
}
enableOrDisableVerticalMovementUp (state);
}
}
public void inputMoveDown (bool state)
{
if (overridingMovementToSurfaceActive) {
return;
}
if (swimSystemActive && moveUpAndDownEnabled) {
enableOrDisableVerticalMovementDown (state);
if (!currentlyDiving) {
setDivingState (true);
}
}
}
void enableOrDisableVerticalMovementUp (bool state)
{
if (movingUp && !state) {
playerInput.overrideInputValues (Vector3.zero, false);
}
movingUp = state;
if (movingUp) {
checkIfLookingInCameraDirection ();
movingDown = false;
}
updateCurrentStateIDValue ();
}
void enableOrDisableVerticalMovementDown (bool state)
{
if (movingDown && !state) {
playerInput.overrideInputValues (Vector3.zero, false);
}
movingDown = state;
if (movingDown) {
checkIfLookingInCameraDirection ();
movingUp = false;
}
updateCurrentStateIDValue ();
}
void checkIfLookingInCameraDirection ()
{
float angleWithCamera = Vector3.Angle (playerTransform.forward, playerCameraTransform.forward);
if (angleWithCamera < 90) {
lookingInCameraDirection = true;
} else {
lookingInCameraDirection = false;
}
if (showDebugPrint) {
print (angleWithCamera + " " + lookingInCameraDirection);
}
}
public void setSwimZoneTransform (Transform newSwimZoneTransform)
{
currentSwimZoneTransform = newSwimZoneTransform;
}
public void setSwimTrigger (Collider newSwimTrigger)
{
currentSwimTrigger = newSwimTrigger;
currentSwimTriggerLocated = currentSwimTrigger != null;
}
public bool isSwimTriggerListEmpty ()
{
if (swimTriggerList.Count > 0) {
return false;
}
return true;
}
public void addSwimTrigger (Collider newTrigger)
{
if (newTrigger == null) {
return;
}
if (!swimTriggerList.Contains (newTrigger)) {
swimTriggerList.Add (newTrigger);
}
}
public void removeSwimTrigger (Collider newTrigger)
{
if (newTrigger == null) {
return;
}
if (swimTriggerList.Contains (newTrigger)) {
swimTriggerList.Remove (newTrigger);
}
}
public void clearSwimTriggerList ()
{
if (swimTriggerList.Count > 0) {
swimTriggerList.Clear ();
}
}
public void setCurrentWaterSurfaceSystem (waterSurfaceSystem newWaterSurfaceSystem)
{
currentWaterSurfaceSystem = newWaterSurfaceSystem;
updateSurfaceTransformDynamically = currentWaterSurfaceSystem != null;
}
public void setDivingState (bool state)
{
bool previouslyDiving = currentlyDiving;
currentlyDiving = state;
currentlyOnSurface = !currentlyDiving;
if (useEventsOnDiveStateChange) {
if (currentlyDiving) {
eventOnStartDive.Invoke ();
} else {
eventOnEndDive.Invoke ();
}
}
updateCurrentStateIDValue ();
if (showDebugPrint) {
print ("setting diving state as " + currentlyDiving + " is character on surface " + currentlyOnSurface);
}
reachingSurfaceFromMovingInput = false;
if (swimSystemActive) {
if (previouslyDiving) {
if (currentlyOnSurface) {
if (useEventOnChangeDiveToSwim) {
eventOnChangeDiveToSwim.Invoke ();
}
}
} else {
if (currentlyDiving) {
if (useEventOnChangeSwimToDive) {
eventOnChangeSwimToDive.Invoke ();
}
}
}
}
}
void updateCurrentStateIDValue ()
{
currentStatID = -1;
if (swimSystemActive) {
if (currentlyDiving) {
if (movingUp) {
currentStatID = movingUpStateID;
} else if (movingDown) {
currentStatID = movingDownStateID;
} else {
currentStatID = diveStateID;
}
}
if (currentlyOnSurface) {
currentStatID = swimStateID;
}
if (walkingOnWater) {
currentStatID = regularIdleID;
}
} else {
currentStatID = regularIdleID;
}
mainPlayerController.setCurrentIdleIDValueFloat (currentStatID);
}
public void setEnableExternalForceOnSwimModeState (bool state)
{
if (swimSystemActive) {
mainPlayerController.setEnableExternalForceOnSwimModeState (state);
}
}
public override void checkPauseStateDuringExternalForceOrBehavior ()
{
swimForcesPaused = true;
}
public override void checkResumeStateAfterExternalForceOrBehavior ()
{
if (swimSystemActive) {
setCurrentPlayerActionSystemCustomActionCategoryID ();
swimForcesPaused = false;
}
}
public override void setCurrentPlayerActionSystemCustomActionCategoryID ()
{
if (behaviorCurrentlyActive) {
if (customActionCategoryID > -1) {
mainPlayerController.setCurrentCustomActionCategoryID (customActionCategoryID);
}
} else {
if (regularActionCategoryID > -1) {
mainPlayerController.setCurrentCustomActionCategoryID (regularActionCategoryID);
}
}
}
}