Aller au contenu
← Tous les articles

février 2024 · 5 min de lecture

De l'ordre au chaos : maîtriser l'aléatoire avec la technique du bucket

Un bucket mélange une liste pour tirer chaque valeur une seule fois dans un ordre aléatoire, idéal pour vos prefabs ou cartes dans Unity.

Un bucket, aussi appelé bean bag (sac de billes), est le moyen le plus simple de transformer une liste ordonnée en une liste aléatoire dans laquelle vous ne tombez jamais deux fois sur le même objet. En fait, c’est pratiquement l’asset que j’utilise le plus dans mes projets, et vous devriez peut-être en faire autant si ce n’est pas encore le cas : voyons ensemble le comment et le pourquoi.

Quelle bille vais-je tirer ensuite ? (Imaginé par moi, créé avec l’IA)

Pourquoi l’utiliser

Imaginons que vous ayez un jeu de deck building : vous avez sûrement mis au point une façon astucieuse d’ajouter des cartes au deck, et au bon moment, vous devez décider dans quel ordre les cartes seront placées dans le deck pendant la partie. Ou imaginons que vous ayez un runner, et que chaque portion du parcours soit un prefab que vous devez instancier dans la scène. Vous devez alors décider quel est le prochain prefab à instancier.

Il existe plusieurs façons de faire. L’une d’elles consiste à lister les prefabs qui peuvent suivre un autre prefab, ce qui vous permet de contrôler le design du parcours et de vous assurer qu’il n’y a aucun problème quand deux prefabs se suivent. Ou, s’il s’agit d’un simple prototype, de choisir simplement les prefabs dans une liste de prefabs. Dans les deux cas, vous devez récupérer un prefab parmi toute la liste de prefabs, qu’il s’agisse de la liste complète ou d’un sous-ensemble.

La façon la plus simple de le faire ? Récupérer un prefab au hasard dans cette liste. Seulement, la méthode aléatoire pose deux problèmes majeurs :

  • elle peut vous donner plusieurs fois le même nombre tout en en laissant d’autres de côté, ce qui produit une distribution non linéaire qui peut agacer le joueur
  • elle n’est pas fiable d’une plateforme à l’autre : obtenir des valeurs aléatoires correctes dans l’éditeur Unity ne sera pas reproductible sur mobile ou sur console (après tout, c’est une valeur aléatoire).

C’est là que le bucket devient utile : il vous permet d’obtenir chaque nombre d’une liste exactement une fois, dans un ordre aléatoire. Ainsi, tous vos prefabs seront utilisés une fois avant que le joueur ne retombe sur le même prefab.

Notez que si vous souhaitez avoir plusieurs fois le même prefab, vous pouvez utiliser plusieurs nombres associés au même prefab, comme une liste pondérée.

Comment l’utiliser

Cet outil est extrêmement simple, un bucket fonctionne en trois phases :

  • générer
  • mélanger
  • tirer

1. Générer

Créez un nouveau Bucket et indiquez le nombre de valeurs que vous voulez en obtenir. Lors de sa création, il génère une liste allant de 0 jusqu’à ce nombre moins un (c’est du C#, donc les index de liste commencent à 0). Une fois le package importé (voir à la fin de l’article), utilisez le code ci-dessous pour un échantillon de 25 nombres aléatoires.

import FredericRP.BucketGenerator;
// ...
var bucket = new Bucket(25);

2. Mélanger

Cela se fait en interne : à partir de la liste générée, le bucket mélange l’ordre de la liste avant le premier appel.

Il n’y a aucun code à écrire pour cela, puisque c’est fait automatiquement à la création de la classe.

3. Tirer

Ensuite, chaque fois que vous voulez un nombre aléatoire, récupérez-le depuis le bucket : il vous donne le nombre courant de la liste, le retire et passe au suivant. Appelez simplement la méthode GetNumber comme ci-dessous.

var myRandomNumber = bucket.GetNumber();

Ces étapes simples sont illustrées dans l’image ci-dessous.

l’utilisation du bucket en trois étapes : générer, mélanger, tirer

Une fois que tous les nombres ont été donnés, tout recommence. Si vous l’avez précisé lors de la phase de construction, la liste est mélangée à nouveau quand l’index est remis à zéro, ce qui donne l’impression d’un tirage vraiment aléatoire.

Pour simplifier et optimiser le bucket, la liste n’est générée qu’une seule fois et nous ne stockons que l’index dans la liste. Une fois que l’index atteint la fin de la liste, il est remis à zéro.

Attention : lorsque vous atteignez la fin de la liste, le mélange peut faire en sorte que le premier élément soit le même que le dernier de la phase de génération précédente. Dans ce cas précis, vous pouvez donc obtenir deux fois de suite le même nombre !

Bucket Generator sous forme de package

Comme les autres outils que je partage, celui-ci est disponible dans un package open source sur le dépôt de packages openupm. Pour importer n’importe lequel de mes outils disponibles sur OpenUPM, suivez les étapes ci-dessous.

1. Ajouter openUPM comme scoped registry dans Unity

Depuis le projet dans lequel vous voulez ajouter votre package, allez dans vos project settings, dans la section nommée package manager, où vous pouvez ajouter un scoped registry.

Pour un même registry, openUPM, vous pouvez ajouter plusieurs scopes si vous y trouvez d’autres assets utiles : veillez donc à ajouter tous les scopes que vous souhaitez pour que Unity aille les chercher au bon endroit. Commencez par ajouter « com.fredericrp », puis cliquez sur Apply.

Ajouter un scoped registry dans les project settings

2. Importer le package depuis le Package Manager

Une fois cela fait, vous verrez les registries correspondants dans le Package Manager de Unity, dans la section « My Registries » : mes packages sont regroupés sous le nom « FredericRP ». Comme pour n’importe quel autre package, vous pouvez installer, mettre à jour et supprimer les packages directement ici, et ils apparaîtront dans le dossier « Packages » de votre projet.

Retrouvez le Generic Singleton et les autres packages juste ici !

C’est l’un des nombreux outils que je partage sur openUPM : suivez-moi pour comprendre et découvrir tous les autres outils que je partage, et suivre mon parcours avec Unity !

Si cet article vous a plu, n’hésitez pas à applaudir ou à laisser un commentaire, merci de l’avoir lu !