Que recherchez-vous ?
Hero background image
Utiliser le modèle de commande pour des systèmes de jeu flexibles et extensibles

L’implémentation de modèles de conception de programmation de jeux courants dans votre projet Unity peut vous aider à créer et à maintenir efficacement une base de code propre, organisée et lisible. Les modèles de conception réduisent le temps de refactorisation et de test, accélèrent les processus de développement et contribuent à une base solide pour développer votre jeu, votre équipe et votre entreprise.

Considérez les modèles de conception non pas comme des solutions finies que vous pouvez copier et coller dans votre code, mais comme des outils supplémentaires qui peuvent vous aider à créer des applications plus grandes et évolutives.

Cette page explique le modèle de conception de la commande.

Le contenu ici est basé sur l’e-book gratuit, Améliorez votre code avec des modèles de programmation de jeux.

Consultez d’autres articles de la série sur les modèles de conception de programmation de jeux Unity sur le hub des meilleures pratiques Unity ou via ces liens :

Présentation du modèle de commande

Le modèle de conception de programmation de commande est l’un des Gang of Four original et est utile chaque fois que vous souhaitez suivre une série spécifique d’actions. Vous avez probablement vu le modèle de commande à l’œuvre si vous avez joué à un jeu qui utilise la fonctionnalité d’annulation/rétablissement ou qui conserve votre historique d’entrée dans une liste. Imaginez un jeu de stratégie où l’utilisateur peut planifier plusieurs tours avant de les exécuter réellement. C’est le modèle de commande.

Le modèle de commande permet de représenter les actions sous forme d’objets. L’encapsulation d’actions en tant qu’objets vous permet de créer un système flexible et extensible pour contrôler le comportement des GameObjects en réponse aux entrées de l’utilisateur. Cela fonctionne en encapsulant un ou plusieurs appels de méthode en tant qu'« objet de commande » plutôt que d’appeler directement une méthode. Vous pouvez ensuite stocker ces objets de commande dans une collection, comme une file d’attente ou une pile, qui fonctionne comme un petit tampon.

Le stockage des objets de commande de cette manière vous permet de contrôler le minutage de leur exécution en retardant potentiellement une série d’actions pour une lecture ultérieure. De même, vous pouvez les rétablir ou les annuler et ajouter une flexibilité supplémentaire pour contrôler l’exécution de chaque objet de commande.

Voici quelques applications courantes du modèle dans différents genres de jeux :

  • Dans un jeu de stratégie en temps réel, le modèle de commandement pourrait être utilisé pour mettre en file d’attente les actions des unités et des bâtiments. Le jeu exécuterait ensuite chaque commande au fur et à mesure que les ressources deviendraient disponibles.
  • Dans un jeu de stratégie au tour par tour, le joueur pouvait sélectionner une unité, puis stocker ses mouvements ou ses actions dans une file d’attente ou une autre collection. À la fin du tour, le jeu exécutait toutes les commandes de la file d’attente du joueur.
  • Dans un jeu de puzzle, le modèle de commande pourrait permettre au joueur d’annuler et de refaire des actions.
  • Dans un jeu de combat, la lecture des pressions sur les boutons ou des mouvements de la manette de jeu dans une liste de commandes spécifique peut entraîner des combos et des mouvements spéciaux.
Gérez le modèle dans un exemple de projet
Gérez le modèle dans un exemple de projet

Essayez l’exemple de projet sur GitHub qui illustre différents modèles de conception de programmation dans le contexte du développement de jeux, y compris le modèle de commande.

Dans cet exemple, le joueur peut se déplacer dans un labyrinthe en cliquant sur les boutons sur le côté gauche. Lorsque votre joueur se déplace, vous pouvez voir une traînée de mouvement. Mais plus important encore, vous pouvez annuler et refaire vos actions précédentes.

Pour trouver la scène correspondante dans le projet, allez dans le dossier nommé « 9 Command ».

L’objet de commande et l’invocateur de commande

Pour implémenter le modèle de commande, vous aurez besoin d’un objet général qui contiendra votre action. Cet objet de commande contiendra la logique à exécuter et comment l’annuler.

Il existe plusieurs façons de l’implémenter, mais voici une version simple utilisant une interface appelée ICommand :

interface publique ICommand
{
void Exécuter() ;
void Annuler() ;
}

Dans ce cas, chaque action de jeu appliquera l’interface ICommand (vous pouvez également l’implémenter avec une classe abstraite).

Chaque objet de commande sera responsable de ses propres méthodes d’exécution et d’annulation . Ainsi, l’ajout de commandes supplémentaires à votre jeu n’affectera pas les commandes existantes.

La classe CommandInvoker est alors responsable de l’exécution et de l’annulation des commandes. En plus des méthodes ExecuteCommand et UndoCommand , il dispose d’une pile d’annulation pour contenir la séquence d’objets de commande.

Exemple: Mouvement irréalisable

Dans l’exemple de projet, vous pouvez déplacer votre joueur dans un petit labyrinthe. Une option simple pour déplacer la position du joueur est de créer un PlayerMover.

Pour ce faire, vous devrez passer un Vector3 dans la méthode Move pour guider le joueur le long des quatre directions de la boussole. Vous pouvez également utiliser un raycast pour détecter les murs dans le LayerMask approprié. Bien sûr, l’implémentation de ce que vous souhaitez appliquer au modèle de commande est distincte du modèle lui-même.

