J'ai travaillé sur le même moteur que coderanger. J'ai un point de vue différent. :)
Premièrement, nous n'avions pas de pile de FSM - nous avions une pile d'états. Une pile d'états constitue un seul FSM. Je ne sais pas à quoi ressemblerait une pile de FSM. Probablement trop compliqué pour faire quoi que ce soit de pratique.
Mon plus gros problème avec notre machine à états globale était qu'il s'agissait d'une pile d'états et non d'un ensemble d'états. Cela signifie que, par exemple, ... / MainMenu / Le chargement était différent de ... / Loading / MainMenu, selon que le menu principal était activé avant ou après l'écran de chargement (le jeu est asynchrone et le chargement est principalement piloté par le serveur. )
Comme deux exemples de choses rendues laides:
- Cela conduisait par exemple à l'état LoadingGameplay, donc vous aviez Base / Loading, et Base / Gameplay / LoadingGameplay pour le chargement dans l'état Gameplay, qui devait répéter une grande partie du code dans l'état de chargement normal (mais pas tous, et en ajouter d'autres). )
- Nous avions plusieurs fonctions telles que "si le créateur de personnage va dans le gameplay; si dans le gameplay allez dans la sélection de personnage; si dans la sélection de personnage revenez à la connexion", parce que nous voulions afficher les mêmes fenêtres d'interface dans des états différents mais faire le Back / Forward les boutons fonctionnent toujours.
Malgré le nom, ce n'était pas très "global". La plupart des systèmes de jeu internes ne l'utilisaient pas pour suivre leurs états internes, car ils ne voulaient pas que leurs états fouillent avec d'autres systèmes. D'autres, par exemple le système d'interface utilisateur, pourraient l'utiliser, mais uniquement pour copier l'état dans leurs propres systèmes d'état locaux. (Je voudrais tout particulièrement mettre en garde contre le système pour les états d'interface utilisateur. L'état d'interface utilisateur n'est pas une pile, mais bien un groupe de disponibilité de base, et essayer de forcer toute autre structure dessus ne fera que créer des interfaces utilisateur dont l'utilisation est frustrante.)
Ce qui était bien, c’était de séparer les tâches d’intégration de code des programmeurs d’infrastructure qui ne savaient pas comment le flux de jeu était structuré, de sorte que vous puissiez dire au gars qui écrit le correctif "placez votre code dans Client_Patch_Update" et au gars qui écrit les graphiques. chargement "mettez votre code dans Client_MapTransfer_OnEnter", et nous pourrions échanger certains flux logiques sans trop de problèmes.
Sur un projet parallèle, j’ai eu plus de chance avec un ensemble d’ états que avec une pile . juste un moyen compliqué de synchroniser les choses avec des variables globales - Bien sûr, vous allez finir par le faire dans un délai raisonnable, mais ne concevez pas cela comme votre objectif . Fondamentalement, l'état dans un jeu n'est pas une pile et les états dans un jeu ne sont pas tous liés.
Le GSM aussi, comme le font souvent les indicateurs de fonction et les comportements non locaux, a rendu le débogage plus difficile, bien que le débogage de ce type de grandes transitions d'état ne soit pas très amusant avant que nous l'ayons. Les ensembles d'états au lieu de piles d'état n'aident pas vraiment cela, mais vous devriez en être conscient. Les fonctions virtuelles plutôt que les pointeurs de fonctions peuvent atténuer quelque peu cet inconvénient.