/// <summary>
        /// (Called by KinematicCharacterMotor during its update cycle)
        /// This is called before the character begins its movement update
        /// </summary>
        public void BeforeCharacterUpdate(float deltaTime)
        {
            //Force deviation closer if too far away.
            if (currentDefaultState == PetDefaultState.Run || currentCrouchedState == PetCrouchedState.Walk)
            {
                if (!_forcingMovementTowardsPlayer && distanceToPlayer > Mathf.Pow(3f, 2) && angleComparison <= .7f &&
                    angleComparison >= -.7f)
                {
                    _forcingMovementTowardsPlayer = true;
                    currentDeviationState         = PetDeviationState.MoveCloser;
                    StopActiveCoroutine(ChangeDeviationDirectionCoroutine);
                    ForceDeviationChangeCoroutine = StartCoroutine(ForceDeviationChange());
                }
            }

            //Move straight to the player if outside the default radius.
            if (CurrentPetState == PetState.Default || CurrentPetState == PetState.Crouched)
            {
                //Debug.Log(playerDir.magnitude);
                if (playerDir.sqrMagnitude > Mathf.Pow(3.5f, 2f))
                {
                    TransitionToState(PetState.MoveStraightToPlayer);
                }
            }

            //Enable pathfinding if no line of sight is met after x amount of time.
            if (CurrentPetState == PetState.Default || CurrentPetState == PetState.Crouched ||
                CurrentPetState == PetState.MoveStraightToPlayer)
            {
                if (!LineOfSightToTarget(playerPosition, .5f))
                {
                    TransitionToState(PetState.FollowPath);
                }
            }

            //Check each pet state.
            switch (CurrentPetState)
            {
            //DEFAULT STATE////////////////////////////////////////////////////////////////////////////////////////
            case PetState.Default:
            {
                //Transition to crouch.
                if (_shouldBeCrouching)
                {
                    TransitionToState(PetState.Crouched);
                }

                //Check the default sub-states
                switch (currentDefaultState)
                {
                //Default running state
                case PetDefaultState.Run:
                {
                    currentCrouchedState = PetCrouchedState.Walk;

                    //Set a new deviation state.
                    if (_canChangeDeviation && !_forcingMovementTowardsPlayer)
                    {
                        _canChangeDeviation = false;
                        ChangeDeviationDirectionCoroutine = StartCoroutine(RandomDeviationStateTime());

                        //Store values for the move input.
                        storedPlayerDir             = playerDir;
                        lastMoveInputDeviationValue = 0;
                        randDeviateAmount           = UnityEngine.Random.Range(.75f, .95f);

                        //Deviate away if the pet is too close.
                        if (playerDirPerpendicularOfVelocity.sqrMagnitude < Mathf.Pow(1f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveAway;
                        }
                        //Deviate closer if the pet is too far away.
                        else if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(2.5f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                        }
                        //No deviation in the middle.
                        else
                        {
                            currentDeviationState = PetDeviationState.NoDeviation;         //Temp
                        }
                    }

                    //Transition to walk if the player moves too slow.
                    if (playerVelocity.sqrMagnitude < Mathf.Pow(4f, 2))
                    {
                        currentDefaultState = PetDefaultState.Walk;
                    }

                    break;
                }

                //Default walking state
                case PetDefaultState.Walk:
                {
                    currentCrouchedState = PetCrouchedState.Walk;

                    //Transition to idle if the player is too slow AND the pet is close enough.
                    if (playerDirTowardsVelocity.sqrMagnitude < Mathf.Pow(.5f, 2) && playerVelocity.sqrMagnitude < Mathf.Pow(1f, 2))
                    {
                        currentDefaultState = PetDefaultState.Idle;
                    }

                    //Transition to run if the player's velocity is above walking speed.
                    if (playerVelocity.sqrMagnitude > Mathf.Pow(4.2f, 2))
                    {
                        currentDefaultState = PetDefaultState.Run;
                    }

                    //Move closer to the player if the pet is too far.
                    if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(2f, 2))
                    {
                        currentDeviationState = PetDeviationState.MoveCloser;
                    }
                    else
                    {
                        currentDeviationState = PetDeviationState.NoDeviation;
                    }
                    break;
                }

                //Default idle state
                case PetDefaultState.Idle:
                {
                    currentCrouchedState = PetCrouchedState.Idle;

                    //Transition to run if the player is too far or if the player's velocity is too high.
                    if (playerDir.sqrMagnitude > Mathf.Pow(2f, 2) ||
                        playerVelocity.sqrMagnitude > Mathf.Pow(4f, 2f))
                    {
                        currentDefaultState = PetDefaultState.Run;
                    }
                    break;
                }
                }

                break;
            }

            //CROUCHED STATE///////////////////////////////////////////////////////////////////////////////////////
            case PetState.Crouched:
            {
                //Transition to default.
                if (!_shouldBeCrouching)
                {
                    TransitionToState(PetState.Default);
                }

                switch (currentCrouchedState)
                {
                //Crouched walking state
                case PetCrouchedState.Walk:
                {
                    currentDefaultState = PetDefaultState.Walk;

                    //If the pet gets close enough to the player, transition to idle.
                    if (playerDirTowardsVelocity.sqrMagnitude < Mathf.Pow(1f, 2f))
                    {
                        currentCrouchedState = PetCrouchedState.Idle;
                    }

                    if (!_forcingMovementTowardsPlayer)
                    {
                        //If the player is too far, move closer to the player
                        if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(1.5f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                        }
                        else
                        {
                            currentDeviationState = PetDeviationState.NoDeviation;
                        }
                    }

                    break;
                }

                //Crouched idle state
                case PetCrouchedState.Idle:
                {
                    currentDefaultState = PetDefaultState.Idle;

                    //Transition to walk if the player is too far or if the player's velocity is too high. (Crouched)
                    if (playerDir.sqrMagnitude > Mathf.Pow(1.5f, 2) ||
                        playerVelocity.sqrMagnitude > Mathf.Pow(1f, 2f))
                    {
                        currentCrouchedState = PetCrouchedState.Walk;
                    }

                    break;
                }
                }

                break;
            }

            //MOVE STRAIGHT TO PLAYER STATE////////////////////////////////////////////////////////////////////////
            case PetState.MoveStraightToPlayer:
            {
                //If the pet enters the default radius, transition back to default.
                if (distanceToPlayer < Mathf.Pow(2.8f, 2f))
                {
                    TransitionToState(PetState.Default);
                }

                break;
            }

            case PetState.FollowPath:
            {
                if (_canCheckPathfinding)
                {
                    _canCheckPathfinding = false;
                    pathfinding.CheckIfCanFollowPath(playerPosition);
                }

                //Transition to default if line of sight is true OR if the pathfinding becomes inactive.
                if (LineOfSightToTarget(playerPosition, 0f))
                {
                    TransitionToState(PetState.Default);
                }

                //Warp to the player
                if (!pathfinding.PathIsActive && !pathfinding.CheckingPath)
                {
                    _canCheckPathfinding = true;
                    if (canWarpToPlayer)
                    {
                        canWarpToPlayer            = false;
                        TimeBeforeWarpingCoroutine = StartCoroutine(TimeBeforeWarping());
                    }
                }
                else
                {
                    canWarpToPlayer = true;
                    StopActiveCoroutine(TimeBeforeWarpingCoroutine);
                }
                break;
            }
            }
        }
        /// <summary>
        /// (Called by KinematicCharacterMotor during its update cycle)
        /// This is called before the character begins its movement update
        /// </summary>
        public void BeforeCharacterUpdate(float deltaTime)
        {
            GetPlayerValues();
            //Crouch if the player is crouching.
            _shouldBeCrouching = player._isCrouching;

            //If the current state is default or crouched...
            if (CurrentPetState == PetState.Default || CurrentPetState == PetState.Crouched)
            {
                //Force the pet to move closer to the player if it goes outside the allowed radius or detects and obstacle.
                if (!_forcingMovementTowardsPlayer)
                {
                    if (distanceToPlayer > Mathf.Pow(3f, 2) && angleComparison <= .7f &&
                        angleComparison >= -.7f || _wallDetected || _ledgeDetected)
                    {
                        _forcingMovementTowardsPlayer = true;
                        StopActiveCoroutine(ChangeDeviationDirectionCoroutine);
                        ForceDeviationStateCoroutine = StartCoroutine(ForceDeviationStateTime());

                        //Store a deviation direction.
                        storedDeviationDir    = Vector3.Slerp(playerVelocity, -playerDirPerpendicularOfVelocity, .3f);
                        currentDeviationState = PetDeviationState.MoveCloser;
                    }
                }

                //If the pet goes outside the default radius, transition to MoveStraightToPlayer.
                if (distanceToPlayer > Mathf.Pow(3.5f, 2f))
                {
                    TransitionToState(PetState.MoveStraightToPlayer);
                }
            }

            //Check each pet state.
            switch (CurrentPetState)
            {
            //DEFAULT STATE////////////////////////////////////////////////////////////////////////////////////////
            case PetState.Default:
            {
                //Transition to crouch.
                if (_shouldBeCrouching)
                {
                    TransitionToState(PetState.Crouched);
                }

                //Check the default sub-states
                switch (currentDefaultState)
                {
                //Default running state
                case PetDefaultState.Run:
                {
                    currentCrouchedState = PetCrouchedState.Walk;

                    //Start deviation if the coroutine ends.
                    if (_canChangeDeviation && !_forcingMovementTowardsPlayer)
                    {
                        _canChangeDeviation = false;
                        ChangeDeviationDirectionCoroutine = StartCoroutine(RandomDeviationStateTime());

                        //(Store a deviation direction so we can use it for the move input.)
                        Vector3 dirToMove = new Vector3();

                        //Check the distance towards the player to determine a deviation direction.
                        if (playerDirPerpendicularOfVelocity.sqrMagnitude < Mathf.Pow(1f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveAway;
                            dirToMove             = -playerDirPerpendicularOfVelocity;
                        }
                        else if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(2.5f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                            dirToMove             = playerDirPerpendicularOfVelocity;
                        }
                        else
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                            //(Can also randomly deviate here.)
                        }
                        storedDeviationDir = Vector3.Slerp(dirToMove, playerVelocity,
                                                           UnityEngine.Random.Range(.75f, .95f));
                    }

                    //If the player starts moving slow, transition to walk.
                    if (playerVelocity.sqrMagnitude < Mathf.Pow(4f, 2))
                    {
                        currentDefaultState = PetDefaultState.Walk;
                    }
                    break;
                }

                //Default walking state
                case PetDefaultState.Walk:
                {
                    currentCrouchedState = PetCrouchedState.Walk;

                    //If the pet gets close enough to the player, transition to idle.
                    if (playerDirTowardsVelocity.sqrMagnitude < Mathf.Pow(.5f, 2))
                    {
                        currentDefaultState = PetDefaultState.Idle;
                    }
                    Debug.Log(playerDirTowardsVelocity.magnitude);

                    //If the player's velocity goes above walking speed, transition to run.
                    if (playerVelocity.sqrMagnitude > Mathf.Pow(4.2f, 2))
                    {
                        currentDefaultState = PetDefaultState.Run;
                    }

                    if (!_forcingMovementTowardsPlayer)
                    {
                        //If the side distance to the player is too far, move closer to the player
                        if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(2f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                        }
                        else
                        {
                            currentDeviationState = PetDeviationState.NoDeviation;
                        }
                    }
                    break;
                }

                //Default idle state
                case PetDefaultState.Idle:
                {
                    currentCrouchedState = PetCrouchedState.Idle;

                    //If the player gets too far or if the player's velocity is too high... (Default)
                    if (playerDir.sqrMagnitude > Mathf.Pow(2f, 2) ||
                        playerVelocity.sqrMagnitude > Mathf.Pow(4f, 2f))
                    {
                        currentDefaultState = PetDefaultState.Run;
                    }

                    //Debug.Log(playerDir.magnitude + ", " + playerVelocity.magnitude);
                    break;
                }
                }
                break;
            }

            //CROUCHED STATE///////////////////////////////////////////////////////////////////////////////////////
            case PetState.Crouched:
            {
                //Transition to default.
                if (!_shouldBeCrouching)
                {
                    TransitionToState(PetState.Default);
                }

                switch (currentCrouchedState)
                {
                //Crouched walking state
                case PetCrouchedState.Walk:
                {
                    currentDefaultState = PetDefaultState.Walk;

                    //If the pet gets close enough to the player, transition to idle.
                    if (playerDirTowardsVelocity.sqrMagnitude < Mathf.Pow(1f, 2f))
                    {
                        currentCrouchedState = PetCrouchedState.Idle;
                    }

                    if (!_forcingMovementTowardsPlayer)
                    {
                        //If the player is too far, move closer to the player
                        if (playerDirPerpendicularOfVelocity.sqrMagnitude > Mathf.Pow(1.5f, 2))
                        {
                            currentDeviationState = PetDeviationState.MoveCloser;
                        }
                        else
                        {
                            currentDeviationState = PetDeviationState.NoDeviation;
                        }
                    }
                    break;
                }

                //Crouched idle state
                case PetCrouchedState.Idle:
                {
                    currentDefaultState = PetDefaultState.Idle;

                    //If the player gets too far or if the player's velocity is too high... (Crouched)
                    if (playerDir.sqrMagnitude > Mathf.Pow(1.5f, 2) ||
                        playerVelocity.sqrMagnitude > Mathf.Pow(1f, 2f))
                    {
                        currentCrouchedState = PetCrouchedState.Walk;
                    }
                    break;
                }
                }
                break;
            }

            case PetState.MoveStraightToPlayer:
            {
                //If the pet enters the default radius, transition back to default.
                if (distanceToPlayer < Mathf.Pow(3f, 2f))
                {
                    TransitionToState(PetState.Default);
                }
                break;
            }
            }
        }