Example #1
0
    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);
    }
Example #2
0
    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);
    }