Du shoot’em up : Considérations techniques (3/3)

Simon Albou
Sep 1, 2018 · 10 min read

Cet article constitue la troisième et dernière partie d’une série sur le genre du shoot’em up, plus précisément d’un retour sur la conception et la production d’un outil de développement complet à destination du grand public, via Unity.
Pour lire les articles précédents :
• Partie 1, design, analyse et décomposition du genre : lien
• Partie 2, problématiques techniques, gestion des collisions : lien
• Extension de la partie 2 à destination des développeurs, tutoriel complet sur l’usage des Compute Shaders et l’optimisation : lien

Il me reste à parler de la gestion de ce projet et des différentes guidelines qui s’imposent naturellement lors de la création de ce type d’outil. Il est important que l’on s’attarde sur les points suivants :
• À quelles échelles cet outil doit-il servir ?
• L’importance de l’UI design sur un tel projet
• Tool programming : les contraintes

III. Concevoir et produire pour un public donné

1 - À quelles échelles cet outil doit-il servir ?

Tout d’abord il faut comprendre pourquoi la question a besoin d’être posée. On peut créer un outil de haute précision et de grande envergure, et consacrer beaucoup de temps à sa production, mais est-ce que cela en vaut la peine s’il ne trouve qu’un usage très réduit ? À titre d’exemple mon cas de figure pourrait se heurter à un problème : le bullet hell, c’est un genre de niche, joué par peu de personnes par rapport à des types de gameplay plus populaires tels que le platforming ou le tir à la première personne. Pour assurer que l’outil soit temporellement rentable, il faudrait qu’il ait d’autres usages. Cela va ouvrir un débat à l’issue duquel certaines guidelines de conception vont émerger.

À quels autres usages un outil conçu autour du genre du bullet hell peut-il servir ?

On va parler de scalability de l’outil (je ne vois pas d’équivalent français, désolé !), c’est-à-dire sa capacité à s’adapter à des projets moins ambitieux, à des scopes plus petits. Certains moteurs sont connus pour être vus comme très compliqués et ne trouvant leur utilité que dans des projets très complexes où 100% de leur potentiel se révèle. À mon sens, c’est un défaut : ces outils ont souvent plusieurs leviers à disposition pour être davantage démocratisés.

Premier exemple, ils pourraient disposer d’un “mode simplifié”, à la façon des logiciels de la suite Adobe qui propose d’adapter son espace de travail pour différentes activités, dont un mode “les essentiels”, généraliste, et direct.

Le menu contextuel que l’on trouve dans Photoshop (CS6).

Second exemple, qui m’intéresse davantage, leur porte d’entrée pourrait être simplement plus facile à appréhender. Un bon outil devrait se révéler utile et rentable même pour les tâches les plus basiques. Ces usages simples peuvent même naturellement aider les utilisateurs à prendre en main leur espace de travail et faciliter leur apprentissage.

Le cas de figure du shoot’em up est directement concerné par cette remarque. Comme mentionné plus tôt, sur un strict plan mécanique le bullet hell peut se résumer à de l’évitement de hitbox. Or, l’évitement de hitbox, c’est un principe que l’on va retrouver dans beaucoup de types de gameplay différents, qui ne relèvent pas toujours du jeu d’arcade, classique, à défilement vertical ou horizontal contre un boss défini par une série de patterns…

Des jeux comme ceux de la licence Megaman intègrent la notion de tir et de projectile, même de façon sommaire. Pareillement pour la plupart des Mario, avec diverses boules de feu. On va même retrouver de la gestion de projectiles, parfois un peu plus complexe, dans des jeux comme les Super Smash Bros.
Si un outil de développement peut apporter gain de performance et vitesse de production sur des bullet hells, pourquoi pas aussi sur ces jeux ?

Il ne faut pas négliger la quantité de situations impliquant des projectiles dans de nombreux jeux.

On tire de ceci une nécessité capitale : l’outil doit absolument être si facile d’usage qu’il permet aussi un gain de temps sur tout autre système de projectile. Cela va orienter la façon dont on en conçoit l’interface car, bien que l’on cherche à être adapté aux situations les plus compliquées et complexes, ce même confort d’utilisation doit se retrouver sur des tâches élémentaires.

