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(); var pickAPointAtASafeDistance = new MaintainRangeFromTransform(this, player, playerProximity); var walkToTarget = new MoveToTarget(this, agent, MoveState.Walking); var startRunningAway = new StartRunningAway(this, agent, playerProximity, maxRangeToPlayer + 2.0f); var runAwayABit = new RunAwayFromTransform(this, agent, playerProximity, MoveState.Running); var stareAtPlayer = new StareAtTransform(this, agent, player); var chargeAtPlayer = new ChargeAtPlayer(this, agent, player, rescueAttack); var toggleAttack = new ToggleAttack(rescueAttack); var aggressivelyWait = new StandAndWait(); //////---- // Set Transitions // // Passives // pickAPointAtASafeDistance stateMachine.AddTransition(pickAPointAtASafeDistance, walkToTarget, () => true); // walkToTarget stateMachine.AddTransition(walkToTarget, pickAPointAtASafeDistance, ReachedGoalPosition()); stateMachine.AddTransition(walkToTarget, startRunningAway, TooCloseToPlayer()); stateMachine.AddTransition(walkToTarget, pickAPointAtASafeDistance, GotStuck()); // startRunningAway stateMachine.AddTransition(startRunningAway, runAwayABit, () => true); // runAwayABit stateMachine.AddTransition(runAwayABit, pickAPointAtASafeDistance, EscapedFromPlayer()); // Aggressive State Transitions // stareAtPlayer stateMachine.AddTransition(stareAtPlayer, toggleAttack, WaitFor(stareAtPlayer, chargeUpTime)); // toggleAttack stateMachine.AddTransition(toggleAttack, chargeAtPlayer, () => true); // chargeAtPlayer stateMachine.AddTransition(chargeAtPlayer, aggressivelyWait, ChargeAttackEnded()); // aggressivelyWait stateMachine.AddTransition(aggressivelyWait, pickAPointAtASafeDistance, WaitFor(aggressivelyWait, pauseAfterAttack)); //////---- // Universal Transitions // // One-frame States stateMachine.AddUniversalTransition(stareAtPlayer, GoingAggressive()); // Conditions Func <bool> ReachedGoalPosition() => () => Vector3.Distance(transform.position, goalPosition) <= agent.stoppingDistance + 0.2f; Func <bool> GotStuck() => () => timeSinceLastProgress > StuckTime; Func <bool> TooCloseToPlayer() => () => playerProximity.IsInRange; Func <bool> EscapedFromPlayer() => () => !playerProximity.IsInRange; Func <bool> WaitFor(IWaitableState state, float seconds) => () => state.GetTimeElapsed() > seconds; Func <bool> ChargeAttackEnded() => () => !rescueAttack.IsEnabled(); Func <bool> GoingAggressive() => () => { if (attackCooldown < 0.0f) { StartAttackCooldown(); return(true); } return(false); }; // Set initial state stateMachine.SetState(pickAPointAtASafeDistance); }