Des systèmes qui créent des écosystèmes : Conception de jeux émergents

Avec de simples scripts, les concepteurs de jeux peuvent créer des systèmes dans leurs jeux qui aboutissent à un gameplay intéressant et inattendu - une sorte de chaos organisé pour ravir et captiver les joueurs. Nous nous sommes entretenus avec le concepteur de jeux Christo Nobbs, qui explique son approche de la conception d'un gameplay émergent à l'aide de quelques fonctionnalités clés d'Unity.
Après des années de discussions avec des créateurs individuels et des studios de jeux, nous savons que lorsque les concepteurs de jeux créent des mécanismes de gameplay et de conception dans Unity, ils peuvent démontrer la vision du jeu de manière claire et plus détaillée au reste de l'équipe.
Nous avons créé un nouvel e-book, The Unity game designer playbook, pour les concepteurs de jeux qui veulent apprendre à prototyper, créer et tester des jeux dans Unity. Les concepteurs de jeux, qu'ils soient nouveaux ou expérimentés, peuvent utiliser ce guide lorsqu'ils commencent à ajouter des compétences Unity à leur profil.
Christo Nobbs, un concepteur de jeux techniques senior spécialisé dans la conception de jeux de systèmes et Unity (C#), a participé à la rédaction de l'e-book. Dans ce billet de blog, le premier d'une série destinée aux concepteurs de jeux, il développe certains des conseils et exemples de conception de systèmes qu'il a fournis dans l'e-book.

Dans la conception d'un jeu, un système utile doit avoir une fonction claire, contenir des données et être modulaire. De cette façon, il peut non seulement interagir avec un autre système, mais aussi interagir avec lui-même sur d'autres GameObjects de manière variable. Lorsque l'on réfléchit à un système de jeu systémique, il est souvent utile de l'envisager non pas comme une architecture complète, mais comme un élément de fonctionnalité qui peut fonctionner de manière récursive dans le jeu.
En combinant ces systèmes, vous pouvez créer des écosystèmes uniques qui réagissent aux actions du joueur et sont équilibrés à l'aide de "leviers de conception" (par opposition à des valeurs cachées et codées en dur). Ces leviers sont mis en place pour manipuler leurs données, ce qui entraîne un jeu systémique.
La plupart des jeux comportent au moins un système, qu'il s'agisse d'un mécanisme unique avec des valeurs à ajuster au cours du jeu ou d'un réseau de systèmes. Dans un jeu de stratégie comme Age of Empires, où le joueur doit apprendre à exploiter et à manipuler les ressources pour progresser et battre ses adversaires, ce sont des écosystèmes complexes qui régissent le jeu.
En fin de compte, c'est aux concepteurs de jeux eux-mêmes de décider comment ils veulent que le joueur progresse dans le jeu. Le jeu doit-il suivre une trajectoire guidée et linéaire ou doit-il être piloté par un système ou une combinaison de systèmes permettant des résultats organiques et émergents ?
Lors de la conception d'un petit système, la priorité doit être donnée à sa modularité et à sa capacité à s'interfacer avec lui-même et avec d'autres systèmes, car ces caractéristiques peuvent donner lieu à des boucles de jeu intéressantes. Vous voulez réfléchir aux chaînes de réactions possibles résultant de la collision d'un système avec lui-même par l'intermédiaire d'un autre objet, ou de la création d'une juxtaposition entre deux systèmes simples. Il faut toujours chercher à créer des systèmes dont la fonction est claire pour le joueur, afin qu'il ait une chance raisonnable d'apprendre le fonctionnement d'un système donné pour en tirer un avantage.

Un exemple de réaction en chaîne se trouve dans le jeu Oxygen Not Included, où l'objectif de la boucle principale est d'équilibrer un certain nombre de systèmes pour atteindre un état d'utopie symbiotique afin de continuer à progresser. Un autre exemple vient de Divinity Original Sin 2, de Larian Studios, où les mobs qui explosent pour attaquer ne peuvent plus le faire si le joueur les mouille, ce qui rend le combat plus facile. Le joueur peut aussi mettre le feu au sol pour se protéger de la foule qui lui fonce dessus.
Un système modulaire peut apporter plus de valeur à votre jeu, car vous pouvez utiliser les pièces d'un système pour en créer un autre, différent. Les courbes d'animation sont une fonctionnalité d'Unity que Christo utilise pour presque tout. Selon lui, "le traitement de leurs données est presque toujours le même. Ils offrent plus de contrôle qu'une seule valeur à équilibrer. De plus, il est possible d'assouplir les mécanismes ou même d'outrepasser les limites du système pour peaufiner un détail".
Une approche modulaire de la conception vous permet également d'informer les programmeurs de la manière la plus précise possible, ce qui les rend plus efficaces pour modifier et déboguer les systèmes de jeu et les réutiliser dans différentes configurations tout au long du jeu.
Les leviers de conception sont utiles pour ajuster les valeurs afin de manipuler un résultat, par exemple pour augmenter ou réduire la difficulté d'un jeu afin qu'il soit gratifiant et qu'il offre le niveau de complexité que vous recherchez. Avec les leviers de conception, vous pouvez tester et ajuster à plusieurs reprises jusqu'à ce que vous obteniez le résultat escompté.
Les leviers de conception peuvent être utilisés aux stades du concept et du prototype du développement du jeu, jusqu'au polissage post-production. Christo dit qu'il ajoute des leviers de conception lorsqu'il schématise ses idées dans un diagramme de flux. Réfléchissez dès le début de votre projet aux interrupteurs et aux leviers dont votre système a besoin afin de pouvoir l'affiner et d'explorer les possibilités de jeu sans avoir à recourir à une refonte du code par la suite.
L'image suivante est un graphique représentant un jeu simple dans lequel les ennemis sont présents dès le départ et où le joueur entre dans le jeu en étant verrouillé et chargé. Il s'agit essentiellement de tuer des ennemis, mais en manipulant les leviers de conception, il est possible de modifier le gameplay pour déplacer le centre d'intérêt. Dans une configuration, le gameplay est centré sur le high-score, l'élimination rapide de nombreux ennemis dans le temps imparti, tandis que dans une autre, l'accent est mis sur l'élimination d'un nombre déterminé d'ennemis en un temps plus court, ce qui laisse aux joueurs le temps de ramasser le butin abandonné avant d'être extraits.

Ce système pourrait également être utilisé pour créer une tempête de balles complète avec d'excellentes chutes et différents types de munitions avec leurs propres propriétés. En ajoutant d'autres leviers de conception, tels qu'un délai de réapparition, vous pouvez étendre le système davantage.
Escape from Tarkov de Battlestate Games est un autre bon exemple de conception de jeu systémique dans Unity. Le jeu dispose d'un système d'artisanat permettant de créer une arme avec son propre ensemble de données, comme le montre l'image ci-dessous. Cet ensemble de données a un impact sur les caractéristiques de l'arme et sur la jouabilité générale de l'arme, de la même manière que la santé du joueur. Si le joueur souffre d'une fracture ou d'un malaise, son arme devient plus difficile à utiliser, alors qu'un joueur en bonne santé contrôle mieux son arme.

La relation entre un système, les armes, et l'autre, la santé, encourage le joueur à accorder de l'importance non seulement à sa vie, mais aussi à des armes plus performantes. Personne ne veut d'un AK sans cache-poussière ni crosse qui rebondit en ratant un tir après l'autre, signe évident que l'arme n'est pas une bonne option dans sa configuration actuelle.
Il existe également un large choix de types de munitions aux propriétés différentes, ainsi que d'armures. Le type de munitions et d'armure de votre adversaire détermine l'endroit du corps où vous devez lui tirer dessus pour lui infliger le plus de dégâts, créant ainsi un méta gameplay. Ces systèmes, qui ont chacun leur lot d'indices visuels, sont équilibrés pour créer l'"essence" de jeu recherchée par leurs concepteurs.

L'une des façons de mettre en place des leviers de conception dans Unity est d'utiliser des objets scriptables (ScriptableObjects). Ils peuvent être utilisés comme conteneurs de données enregistrés en tant qu'actifs et référencés à partir de scripts sans créer de dépendances avec d'autres objets de la scène.
Vous pouvez créer plusieurs actifs ScriptableObject contenant différents ensembles de valeurs que vous pouvez partager et échanger pour modifier des sections entières du gameplay, à l'instar des préréglages. Vos modifications sont enregistrées en mode lecture avec les objets scriptables, de sorte qu'une fois que vous avez quitté le jeu, vous n'avez pas besoin de revenir aux notes et de mettre en œuvre les changements.
Par exemple, lors du prototypage d'un personnage, vous pouvez modifier la sensation du personnage en remplaçant la ressource ScriptableObject par une autre contenant un ensemble de valeurs différent. Il s'agit d'une porte d'entrée potentielle vers le prototypage de buffs et debuffs ou la connexion de la sélection de personnages aux profils.
Supposons que vous réalisiez un jeu de tir et que vous ayez mis en place un système de pistolet avec des valeurs arbitraires pour des actions telles que le recul, la cadence de tir, la précision, les modes de tir, les paramètres audio, les paramètres VFX, etc. Vous pouvez créer un nombre illimité de nouveaux profils d'armes et ajuster leurs paramètres en mode lecture, où vos modifications sont sauvegardées, le tout en une seule fois. Vous pouvez également envoyer ces objets scriptables prédéfinis aux membres de votre équipe pour obtenir leurs commentaires, ce qui est utile lorsque vous essayez de trouver la bonne sensation pour le gameplay.
Les leviers de conception peuvent remplacer des variables individuelles dans le code en tant que propriétés publiques, et leur portée peut être limitée à l'aide de l'attribut RangeAttribute d'Unity, qui limite les nombres flottants ou entiers de votre script à une certaine portée tout en leur permettant d'être affichés sous forme de curseurs dans l'inspecteur. L'objectif est de manipuler les leviers à la volée, et pas seulement en mode lecture, ce qui s'applique également si vous exécutez en mode édition ou si vous testez un outil.

Dans les jeux de survie, entre autres, le joueur s'attend à un éventail de choix qui entraînent des conséquences logiques et raisonnables, ce qui l'incite à trouver une solution à chaque défi. Comment concevoir un système de manière à ce que les défis et les solutions soient, dans une certaine mesure, le résultat de l'émergence ?
Prenons un exemple où le joueur doit rester dans une zone pour survivre, comme dans le jeu Don't Starve de Klei studio. Le joueur peut rester près d'un feu pour empêcher l'ennemi d'attaquer. Le feu peut également être utilisé pour faire cuire des aliments et garder les joueurs au chaud. Cependant, si le feu s'approche trop près du joueur, de la nourriture ou d'objets inflammables, il les brûlera.
Quel type de système est nécessaire pour créer des réactions en chaîne comme celle décrite ci-dessus ? Vous pourriez simplement créer un volume dans lequel le joueur se tiendrait et qui lui donnerait de la chaleur au fil du temps, ou créer un système de propagation linéaire du feu. Mais pourquoi ne pas l'aborder sous l'angle d'un concepteur plus centré sur le système ? Vous voulez obliger le joueur à réagir dans une situation qui est le résultat d'une réaction en chaîne de systèmes individuels de propagation du feu entrant en collision les uns avec les autres et avec d'autres systèmes existant dans le monde du jeu.

Vous pourriez avoir un système dans lequel les arbres poussent dans une zone de terrain définie autour d'un étang au fil du temps. Ces arbres germeront, puis grandiront jusqu'à ce que la limite d'espace soit atteinte. Lorsqu'ils arrivent à maturité, les arbres peuvent être coupés et transformés en bois, qui est bien entendu inflammable.
Le joueur peut utiliser ce bois pour construire des objets, comme une chaise en bois fantaisie, ou faire un petit feu de camp près de l'étang pour se réchauffer et se sécher après la baignade. Mais que se passe-t-il si vous donnez au joueur la possibilité d'allumer le feu de camp ?
Le système d'inflammabilité du bois n'est pas complexe, mais si quelque chose est en feu, il émet de la chaleur dans un rayon, et si cette valeur de chaleur est supérieure à la limite de l'objet en bois ou de l'arbre à proximité, ces objets prendront feu également (propagation simple). Ainsi, le joueur, en allumant son feu de camp, a mis le feu à sa belle chaise en bois. Le joueur doit maintenant attraper la chaise et la jeter dans l'eau pour éteindre le feu, mais pendant ce temps, le feu de camp met le feu à l'arbre le plus proche, et vous avez maintenant un feu de forêt sur les bras.
Même un système restreint comme celui-ci peut permettre aux joueurs de vivre des expériences amusantes et "non scénarisées". Il est également essentiel de se concentrer sur le résultat souhaité pour le joueur, plutôt que sur une conception trop étroitement liée à la réalité, qui vous donnera moins de possibilités de créer des résultats inattendus.
Dans cet exemple, dans Unity, vous pouvez créer des possibilités émergentes en stockant vos leviers de conception dans un ScriptableObject placé sur tout ce que vous voulez voir prendre feu. Commençons par étudier le bois dans un monde où un arbre mort est déjà en feu à côté du bord de l'eau mais penche vers l'eau, et où notre joueur a besoin de se réchauffer.
Dans cet exemple, le bois est recouvert d'un objet scriptable contenant diverses valeurs.


Examinons ces valeurs plus en détail :
- Température par défaut : Une valeur de remplacement, si rien n'est hérité d'un état global. Si les températures sont globalement élevées ou basses, nous pouvons avoir un impact sur le fonctionnement de l'ensemble du système, car des températures plus élevées pourraient provoquer un incendie de forêt, en supposant que tous les arbres utilisent le système de propagation des incendies.
- Température actuelle : La température d'un objet lorsqu'il se réchauffe ou se refroidit, ce qui détermine si un objet a brûlé ou non (si la valeur de la température actuelle est supérieure à la valeur de la résistance).
- Température de combustion : La température qu'un objet doit atteindre avant de s'enflammer.
- Taux de chauffage : La vitesse à laquelle l'objet se réchauffe lorsqu'il se trouve dans le rayon d'une autre source de chaleur.
- Taux de refroidissement : La rapidité avec laquelle l'article revient à sa température "non chauffée", que l'on pourrait appeler rétention ou qualité thermique, pour autant que le nom du levier de conception soit auto-descriptif.
- Taux de combustion : La vitesse à laquelle l'objet brûle au fil du temps
- Carburant : La quantité de carburant dont dispose l'objet lorsqu'il brûle
- Résistance à la chaleur : La force de la chaleur dans le rayon
- Rayon de chaleur : Portée ou extension de la chaleur
Avec un peu de code de jeu, vous pouvez faire en sorte qu'un objet situé à côté d'un autre prenne feu. Vous pouvez enregistrer les profils de vos prototypes et essayer des configurations extrêmement différentes jusqu'à ce que vous trouviez les points de rupture, puis fixer ces valeurs avec des attributs.

Il n'est pas prévu que le feu soit bloqué par l'eau, mais s'il n'y a rien d'inflammable sur l'eau, le feu ne se propagera pas s'il ne peut pas atteindre l'autre côté, à moins que vous n'ajoutiez un nouveau système.
Cet exemple de système de propagation d'un incendie permet de créer le même résultat en jouant sur le combustible, la vitesse de combustion et la puissance calorifique. Vous pouvez également créer de nouveaux résultats, par exemple en remplaçant le carburant par la "santé", afin de disposer d'une plage constante pour contrôler le moment où un arbre tombe sans perdre de fonctionnalité. Lorsqu'un arbre est en mauvaise santé, la probabilité qu'il tombe est élevée. Désormais, lorsqu'un arbre en feu atteint un niveau de santé faible, il peut tomber, ce qui crée un chaos absolu lorsque le joueur ne le gère pas dans une zone où se trouvent des objets combustibles.
Au fur et à mesure que vous ajoutez des systèmes à votre environnement, vous créez un écosystème de systèmes qui peuvent réagir les uns avec les autres. En supposant que le joueur puisse récolter, construire et fabriquer des objets en bois et que tous héritent de notre système de propagation du feu, le chaos pourrait être au coin de la rue si vous ne faites pas attention !

Vous pouvez créer une configuration de propagation d'incendie très volatile en réduisant le seuil de combustion et en augmentant la vitesse d'échauffement afin que les objets se consument plus rapidement. Augmentez le rayon pour obtenir une propagation plus rapide et plus incontrôlable. Le taux d'échauffement est limité de 0 à 50 pour assurer une certaine granularité ; l'intensité de la chaleur peut être utilisée pour multiplier cette valeur, mais il est préférable de la maintenir dans une fourchette raisonnable. Une puissance calorifique de 4 étend le taux d'échauffement à une fourchette de 0 à 200, ce qui est excessif et provoquerait un incendie de forêt en quelques secondes. Comme le joueur n'a pas le temps de réagir pour contrôler le brasier, ce n'est pas une grande expérience de jeu.

L'augmentation du seuil de combustion à 300 permet de mieux équilibrer le système de propagation de l'incendie. Le joueur peut effectuer d'autres tâches avant qu'un incendie ne se déclare, et lorsqu'il se déclare, il a le temps de réagir et de le maîtriser s'il est rapide. Surtout s'ils ont la possibilité d'abattre des arbres, de construire des barrières ou d'avoir accès à un système d'eau tout aussi systémique et simple.
Vous pouvez étendre le système de propagation de l'incendie en introduisant une valeur de résistance pour les objets situés dans le rayon de chaleur d'un incendie. Cela permettrait d'avoir des incendies de températures variables, ou d'introduire des revêtements résistants au feu sur les structures comme une amélioration possible. C'est probablement exagéré, mais c'est un exemple de la façon de penser la conception du gameplay d'une manière systématique qui peut donner au joueur plus de possibilités de survivre et de s'épanouir dans un environnement forestier froid en interagissant avec le système de feu.

L'exemple des systèmes de propagation des incendies montre comment on peut prendre une idée de mécanisme linéaire et la transformer en une expérience intéressante qui permet au joueur de relever des défis en apprenant et en comprenant les systèmes du jeu. Et lorsque votre système n'a pas besoin d'imiter la réalité, vous n'avez pas à tenir compte d'une complexité et d'abstractions supplémentaires.
Avec cet exemple simple, ce billet explore comment vous pouvez concevoir des systèmes modulaires, petits et simples avec une interactivité qui crée un plus grand écosystème pour le gameplay qui peut être équilibré avec des leviers de conception que vous pouvez peaufiner et itérer avec l'apport de vos collègues. Ces éléments peuvent créer des moments inattendus d'amusement, de plaisir et de suspense pour vos joueurs, contribuant à faire de votre jeu une expérience vraiment unique.
Obtenez beaucoup plus de conseils, d'instructions et d'inspiration pour concevoir et dynamiser le gameplay dans Unity dans notre nouvel e-book disponible gratuitement.
