Esempio n. 1
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);
    }
Esempio n. 2
0
    protected override void SetupStateMachine()
    {
        stateMachine = new StateMachine();

        /*         @NOTE:
         *     Current intent is to not actually implement the AI as described. We don't have the API to make
         *     assertions about whether or not a child has received the balloon they wanted. We can only check
         *     unicorns for captured states. As a result, I see fit to only implement guarding *unicorns*
         *     and not children from being delivered. We can revisit this later if there is time.
         */

        var findGuardTarget       = new FindGuardTarget(this);
        var betweenTargetAndGuard = new TargetPositionBetween(this, player);
        var moveToGuardPoint      = new MoveToTarget(this, agent, MoveState.Walking);
        var passivelyWait         = new StandAndWait();

        var stareAtPlayer      = new StareAtTransform(this, agent, player);
        var chargeAtPlayer     = new ChargeAtPlayer(this, agent, player, chargingAttack);
        var chargeAttackRecoil = new ChargeAttackRecoil(agent, player, chargingAttack);
        var aggressivelyWait   = new StandAndWait();

        #region Transitions

        // Passive State Transitions

        // findGuardTarget
        stateMachine.AddTransition(findGuardTarget, betweenTargetAndGuard, HasGuardTarget());
        stateMachine.AddTransition(betweenTargetAndGuard, moveToGuardPoint, () => true);

        // moveToGuardPoint
        stateMachine.AddTransition(moveToGuardPoint, findGuardTarget, GotStuck());
        stateMachine.AddTransition(moveToGuardPoint, findGuardTarget, WaitFor(moveToGuardPoint, 1.0f));
        stateMachine.AddTransition(moveToGuardPoint, passivelyWait, ReachedGoalPosition());

        // standAndWait
        stateMachine.AddTransition(passivelyWait, findGuardTarget, WaitFor(passivelyWait, 1.0f));



        // Aggressive State Transitions

        // stareAtPlayer
        stateMachine.AddTransition(stareAtPlayer, chargeAtPlayer, WaitFor(stareAtPlayer, chargeUpTime));
        stateMachine.AddTransition(stareAtPlayer, findGuardTarget, PlayerNotInRange());

        // chargeAtPlayer
        stateMachine.AddTransition(chargeAtPlayer, findGuardTarget, PlayerNotInRange());
        stateMachine.AddTransition(chargeAtPlayer, aggressivelyWait, PlayerNotInFront());
        stateMachine.AddTransition(chargeAtPlayer, chargeAttackRecoil, ChargeAttackSuccessful());

        //chargeAttackRecoil
        stateMachine.AddTransition(chargeAttackRecoil, stareAtPlayer, WaitFor(chargeAttackRecoil, chargingAttack.ministunDuration * 2.0f));

        // aggressivelyWait
        stateMachine.AddTransition(aggressivelyWait, stareAtPlayer, WaitFor(aggressivelyWait, unsuccessfulWaitTime));



        // Universal State Transitions
        stateMachine.AddUniversalTransition(stareAtPlayer, GoAggressive());
        stateMachine.AddUniversalTransition(findGuardTarget, GoPassive());

        #endregion

        // Conditions
        Func <bool> HasGuardTarget() =>
        () => guardTarget != null;

        Func <bool> GotStuck() =>
        () => timeSinceLastProgress > StuckTime;

        Func <bool> ReachedGoalPosition() =>
        () => Vector3.Distance(transform.position, goalPosition) <= agent.stoppingDistance + 0.2f;

        Func <bool> WaitFor(IWaitableState state, float seconds) =>
        () => state.GetTimeElapsed() > seconds;

        Func <bool> GoAggressive() =>
        () =>
        {
            if (isAggressive || !playerProximity.IsInRange)
            {
                return(false);
            }
            isAggressive = true;
            return(true);
        };

        Func <bool> GoPassive() =>
        () =>
        {
            if (!isAggressive || playerProximity.IsInRange)
            {
                return(false);
            }
            isAggressive = false;
            return(true);
        };

        Func <bool> PlayerNotInRange() =>
        () => !playerProximity.IsInRange;

        Func <bool> PlayerNotInFront() =>
        () => Vector3.Dot(transform.forward, player.position - transform.position) < 0.3f;

        Func <bool> ChargeAttackSuccessful() =>
        () => !chargingAttack.IsEnabled();

        // Set initial state
        stateMachine.SetState(findGuardTarget);
    }