L’intégration totale de l’outil doit être très légère et rapide. Dans cette optique, pour l’utilisateur, je fais le choix de fournir des objets les moins intrusifs possibles dans son projet Unity.
Un seul composant, “Bullet Receiver”, se pose sur tout objet pouvant être frappé par un projectile. (exemple : notre avatar)
Un seul composant, “Bullet Emitter”, se pose sur tout objet pouvant émettre un projectile. (exemple : un ennemi)
Un seul prérequis d’installation : certains scripts doivent être présents dans la scène de jeu. Mais cela ne doit pas mobiliser l’utilisateur. Cette opération est donc facilitée en les réunissant tous dans un seul objet sur Unity (prefab), que je nomme “Quick Start” et qui sera le seul objet que je laisse à la racine du dossier qu’installe l’utilisateur dans son projet.
• En ajoutant même un exemple d’Emitter et de Receiver dans cet objet “Quick Start”, de façon effective l’installation complète de l’outil et tout son usage se résument à un seul drag’n’drop. Le reste n’est qu’affinement et paramétrage de gameplay.

Ce type de pratique participe à résoudre le problème du scope, du public niche, et de la capacité qu’aura le produit fini à atteindre un marché supplémentaire. Simplifier les choses reste l’idée maîtresse !

2 - L’importance de l’UI Design

À partir de maintenant, on a établi qu’il fallait se focaliser sur l’interface pour privilégier la lisibilité. Mais ça n’est pas tout : ce design d’interface va également diriger notre mode de production. Puisqu’on fabrique quelque chose qui se veut modulaire, notre production va se subdiviser en plusieurs sous-outils, plus petits, qui vont chacun servir un objectif différent pour l’utilisateur. Exemples de sous-objectifs qui méritent chacun leur interface :
• Dessiner des patterns
• Paramétrer un projectile précis
• Gérer le nombre de projectiles présents dans le jeu
• Modifier ou animer les paramètres de certains projectiles en fonction de leur placement dans l’espace
• La liste est encore longue !

Pour chacun, on va devoir se mettre à la place de l’utilisateur. Qu’est-ce que j’ai envie d’avoir à ma disposition ? De quelles commodités est-ce que je ressens le besoin ? Également, plus l’usage d’un sous-outil est spécifique (et rare), et plus l’on peut se permettre de proposer des interfaces élaborées, moins minimalistes, car elles seront nécessaires.
• Simplement paramétrer un bullet doit rester élémentaire et fonctionner avec une liste de champs (pour des valeurs numériques) très bien ordonnés.
• À l’inverse, organiser un série de bullets dans l’espace est une tâche plus ardue. Cela vaut la peine de passer du temps à créer une interface adaptée.
• À une échelle plus micro, le même raisonnement s’applique : cette interface adaptée, aussi complexe puisse-t-elle être, doit permettre de créer les patterns les plus élémentaires en quelques clics et sans aucune contrainte inutile.

Finalement, j’ai pris l’habitude de concevoir et fabriquer ces interfaces avant même le fonctionnement réel de l’outil. C’est la priorité, et cela fournit un cadre dans lequel mettre en place nos différentes features. Dans Unity, cela se traduit par le fait de fabriquer tous les scripts Editor, tous les inspectors et PropertyDrawers personnalisés relatifs à une fonctionnalité précise, avant sa mise en place réelle ingame. Lorsque l’UI est assez claire, agréable et amusante à manipuler, il ne reste plus qu’à assigner à chaque bouton, chaque menu déroulant, chaque champ, les paramètres réels que ces éléments vont modifier.

On peut tout à fait reproduire cet automatisme à l’échelle de la production d’un jeu. C’est l’équivalent de “commencer par développer les menus, les systèmes de sauvegarde, les options” avant de créer son gameplay. Puis, au sein du gameplay, d’abord réaliser une template de chaque écran, de chaque interface, et des contrôles existants, avant de penser au moindre contenu. Et on se rend vite compte que c’est un mode de production qui fonctionne très bien :
• Cela crée un cadre de travail et nous force à avoir une vision globale, complète, de notre design.
• Cela délimite la place qui sera éventuellement accordée à des changements d’avis en milieu de production. Il faut laisser des portes ouvertes aux incertitudes, mais de manière contrôlée !
• Cela évacue au plus tôt les questions qui sont totalement parasitaires en fin de production. On s’assure que si le temps de production doit être allongé, ce sera nécessairement pour ajouter du contenu ou améliorer sa qualité, pas pour combler des trous ou corriger des bugs (dans un cas idéal).

En bref, aura émergé de cette expérience de tool programming un workflow que je juge beaucoup plus sain, plus efficace et plus sensé, également valable pour la production classique d’un jeu.

3 - Tool programming : contraintes, guidelines

