/// <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; } } }