Menu
CoddyTech

Une machine à états

Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 29 sur 50.

La méthode SetState de Beacon serait la même dans chaque objet ayant des états : une tourelle, un ennemi, une porte. Ce code peut être placé dans une classe à part, une machine à états, qui conserve l’état actuel et le modifie. Chaque objet crée une machine et l’appelle, au lieu de répéter le code :

public class StateMachine
{
    public IState Current { get; private set; }

    public void ChangeState(IState next)
    {
        Current?.Exit();
        Current = next;
        Current.Enter();
    }

    public void Tick()
    {
        Current?.Tick();
    }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private StateMachine machine = new StateMachine();
    private IState blink;
    private IState steady;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        machine.ChangeState(steady);
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame) machine.ChangeState(machine.Current == steady ? blink : steady);
        machine.Tick();
    }
}

Le premier appel à ChangeState n’a aucun état à quitter : Current est null, et ?. ignore l’appel à Exit. La section 1 a indiqué que ?. ne détecte pas le faux null de Unity ; cela concerne les objets Unity détruits, et les états sont de simples objets C#, donc ?. est sûr ici. Current a un private set, donc aucun script ne peut remplacer l’état sans passer par ChangeState et ses appels à Exit et Enter.

L’ordre à l’intérieur de ChangeState est important lorsque deux états agissent sur la même chose. Exit annule ce que l’ancien état a modifié, puis Enter configure le nouvel état, qui a donc le dernier mot. Si Enter de DarkState éteignait la lampe et s’exécutait avant Exit de BlinkState, cet Exit rallumerait la lampe dans l’état sombre. StateMachine est également une classe ordinaire : la balise, une tourelle et un ennemi en créent chacun une avec new et appellent son Tick depuis leur Update.

challenge icon

Défi

Moyen

Maintenez la barre d’espace pour vous déplacer furtivement. WalkState et SneakState sont prêts dans PlayerStates.cs : leurs méthodes Enter et Exit indiquent ce qui se passe (Walk: enter, Sneak: exit...), et leur méthode Tick appelle Move() du joueur. Écrivez la machine qui les exécute.

  • Dans StateMachine.cs, écrivez une classe simple StateMachine avec une propriété publique Current que seule la machine peut définir, une méthode ChangeState(IState next) qui exécute Exit de l’ancien état, puis Enter du nouvel état, et une méthode Tick() qui exécute Tick de l’état actuel.
  • Le joueur demande son état à chaque image. Ainsi, si ChangeState est appelée avec l’état déjà actuel, elle ne fait rien : ni Exit ni Enter.
  • Dans Player.cs, ajoutez un champ StateMachine nommé machine. Dans Start, créez la machine et les deux états (chacun reçoit le joueur), puis commencez à marcher. Dans Update, passez à l’état furtif tant que la barre d’espace est maintenue, et à l’état de marche sinon, puis faites avancer la machine d’une étape.

Appuyez sur Play, marchez, maintenez la barre d’espace et continuez à marcher, puis cliquez sur Check.

Essayez vous-même

// StateMachine : Current, ChangeState et Tick
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Architecture de jeu dans Unity