Je tiens à terminer cette série par une liste, en vrac, de plusieurs “bonnes pratiques” qui devraient être suivies dans toute situation où l’on crée un outil de production, destiné à d’autres développeurs. Certaines de ces directives font partie des consignes officielles d’Unity afin qu’un plugin soit valide sur leur plateforme, d’autres non.

  • La documentation. Ça ne passe pas que par un fichier .pdf fourni avec l’outil ! Commenter le code est également utile dans la mesure où certains utilisateurs pourront en être curieux ou avoir besoin d’éditer des sources d’une manière que l’on ne prévoit pas. Similairement à une production de jeu, l’utilisateur/le joueur ne va rien deviner tout seul et une large, très large quantité de travail mental doit lui être épargnée. L’organisation des dossiers, les noms de fichiers, les noms de variables, il ne faut rien laisser au hasard. C’est aussi un service rendu à soi-même car ce type de projet demande une maintenance sur le long terme. Avec quelle facilité arrive-t-on à reprendre notre code d’il y a un an ?
  • Sélections multiples. Quand on propose nos propres outils, il est rare qu’ils soient pleinement compatibles avec l’édition de masse, pourtant c’est souvent une nécessité. Y consacrer du temps sera toujours une bonne idée. Cet article n’a pas vocation à être un guide technique, mais je tiens quand même à mentionner certaines fonctions et attributs pour gérer le multi-editing avec Unity :
    - CanEditMultipleObjects
    -
    Editor.targets
    - serializedProperty.hasMultipleDifferentValues
    - serializedProperty.arraySize
    - serializedProperty.GetArrayElementAtIndex(int index)
  • Ctrl+Z. Fonction agréable, non ? Problème, elle n’est pas implémentée par défaut dans les outils personnalisés d’Unity et il faut la prendre en charge soi-même. De manière générale, il faut systématiquement permettre à l’utilisateur de faire un demi-tour complet n’importe quand. Le fait qu’Unity ne propose pas de prise en charge automatique de l’Undo (excepté avec l’objet SerializedProperty) est en réalité un avantage, car il nous permet de personnaliser la façon dont il est mis en place. On peut par exemple mettre en place des fonctions supplémentaires de vérification lors de l’Undo, le verrouiller dans certains cas exceptionnels, etc.
  • On ne prévoit jamais assez de messages d’erreur. Anticiper tout ce que l’utilisateur peut mal faire à tout instant est peut-être ce qu’il y a de plus complexe avec la mise en place d’outils ; le cas échéant, il faut penser à fournir des messages d’erreur explicite et fournir des façons de régler automatiquement chaque problème. Cela peut être par exemple un gros bouton jaune “Réparer” qui apparaît dans l’Inspector lorsqu’une valeur est mal renseignée — même si c’est un exemple ridicule, en pratique c’est un excellent filet de sécurité (tant qu’il ne produit pas de pollution visuelle).
  • Du côté script, il faut activement prévenir toutes les exceptions qui ont l’habitude de nous embêter. Notamment avec l’usage de tableaux et de listes ; récupérer un objet dans une collection ne devrait jamais se faire sans d’abord vérifier successivement trois choses :
    1) que la collection elle-même n’est pas égale à null
    2) que la taille de la collection n’est pas égale à 0
    3) que l’index de l’objet recherché est compris entre 0 et cette taille
    Dans ces trois cas de figure, penser à également prévoir un message d’erreur personnalisé.
  • Exhaustivité et incertitude. Pour résumer en une phrase : si une feature nous vient à l’esprit alors qu’on ne voit pas, sur le moment, à quoi elle pourrait servir, ça n’est pas une raison valable de ne pas la produire. On fabrique l’espace de travail d’une infinité de développeurs potentiels sur une infinité de jeux potentiels, voire d’autres usages ; ils auront une infinité de besoins potentiels. On ne peut pas se permettre de limiter ce scope à notre seule vision des choses.
  • Layout et responsive design. Sur Unity, les interfaces personnalisées d’outils éditeur se conçoivent parfois (souvent) de façon similaire à une page web. Et on y retrouve des problématiques identiques : on ne peut pas savoir quelle taille fera la fenêtre dans laquelle les développeurs travailleront. Créer une bonne UI, c’est aussi s’assurer qu’elle restera tout autant utilisable dans différentes configurations d’espace de travail.

Illustration : la fenêtre Inspector d’Unity est rarement très large, et de toute façon l’oeil humain préfère traiter des surfaces qui demandent peu de mouvements latéraux (comme une colonne de journal). On va donc chercher à éviter les interfaces qui s’étendent beaucoup horizontalement, qu’elles s’intègrent ou non à l’inspector.

En bref, lorsque l’on conçoit un outil il faut penser au moindre détail en se projetant dans le comportement de l’utilisateur, et en décomposant nos propres modèles et habitudes lorsque c’est à notre tour d’avoir ce statut.

Conclusion

Voilà qui termine ma série sur le shoot’em up et le développement d’outils. Je serai bientôt en capacité de montrer mes productions et promouvoir mon plugin ! Je serai également ravi de pouvoir répondre à d’éventuelles questions sur l’un des sujets abordés.

Merci d’avoir lu, et à bientôt peut-être !

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade