Files
beyond/Assets/ThirdParty/Invector-3rdPersonController/Basic Locomotion/Scripts/CharacterController/vThirdPersonController.cs
2024-11-20 15:21:28 +01:00

365 lines
12 KiB
C#

using System.Collections;
using System.Collections;
using UnityEngine;
namespace Invector.vCharacterController
{
[vClassHeader("THIRD PERSON CONTROLLER", iconName = "controllerIcon")]
public class vThirdPersonController : vThirdPersonAnimator
{
/// <summary>
/// Move the controller to a specific Position, you must Lock the Input first
/// </summary>
/// <param name="targetPosition"></param>
public virtual void MoveToPosition(Transform targetPosition)
{
MoveToPosition(targetPosition.position);
}
/// <summary>
/// Move the controller to a specific Position, you must Lock the Input first
/// </summary>
/// <param name="targetPosition"></param>
public virtual void MoveToPosition(Vector3 targetPosition)
{
Vector3 dir = targetPosition - transform.position;
dir.y = 0;
/*dir = dir.normalized * Mathf.Min(1f, dir.magnitude);*/ /*That is to make smootly stop*/
if (dir.magnitude < 0.1f)
{
input = Vector3.zero;
moveDirection = Vector3.zero;
}
else
{
input = transform.InverseTransformDirection(dir.normalized);
moveDirection = dir.normalized;
}
}
/// <summary>
/// Handle RootMotion movement and specific Actions
/// </summary>
public virtual void ControlAnimatorRootMotion()
{
if (!this.enabled)
{
return;
}
if (isRolling)
{
RollBehavior();
return;
}
if (customAction || lockAnimMovement)
{
StopCharacterWithLerp();
transform.position = animator.rootPosition;
transform.rotation = animator.rootRotation;
}
// commented for test
//else if (inputSmooth.magnitude == 0 && isGrounded && !isSliding)
//{
// if (!ignoreAnimatorMovement)
// {
// animator.ApplyBuiltinRootMotion();
// transform.position = animator.rootPosition;
// transform.rotation = animator.rootRotation;
// }
//}
if (useRootMotion)
{
MoveCharacter(moveDirection);
}
}
/// <summary>
/// Set the Controller movement speed (rigidbody, animator and root motion)
/// </summary>
public virtual void ControlLocomotionType()
{
if (lockAnimMovement || lockMovement || customAction)
{
return;
}
if (!lockSetMoveSpeed)
{
if (locomotionType.Equals(LocomotionType.FreeWithStrafe) && !isStrafing || locomotionType.Equals(LocomotionType.OnlyFree))
{
SetControllerMoveSpeed(freeSpeed);
SetAnimatorMoveSpeed(freeSpeed);
}
else if (locomotionType.Equals(LocomotionType.OnlyStrafe) || locomotionType.Equals(LocomotionType.FreeWithStrafe) && isStrafing)
{
isStrafing = true;
SetControllerMoveSpeed(strafeSpeed);
SetAnimatorMoveSpeed(strafeSpeed);
}
}
if (!useRootMotion)
{
MoveCharacter(moveDirection);
}
}
/// <summary>
/// Manage the Control Rotation Type of the Player
/// </summary>
public virtual void ControlRotationType()
{
if (lockAnimRotation || lockRotation || customAction || isRolling)
{
return;
}
bool validInput = input != Vector3.zero || (isStrafing ? strafeSpeed.rotateWithCamera : freeSpeed.rotateWithCamera);
if (validInput)
{
if (lockAnimMovement)
{
// calculate input smooth
inputSmooth = Vector3.Lerp(inputSmooth, input, (isStrafing ? strafeSpeed.movementSmooth : freeSpeed.movementSmooth) * Time.deltaTime);
}
Vector3 dir = (isStrafing && isGrounded && (!isSprinting || sprintOnlyFree == false) || (freeSpeed.rotateWithCamera && input == Vector3.zero)) && rotateTarget ? rotateTarget.forward : moveDirection;
//RotationTest(dir);
RotateToDirection(dir);
}
}
/// <summary>
/// Use it to keep the direction the Player is moving (most used with CCV camera)
/// </summary>
public virtual void ControlKeepDirection()
{
// update oldInput to compare with current Input if keepDirection is true
if (!keepDirection)
{
oldInput = input;
}
else if ((input.magnitude < 0.01f || Vector3.Distance(oldInput, input) > 0.9f) && keepDirection)
{
keepDirection = false;
}
}
/// <summary>
/// Determine the direction the player will face based on input and the referenceTransform
/// </summary>
/// <param name="referenceTransform"></param>
public virtual void UpdateMoveDirection(Transform referenceTransform = null)
{
if (isRolling && !rollControl /*|| input.magnitude <= 0.01*/)
{
moveDirection = Vector3.Lerp(moveDirection, Vector3.zero, (isStrafing ? strafeSpeed.movementSmooth : freeSpeed.movementSmooth) * Time.deltaTime);
return;
}
if (referenceTransform && !rotateByWorld)
{
//get the right-facing direction of the referenceTransform
var right = referenceTransform.right;
right.y = 0;
//get the forward direction relative to referenceTransform Right
var forward = Quaternion.AngleAxis(-90, Vector3.up) * right;
// determine the direction the player will face based on input and the referenceTransform's right and forward directions
moveDirection = (inputSmooth.x * right) + (inputSmooth.z * forward);
}
else
{
moveDirection = new Vector3(inputSmooth.x, 0, inputSmooth.z);
}
}
/// <summary>
/// Set the isSprinting bool and manage the Sprint Behavior
/// </summary>
/// <param name="value"></param>
public virtual void Sprint(bool value)
{
// EM TESTE FORAM REMOVIDOS ALGUMAS CONDIÇÕES
//var sprintConditions = (currentStamina > 0 && hasMovementInput && isGrounded &&
// !(isStrafing && !strafeSpeed.walkByDefault && (horizontalSpeed >= 0.5 || horizontalSpeed <= -0.5 || verticalSpeed <= 0.1f) && !sprintOnlyFree));
var sprintConditions = (!isCrouching || (!inCrouchArea && CanExitCrouch())) && (currentStamina > 0 && hasMovementInput &&
!(isStrafing && (horizontalSpeed >= 0.5 || horizontalSpeed <= -0.5 || verticalSpeed <= 0.1f) && !sprintOnlyFree));
if (value && sprintConditions)
{
if (currentStamina > (finishStaminaOnSprint ? sprintStamina : 0) && hasMovementInput)
{
finishStaminaOnSprint = false;
if (isGrounded && useContinuousSprint)
{
isCrouching = false;
isSprinting = !isSprinting;
if (isSprinting)
{
OnStartSprinting.Invoke();
// TESTE PARA SAIR DO WALKONLY QUANDO SPRINTA
alwaysWalkByDefault = false;
}
else
{
OnFinishSprinting.Invoke();
}
}
else if (!isSprinting)
{
OnStartSprinting.Invoke();
// TESTE PARA SAIR DO WALKONLY QUANDO SPRINTA
alwaysWalkByDefault = false;
isSprinting = true;
}
}
else if (!useContinuousSprint && isSprinting)
{
if (currentStamina <= 0)
{
finishStaminaOnSprint = true;
OnFinishSprintingByStamina.Invoke();
}
isSprinting = false;
OnFinishSprinting.Invoke();
}
}
else if (isSprinting && (!useContinuousSprint || !sprintConditions))
{
if (currentStamina <= 0)
{
finishStaminaOnSprint = true;
OnFinishSprintingByStamina.Invoke();
}
isSprinting = false;
OnFinishSprinting.Invoke();
}
}
/// <summary>
/// Manage the isCrouching bool
/// </summary>
public virtual void Crouch()
{
if (isGrounded && !customAction)
{
AutoCrouch();
if (isCrouching && CanExitCrouch())
{
isCrouching = false;
}
else
{
isCrouching = true;
isSprinting = false;
}
}
}
/// <summary>
/// Set the isStrafing bool
/// </summary>
public virtual void Strafe()
{
isStrafing = !isStrafing;
}
/// <summary>
/// Triggers the Jump Animation and set the necessary variables to make the Jump behavior in the <seealso cref="vThirdPersonMotor"/>
/// </summary>
/// <param name="consumeStamina">Option to consume or not the stamina</param>
public virtual void Jump(bool consumeStamina = false)
{
// trigger jump behaviour
jumpCounter = jumpTimer;
OnJump.Invoke();
// trigger jump animations
if (input.sqrMagnitude < 0.1f)
{
StartCoroutine(DelayToJump());
animator.CrossFadeInFixedTime("Jump", 0.1f);
}
else
{
isJumping = true;
animator.CrossFadeInFixedTime("JumpMove", .2f);
}
// reduce stamina
if (consumeStamina)
{
ReduceStamina(jumpStamina, false);
currentStaminaRecoveryDelay = 1f;
}
}
protected IEnumerator DelayToJump()
{
yield return new WaitForSeconds(jumpStandingDelay);
isJumping = true;
}
/// <summary>
/// Triggers the Roll Animation and set the stamina cost for this action
/// </summary>
public virtual void Roll()
{
OnRoll.Invoke();
isRolling = true;
animator.CrossFadeInFixedTime("Roll", rollTransition, baseLayer);
ReduceStamina(rollStamina, false);
currentStaminaRecoveryDelay = 2f;
}
#region Check Action Triggers
/// <summary>
/// Call this in OnTriggerEnter or OnTriggerStay to check if enter in triggerActions
/// </summary>
/// <param name="other">collider trigger</param>
protected override void OnTriggerStay(Collider other)
{
try
{
CheckForAutoCrouch(other);
}
catch (UnityException e)
{
Debug.LogWarning(e.Message);
}
base.OnTriggerStay(other);
}
/// <summary>
/// Call this in OnTriggerExit to check if exit of triggerActions
/// </summary>
/// <param name="other"></param>
protected override void OnTriggerExit(Collider other)
{
AutoCrouchExit(other);
base.OnTriggerExit(other);
}
#endregion
public void Respawn()
{
currentHealth = maxHealth;
currentStamina = maxStamina;
animator.SetBool(vAnimatorParameters.IsDead, false);
}
}
}