MoveCommand
COMMANDINVOKER, ICOMMAND ET MOVECOMMAND
MoveCommand

Pour suivre le modèle de commande, capturez la méthode Move du PlayerMover en tant qu’objet. Au lieu d’appeler Move directement, créez une nouvelle classe, MoveCommand, qui implémente l’interface ICommand .

classe publique MoveCommand : ICommand
{
PlayerMover playerMover ;
Mouvement Vector3 ;
public MoveCommand(PlayerMover player, Vector3 moveVector)
{
this.playerMover = joueur ;
this.movement = moveVector ;
}
public void Exécuter()
{
playerMover.Move(movement);
}
public void Annuler ()
{
playerMover.Move(-movement);
}
}

Quelle que soit la logique que vous voulez accomplir, appelez Move avec le vecteur de mouvement.

ICommand a également besoin d’une méthode Undo pour restaurer la scène à son état précédent. Dans ce cas, la logique d’annulation soustrait le vecteur de mouvement, poussant essentiellement le joueur dans la direction opposée.

La commande MoveCommand stocke tous les paramètres dont elle a besoin pour s’exécuter. Configurez-les avec un constructeur. Dans ce cas, vous enregistrez le composant PlayerMover approprié et le vecteur de mouvement.

Une fois que vous avez créé l’objet de commande et enregistré ses paramètres nécessaires, utilisez les méthodes statiques ExecuteCommand et UndoCommand de CommandInvoker pour transmettre votre MoveCommand. Cela exécute Execute or Undo de MoveCommand et suit l’objet de commande dans la pile d’annulation.

L’InputManager n’appelle pas directement la méthode Move du PlayerMover. Au lieu de cela, ajoutez une méthode supplémentaire, RunMoveCommand, pour créer une nouvelle MoveCommand et l’envoyer au CommandInvoker.

Ensuite, configurez les différents événements onClick des boutons d’interface utilisateur pour appeler RunPlayerCommand avec les quatre vecteurs de mouvement.

Consultez l’exemple de projet pour plus de détails sur l’implémentation d’InputManager. Vous pouvez également configurer votre propre saisie à l’aide du clavier ou de la manette de jeu. Votre joueur peut maintenant naviguer dans le labyrinthe. Cliquez sur le bouton Annuler pour revenir au carré de début.

Avantages et inconvénients

L’implémentation de la rejouabilité ou de l’infaisabilité est aussi simple que de générer une collection d’objets de commande. Vous pouvez également utiliser le tampon de commande pour lire des actions en séquence avec des commandes spécifiques.

Par exemple, pensez à un jeu de combat où une série de clics sur des boutons spécifiques déclenche un combo ou une attaque. Le stockage des actions du joueur avec le modèle de commande rend la configuration de ces combos beaucoup plus simple.

D’un autre côté, le modèle de commande introduit plus de structure, tout comme les autres modèles de conception. Vous devrez décider où ces classes et interfaces supplémentaires offrent suffisamment d’avantages pour déployer des objets de commande dans votre application

Une fois que vous avez appris les bases, vous pouvez modifier la synchronisation des commandes et les lire successivement ou inversement, selon le contexte.

Tenez compte des éléments suivants lors de l’incorporation du modèle de commande :

  • Créez d’autres commandes : L’exemple de projet n’inclut qu’un seul type d’objet de commande, le MoveCommand. Vous pouvez créer un nombre illimité d’objets de commande qui implémentent ICommand et les suivre à l’aide de CommandInvoker.
  • L’ajout de la fonctionnalité de rétablissement consiste à ajouter une autre pile : Lorsque vous annulez un objet de commande, poussez-le sur une pile distincte qui suit les opérations de rétablissement. De cette façon, vous pouvez rapidement parcourir l’historique d’annulation ou rétablir ces actions. Effacez la pile de restauration lorsque l’utilisateur appelle un mouvement entièrement nouveau (vous pouvez trouver une implémentation dans l’exemple de projet).
  • Utilisez une collection différente pour votre mémoire tampon d’objets de commande : Une file d’attente peut être plus pratique si vous voulez un comportement FIFO (premier entré, premier sorti). Si vous utilisez une liste, suivez l’index actuellement actif ; Les commandes avant l’index actif sont annulables. Les commandes après l’index peuvent être rétablies.
  • Limitez la taille des piles : Les opérations d’annulation et de rétablissement peuvent rapidement devenir incontrôlables. Limitez les piles au plus petit nombre de commandes.
  • Transmettez tous les paramètres nécessaires dans le constructeur : Cela permet d’encapsuler la logique comme le montre l’exemple MoveCommand.
  • Le CommandInvoker, comme les autres objets externes, ne voit pas le fonctionnement interne de l’objet de commande, appelant uniquement Exécuter ou Annuler. Donnez à l’objet de commande toutes les données nécessaires pour fonctionner lors de l’appel du constructeur.
ebook bleu
Plus de ressources

Vous trouverez d’autres conseils sur l’utilisation des modèles de conception dans vos applications Unity, ainsi que sur les principes SOLID, dans l’e-book gratuit Améliorez votre code avec des modèles de programmation de jeux.

Vous pouvez trouver tous les e-books techniques avancés de Unity et des articles sur le hub des meilleures pratiques . Les livres électroniques sont également disponibles sur la page des meilleures pratiques avancées dans la documentation.

Vous avez aimé ce contenu ?