// Amplify Animation Pack - Third-Person Character Controller // Copyright (c) Amplify Creations, Lda using UnityEngine; namespace AmplifyAnimationPack { public class GroundedState : CharacterStateBase { // input variables private float inputRight; private float inputUp; private float movementAxisInputs; // target variables private Vector3 targetDirection; private Quaternion targetRotation; private Vector3 targetDir2D; private Vector3 characterFwd2D; // ray variables for raycasts private Ray detectionRay; private RaycastHit detectionRayHit; // bump variables private float currTimeToBump; // lean variables private float newLeanAmount; private float finalLeanAmount; private Quaternion finalLeanRot; private float currentLeanLimit; public override void EnterState() { // setup components charRef.ChangeCollider( CharacterColliderTypes.baseCol ); charRef.baseColl.enabled = true; charRef.LerpCapsuleRadius( 0.5f , 0.2f ); charRef.rigid.interpolation = RigidbodyInterpolation.None; charRef.rigid.velocity = Vector3.zero; charRef.rigid.useGravity = true; charRef.hitbox.SetActive( false ); charRef.uiManager.PlaygroundText_Enable(); charRef.canMove = true; charRef.ChangeMovementMode( CharacterMovementModes.animationBased ); charRef.ChangeMovementType( CharacterMovementTypes.idle ); charRef.ChangeAttackAction( CharacterCombatActions.none ); charRef.currRotAmount = charRef.idleRotAmount; charRef.targetHeadMarkerPos = charRef.idleHeadMarkerPos; charRef.cameraTargetOffset = Vector3.zero; } public override void ExitState() { charRef.meshTransf.rotation = Quaternion.Euler( charRef.meshTransf.eulerAngles.x , charRef.meshTransf.eulerAngles.y , 0f ); charRef.targetHeadMarkerPos = charRef.idleHeadMarkerPos; charRef.transf.rotation = charRef.transf.rotation; charRef.cameraTargetOffset = Vector3.zero; charRef.SetCameraShakeAmplitude( 0f ); charRef.uiManager.PlaygroundText_Disable(); } public override void UpdateState() { charRef.CheckIsGrounded(); DetectObjectToInteract(); DetectClimbDown(); // calculates speed movementAxisInputs = Mathf.Abs( inputRight ) + Mathf.Abs( inputUp ); movementAxisInputs = Mathf.Clamp( movementAxisInputs , 0f , 1f ); charRef.animBeh.anim.SetFloat( "Speed" , movementAxisInputs ); if( movementAxisInputs != 0f ) { // set target values targetDirection = charRef.GetFollowCamTransform().GetChild( 0 ).forward * inputUp + charRef.GetFollowCamTransform().GetChild( 0 ).right * inputRight; targetRotation = Quaternion.Euler( charRef.transf.eulerAngles.x , Quaternion.LookRotation( targetDirection ).eulerAngles.y , charRef.transf.rotation.eulerAngles.z ); targetDir2D = new Vector3( targetDirection.x , 0f , targetDirection.z ); characterFwd2D = new Vector3( charRef.transf.forward.x , 0f , charRef.transf.forward.z ); // update animator values charRef.animBeh.anim.SetFloat( "TimeToStop" , 0f ); charRef.animBeh.anim.SetFloat( "TargetDir" , Vector3.Angle( characterFwd2D , targetDir2D ) ); if( charRef.isLocked ) { if( charRef.canMove ) { charRef.animBeh.anim.SetFloat( "InputRight" , Mathf.Lerp( charRef.animBeh.anim.GetFloat( "InputRight" ) , inputRight , 0.2f ) ); charRef.animBeh.anim.SetFloat( "InputFwd" , Mathf.Lerp( charRef.animBeh.anim.GetFloat( "InputFwd" ) , inputUp , 0.2f ) ); RotateCharToEnemy(); } } else { charRef.animBeh.anim.SetFloat( "InputRight" , inputRight ); charRef.animBeh.anim.SetFloat( "InputFwd" , inputUp ); if( charRef.canMove ) { charRef.ChangeLocomotionType( ( charRef.isLockedToWalking ) ? CharacterLocomotionTypes.walking : CharacterLocomotionTypes.running ); // when not turning around if( charRef.animBeh.anim.GetFloat( "TargetDir" ) < 135f ) { // rotate the character charRef.transf.rotation = Quaternion.RotateTowards( charRef.transf.rotation , targetRotation , charRef.currRotAmount ); } // detect obstacles ObstacleDetection(); } } } else { // stops the character if( charRef.canMove ) { if( !charRef.isLocked ) { charRef.ChangeLocomotionType( CharacterLocomotionTypes.stopped ); } else { RotateCharToEnemy(); } charRef.animBeh.anim.SetFloat( "TimeToStop" , Mathf.Min( charRef.animBeh.anim.GetFloat( "TimeToStop" ) + Time.deltaTime , 1f ) ); } } // calculates the amount to lean to based on direction CalculateLeaningAmount(); } public override void LateUpdateState() { ApplyLeaning(); } public override void InputMoveForward( float _axisVal ) { inputUp = _axisVal; } public override void InputMoveRight( float _axisVal ) { inputRight = _axisVal; } public override void InputSprint( bool _actionVal ) { if( charRef.canMove ) { if( _actionVal && movementAxisInputs > 0f ) { if( charRef.currMovementType == CharacterMovementTypes.idle ) { charRef.ChangeMovementType( CharacterMovementTypes.sprint ); charRef.currRotAmount = charRef.sprintRotAmount; charRef.SetCameraShakeAmplitude( 0.4f ); charRef.SetCameraShakeFrequency( 4f ); charRef.cameraTargetOffset = new Vector3( 0f , 0f , charRef.sprintTargetOffsetAmount ); } } else { if( charRef.currMovementType == CharacterMovementTypes.sprint ) { charRef.ChangeMovementType( CharacterMovementTypes.idle ); charRef.currRotAmount = charRef.idleRotAmount; charRef.SetCameraShakeAmplitude( 0f ); charRef.cameraTargetOffset = Vector3.zero; } } } } public override void InputCrouch( bool _actionVal ) { if( charRef.canMove ) { if( _actionVal ) { if( charRef.currMovementType == CharacterMovementTypes.idle ) { charRef.targetHeadMarkerPos = charRef.crouchHeadMarkerPos; charRef.ChangeMovementType( CharacterMovementTypes.crouch ); charRef.ChangeCollider( CharacterColliderTypes.crouchCol ); charRef.currRotAmount = charRef.crouchRotAmount; charRef.cameraTargetOffset = new Vector3( 0f , 0f , charRef.crouchTargetOffsetAmount ); } } else { if( charRef.currMovementType == CharacterMovementTypes.crouch ) { charRef.targetHeadMarkerPos = charRef.idleHeadMarkerPos; charRef.ChangeMovementType( CharacterMovementTypes.idle ); charRef.ChangeCollider( CharacterColliderTypes.baseCol ); charRef.currRotAmount = charRef.idleRotAmount; charRef.cameraTargetOffset = Vector3.zero; } } } } public override void InputJump( bool _actionVal ) { if( _actionVal ) { if( charRef.canMove ) { if( charRef.currMovementType == CharacterMovementTypes.crouch ) { charRef.ChangeState(); } else { charRef.ChangeState(); } } } } public override void InputInteract( bool _actionVal ) { if( _actionVal ) { if( charRef.canMove ) { if( charRef.objToInteract != null ) { charRef.objToInteract.Interact( charRef ); } } } } public override void InputAttack( bool _actionVal , CharacterCombatActions _newAttack ) { if( _actionVal ) { if( charRef.canMove ) { charRef.ChangeAttackAction( ( !charRef.objectCaught ) ? _newAttack : CharacterCombatActions.throwObject ); charRef.ChangeState(); } } } public override void InputDodge( bool _actionVal ) { if( _actionVal ) { if( charRef.canMove ) { if( charRef.isLocked ) { charRef.ChangeState(); } else { charRef.ChangeState(); } } } } public override void InputLockOn( bool _actionVal ) { if( _actionVal ) { if( charRef.canMove ) { charRef.TriggerLockOn(); } } } private void ObstacleDetection() { detectionRay = new Ray( charRef.transf.position - Vector3.up * 0.5f , charRef.transf.forward ); if( Physics.Raycast( detectionRay , out detectionRayHit , 1.7f ) ) { if( charRef.currMovementType != CharacterMovementTypes.crouch ) { if( detectionRayHit.collider.gameObject.GetComponent() ) { charRef.ChangeState(); } else { currTimeToBump += Time.deltaTime; if( currTimeToBump >= charRef.bumpDelay ) { charRef.ChangeState(); } } } } else { currTimeToBump = 0f; } } private void CalculateLeaningAmount() { if( charRef.canMove && movementAxisInputs != 0f ) { newLeanAmount = Vector3.SignedAngle( characterFwd2D , targetDir2D , Vector3.up ) / 135f * 90f; newLeanAmount = Mathf.Round( newLeanAmount * 100f ) / 100f; currentLeanLimit = ( charRef.currMovementType == CharacterMovementTypes.sprint ) ? charRef.leanLimitSprint : charRef.leanLimitDefault; newLeanAmount = Mathf.Clamp( newLeanAmount , -currentLeanLimit , currentLeanLimit ); finalLeanAmount = Mathf.Lerp( finalLeanAmount , newLeanAmount , 0.2f ); } else { newLeanAmount = 0f; finalLeanAmount = Mathf.Lerp( finalLeanAmount , newLeanAmount , 0.2f ); } } private void ApplyLeaning() { if( !charRef.isLocked ) { finalLeanRot = Quaternion.Euler( charRef.meshTransf.eulerAngles.x , charRef.meshTransf.eulerAngles.y , -finalLeanAmount ); charRef.meshTransf.rotation = finalLeanRot; } } private void RotateCharToEnemy() { targetRotation = Quaternion.Euler( charRef.transf.eulerAngles.x , Quaternion.LookRotation( charRef.lockOnTarget.transform.position - charRef.transf.position ).eulerAngles.y , charRef.transf.rotation.eulerAngles.z ); charRef.transf.rotation = Quaternion.RotateTowards( charRef.transf.rotation , targetRotation , 7f ); } private void DetectObjectToInteract() { detectionRay = new Ray( charRef.transf.position , charRef.transf.forward ); if( Physics.Raycast( detectionRay , out detectionRayHit , 0.7f ) ) { charRef.objToInteractRotationVector = detectionRayHit.normal; charRef.objToInteractContactPoint = detectionRayHit.point; if( charRef.objToInteract == null ) { if( detectionRayHit.collider.gameObject != null ) { if( detectionRayHit.collider.gameObject.GetComponent() ) { charRef.objToInteract = detectionRayHit.collider.gameObject.GetComponent(); charRef.uiManager.InteractionText_Enable( "Press E to Climb" ); } else if( detectionRayHit.collider.gameObject.GetComponent() ) { charRef.objToInteract = detectionRayHit.collider.gameObject.GetComponent(); charRef.uiManager.InteractionText_Enable( "Press E to Enter cover" ); } else if( detectionRayHit.collider.gameObject.GetComponent() ) { charRef.objToInteract = detectionRayHit.collider.gameObject.GetComponent(); charRef.uiManager.InteractionText_Enable( "Press E to Push" ); } } } } else { if( charRef.objToInteract != null ) { if( charRef.objToInteract is ClimbObjectClass || charRef.objToInteract is CoverObjectClass || charRef.objToInteract is PushObjectClass ) { charRef.objToInteract = null; charRef.uiManager.InteractionText_Disable(); } } } } private void DetectClimbDown() { detectionRay = new Ray( charRef.transf.position , -charRef.transf.up ); if( Physics.SphereCast( detectionRay , 0.2f , out detectionRayHit , 1f ) ) { if( charRef.objToInteract == null ) { if( detectionRayHit.collider.gameObject.GetComponent() ) { charRef.objToInteract = detectionRayHit.collider.gameObject.GetComponent(); charRef.uiManager.InteractionText_Enable( "Press E to Climb down" ); } } } else if( charRef.objToInteract is WallPointClass ) { charRef.objToInteract = null; charRef.uiManager.InteractionText_Disable(); } } } }