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.
Défi
MoyenMaintenez 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 simpleStateMachineavec une propriété publiqueCurrentque seule la machine peut définir, une méthodeChangeState(IState next)qui exécute Exit de l’ancien état, puis Enter du nouvel état, et une méthodeTick()qui exécute Tick de l’état actuel. - Le joueur demande son état à chaque image. Ainsi, si
ChangeStateest appelée avec l’état déjà actuel, elle ne fait rien : ni Exit ni Enter. - Dans
Player.cs, ajoutez un champStateMachinenommé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
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
1Des composants, pas des hiérarchies
Des composants simplesUn script de base pour les ennemisDes composants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaire4Données sérialisées
Classes sérialisablesListes dans l’inspecteurÉnumérations dans l’inspecteurRécapitulatif : table de butin7Machines à états
Les états sous forme de classesUne machine à étatsTransitionsLes cerveaux des ennemisRécapitulatif : états d’une porte10Projet : Survivant de l’arène
Le hérosTypes d’ennemis2Interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interaction5ScriptableObjects
Assets de donnéesStatistiques des armesParamètres partagésLes vagues sous forme de donnéesRécapitulatif : base de données d’objets