protected override void SetupStateMachine() { stateMachine = new StateMachine(); // Set Up States var walkRandomWithinCircle = new MoveToRandomWithinCircle(this, agent, SpawnPatrolRadius); var walkToTarget = new MoveToTarget(this, agent, MoveState.Walking); var standAndWait = new StandAndWait(); var runAwayFromPlayer = new RunAwayFromTransform(this, agent, playerProximity, MoveState.Running); var startRunningAway = new StartRunningAway(this, agent, playerProximity, EscapedPlayerRadius); //////---- // Set Transitions // // walkToTarget stateMachine.AddTransition(walkToTarget, standAndWait, ReachedGoalPosition()); stateMachine.AddTransition(walkToTarget, standAndWait, GotStuck()); // standAndWait stateMachine.AddTransition(standAndWait, walkRandomWithinCircle, WaitFor(standAndWait, IdleTime)); // startRunningAway stateMachine.AddTransition(startRunningAway, runAwayFromPlayer, () => true); // runAwayFromPlayer stateMachine.AddTransition(runAwayFromPlayer, startRunningAway, GotStuck()); stateMachine.AddTransition(runAwayFromPlayer, startRunningAway, WaitFor(runAwayFromPlayer, 1.0f)); stateMachine.AddTransition(runAwayFromPlayer, walkRandomWithinCircle, EscapedFromPlayer()); // One-frame States stateMachine.AddTransition(walkRandomWithinCircle, walkToTarget, () => true); //////---- // Set Universal Transitions // // One-frame States stateMachine.AddUniversalTransition(startRunningAway, WantToRunFromPlayer()); // Conditions Func <bool> ReachedGoalPosition() => () => Vector3.Distance(transform.position, goalPosition) <= agent.stoppingDistance + 0.2f; Func <bool> GotStuck() => () => timeSinceLastProgress > StuckTime; Func <bool> WaitFor(IWaitableState state, float seconds) => () => state.GetTimeElapsed() > seconds; Func <bool> WantToRunFromPlayer() => () => (stateMachine._curState != runAwayFromPlayer) && playerProximity.IsInRange; Func <bool> EscapedFromPlayer() => () => !playerProximity.IsInRange; // Set initial state stateMachine.SetState(walkRandomWithinCircle); }
protected override void SetupStateMachine() { stateMachine = new StateMachine(); // Set Up States var randomPointFarAway = new RandomOnNavMesh(this, transform, minDistanceToNextLocation); var walkRandomWithinCircle = new MoveToRandomWithinCircle(this, agent, locationPatrolRadius); var walkToTarget = new MoveToTarget(this, agent, MoveState.Walking); var standAndWait = new StandAndWait(); //////---- // Set Transitions // // randomPointFarAway stateMachine.AddTransition(randomPointFarAway, walkToTarget, RandomPointIsGood()); // walkToTarget stateMachine.AddTransition(walkToTarget, standAndWait, ReachedGoalPosition()); stateMachine.AddTransition(walkToTarget, randomPointFarAway, GotStuck()); // standAndWait stateMachine.AddTransition(standAndWait, walkRandomWithinCircle, WaitFor(standAndWait, waitTimeBetweenSmallMoves)); // walkRandomWithinCircle stateMachine.AddTransition(walkRandomWithinCircle, walkToTarget, () => true); //////---- // Universal Transitions // stateMachine.AddUniversalTransition(randomPointFarAway, PatrolTimerExpired()); // Conditions Func <bool> ReachedGoalPosition() => () => { if (!(Vector3.Distance(transform.position, goalPosition) <= agent.stoppingDistance + 0.2f)) { return(false); } isInTransit = false; return(true); }; Func <bool> RandomPointIsGood() => () => { var vector = transform.position - initialPosition; return(Vector3.Dot(vector, vector) > minDistanceToNextLocation * minDistanceToNextLocation); }; Func <bool> PatrolTimerExpired() => () => { if (timeAtThisLocation > timeSpentAtEachLocation) { timeAtThisLocation = 0.0f; isInTransit = true; return(true); } return(false); }; Func <bool> GotStuck() => () => timeSinceLastProgress > StuckTime; Func <bool> WaitFor(IWaitableState state, float seconds) => () => state.GetTimeElapsed() > seconds; // Set initial state stateMachine.SetState(randomPointFarAway); }