using System.Collections; using System.Collections; using UnityEngine; namespace Invector.vCharacterController { [vClassHeader("THIRD PERSON CONTROLLER", iconName = "controllerIcon")] public class vThirdPersonController : vThirdPersonAnimator { /// /// Move the controller to a specific Position, you must Lock the Input first /// /// public virtual void MoveToPosition(Transform targetPosition) { MoveToPosition(targetPosition.position); } /// /// Move the controller to a specific Position, you must Lock the Input first /// /// 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; } } /// /// Handle RootMotion movement and specific Actions /// 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); } } /// /// Set the Controller movement speed (rigidbody, animator and root motion) /// 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); } } /// /// Manage the Control Rotation Type of the Player /// 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); } } /// /// Use it to keep the direction the Player is moving (most used with CCV camera) /// 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; } } /// /// Determine the direction the player will face based on input and the referenceTransform /// /// 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); } } /// /// Set the isSprinting bool and manage the Sprint Behavior /// /// 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(); } } /// /// Manage the isCrouching bool /// public virtual void Crouch() { if (isGrounded && !customAction) { AutoCrouch(); if (isCrouching && CanExitCrouch()) { isCrouching = false; } else { isCrouching = true; isSprinting = false; } } } /// /// Set the isStrafing bool /// public virtual void Strafe() { isStrafing = !isStrafing; } /// /// Triggers the Jump Animation and set the necessary variables to make the Jump behavior in the /// /// Option to consume or not the stamina 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; } /// /// Triggers the Roll Animation and set the stamina cost for this action /// public virtual void Roll() { OnRoll.Invoke(); isRolling = true; animator.CrossFadeInFixedTime("Roll", rollTransition, baseLayer); ReduceStamina(rollStamina, false); currentStaminaRecoveryDelay = 2f; } #region Check Action Triggers /// /// Call this in OnTriggerEnter or OnTriggerStay to check if enter in triggerActions /// /// collider trigger protected override void OnTriggerStay(Collider other) { try { CheckForAutoCrouch(other); } catch (UnityException e) { Debug.LogWarning(e.Message); } base.OnTriggerStay(other); } /// /// Call this in OnTriggerExit to check if exit of triggerActions /// /// protected override void OnTriggerExit(Collider other) { AutoCrouchExit(other); base.OnTriggerExit(other); } #endregion public void Respawn() { currentHealth = maxHealth; currentStamina = maxStamina; animator.SetBool(vAnimatorParameters.IsDead, false); } } }