
Cette page explique comment utiliser des énumérations basées sur ScriptableObject dans votre projet Unity.
Ceci est le troisième d'une série de six mini-guides créés pour aider les développeurs Unity avec la démo qui accompagne le livre électronique, Créer une architecture de jeu modulaire dans Unity avec des ScriptableObjects.
La démo s'inspire des mécaniques de jeu d'arcade classiques de balle et de palette, et montre comment les ScriptableObjects peuvent vous aider à créer des composants qui sont testables, évolutifs et conviviaux pour les concepteurs.
Ensemble, le livre électronique, le projet de démo et ces mini-guides fournissent les meilleures pratiques pour utiliser les modèles de conception de programmation avec la classe ScriptableObject dans votre projet Unity. Ces conseils peuvent vous aider à simplifier votre code, réduire l'utilisation de la mémoire et promouvoir la réutilisabilité du code.
Cette série comprend les articles suivants :
Avant de plonger dans le projet de démonstration ScriptableObject et cette série de mini-guides, rappelez-vous qu'à leur cœur, les modèles de conception ne sont que des idées. Ils ne s'appliqueront pas à chaque situation. Ces techniques peuvent vous aider à apprendre de nouvelles façons de travailler avec Unity et les ScriptableObjects.
Chaque modèle a ses avantages et ses inconvénients. Choisissez uniquement ceux qui bénéficient de manière significative à votre projet spécifique. Vos concepteurs s'appuient-ils fortement sur l'éditeur Unity ? Un modèle basé sur ScriptableObject pourrait être un bon choix pour les aider à collaborer avec vos développeurs.
En fin de compte, la meilleure architecture de code est celle qui convient à votre projet et à votre équipe.

Les énumérations sont un moyen pratique de gérer un ensemble fixe de valeurs nommées dans votre code. Cependant, elles comportent certaines limitations. Puisque les valeurs d'énumération sérialisées sont stockées sous forme d'entiers plutôt que sous leurs noms symboliques, supprimer ou réorganiser une valeur peut entraîner un comportement incorrect ou inattendu. Cela signifie que les énumérations, surtout lorsque vous en avez beaucoup, peuvent créer des maux de tête dans le développement Unity.
La méthode standard
Voici à quoi ressemble une énumération typique :
[System.Serializable]
public enum HandGestures
{
Pierre,
Article,
Ciseaux
}
Vous pouvez sérialiser un énum avec l'attribut System.Serializable et il apparaît dans l'Inspecteur.
Le problème
Réorganiser ou supprimer une valeur peut causer des problèmes. Parce que chaque valeur est en interne un entier, ce qu'elle représente peut devenir quelque chose de différent. Dans l'exemple donné, supprimer la valeur Papier ferait que Ciseaux assume la valeur de 1.
Ou, si nous ajoutions une valeur comme dans l'exemple ci-dessous.
La valeur d'énum sélectionnée changerait si elle vient après l'entrée supprimée.
Cela peut causer des problèmes lors de la maintenance et de la mise à jour des projets, en particulier lorsque votre énum contient de nombreuses valeurs. Vous pouvez atténuer ce problème en laissant un élément vide ou inutilisé, ou en définissant explicitement des valeurs entières. Cependant, aucune des solutions n'est idéale.

Les énumérations basées sur ScriptableObject vous donnent la fonctionnalité des énumérations traditionnelles mais sont stockées en tant qu'actifs individuels. Par exemple, regardez le ScriptableObject PlayerIDSO dans le projet PaddleBallSO dans l'exemple ci-dessous.
Essentiellement, c'est un ScriptableObject vide.
Vous pouvez l'utiliser pour créer un certain nombre d'actifs ScriptableObject dans le projet, comme P1, P2, etc. Même lorsqu'ils ne contiennent aucune donnée, vous pouvez utiliser les ScriptableObjects pour la comparaison. Il suffit de créer un nouvel actif ScriptableObject dans le projet et de lui donner un nom.
Vous pouvez créer autant d'ID de joueur que vous en avez besoin dans le projet et facilement passer de l'un à l'autre. Il suffit de changer l'actif assigné dans le script GameDataSO.
Si vous vérifiez l'égalité, cela fonctionne de manière similaire à un enum. Deux variables font-elles référence au même ScriptableObject ? Si oui, ce sont le même type d'élément. Sinon, ce ne sont pas.
Même sans données supplémentaires, le ScriptableObject représente une catégorie ou un type d'élément.
Dans PaddleBallSO, le PlayerIDSO devient une désignation d'équipe. Nous utilisons les actifs P1 et P2 dans le GameDataSO pour différencier les deux palettes.
Le script GameSetup attribue à chaque palette un ID de joueur. Pendant le jeu, les scripts Paddle comparent l'entrée du joueur avec l'ID d'équipe désigné.
Cela a des applications pour tout type de jeu multijoueur. Alternativement, envisagez de les adopter partout où vous utilisez un enum.
Puisqu'ils sont simplement des attributions dans l'Inspector, les ScriptableObjects ne sont pas soumis aux mêmes problèmes de renommage et de réorganisation.
Vous voulez changer les noms d'identifiant en « Joueur1 » ou « Joueur2 », respectivement ? Vous pouvez le faire, et tout continue à fonctionner. Ajouter plus de ScriptableObjects ? Pas de problème – l'attribution d'actifs dans l'Inspector reste la même.

Ce comportement est utile pour créer du gameplay. Dans la démo Patterns, cliquez sur le bouton Switch Enum pour changer d'équipe. Un MonoBehaviour sur le DemoBall met à jour le SpriteRenderer en conséquence.
La balle inflige-t-elle des dégâts à un Bloc lorsqu'elle entre en collision ? Découvrez-le en effectuant un test rapide d'égalité. Voici une façon de les comparer dans l'exemple de code ci-dessous.
Cette méthode peut déterminer si deux GameObjects sont dans la même équipe, ce qui est utile lors de la vérification des interactions amicales ou ennemies. Cette simple comparaison peut s'appliquer aux ramassages d'objets, aux dégâts ou à tout autre élément ayant une "équipe" ou un "alignement".
La partie amusante se produit lorsque vous ajoutez de la logique à vos ScriptableObjects. Contrairement à un enum conventionnel, un ScriptableObject peut avoir des champs et des méthodes, en plus de contenir des données.
Utilisez-les pour que chaque ScriptableObject puisse avoir une logique de comparaison spécialisée. Par exemple, vous pourriez avoir un ScriptableObject qui définit des effets de dégâts spéciaux (par exemple, froid, chaleur, électrique, magique, etc.).
Si votre application nécessite un système d'inventaire pour équiper des objets de gameplay, les ScriptableObjects peuvent représenter des types d'objets ou des emplacements d'armes. Certains personnages ne sont-ils pas autorisés à tenir certains objets ? Certains objets sont-ils magiques ou ont-ils des capacités spéciales ? Les enums basés sur ScriptableObject peuvent ajouter des méthodes pour vérifier cela.
Le MonoBehaviour DemoBall dans l'exemple précédent inclut la méthode AreEqual pour comparer les ScriptableObjects. Lors de l'extension du comportement, vous pouvez regrouper la logique de comparaison à l'intérieur du ScriptableObject lui-même.
Dans la démo Patterns, vous pourriez modifier la balle pour qu'elle soit plus sélective lors de la collision avec un objet. Regardez un objet polyvalent pour la collision dans l'exemple de code ci-dessous.
Cela pourrait atteindre des résultats similaires à la démo actuelle, mais il a maintenant un champ de m_Weakness. Cela permet à chaque ScriptableObject de définir un autre ScriptableObject à détruire lors d'une collision.
Plutôt que d'appeler la méthode AreEqual, chaque ScriptableObject gère simplement sa propre logique de comparaison.
Le résultat est plus flexible et extensible. Au lieu de faire détruire la balle à un bloc d'une équipe différente, vous pouvez être spécifique. Plusieurs balles dans la scène pourraient détruire différents blocs, en fonction de leurs CollisionItems individuels.
Cela prépare le terrain pour des interactions différentes et plus complexes. Si vous vouliez créer un système de pierre-papier-ciseaux, vous pourriez définir trois ScriptableObjects : Pierre, Papier et Ciseaux. Chacun pourrait avoir sa propre m_Weakness unique et utiliser la méthode IsWinner pour gérer les interactions.
Contrairement aux enums, les ScriptableObjects rendent ce processus modulaire et adaptable. Il n'est pas nécessaire de s'appuyer sur des structures de données supplémentaires ou d'ajouter une logique supplémentaire pour synchroniser avec un ensemble de données séparé. Ajoutez simplement un champ et/ou une méthode supplémentaires pour gérer la logique.
Une fois que vous êtes familiarisé avec les enums basés sur ScriptableObject, vous constaterez qu'ils peuvent améliorer votre flux de travail, surtout lorsque vous travaillez avec des coéquipiers. Comme ce sont des actifs, les mettre à jour crée moins de conflits de fusion, réduisant le risque de perte de données.
Ajouter de nouveaux enums basés sur ScriptableObject est comme créer un autre actif. Contrairement aux enums traditionnels, ajouter de nouvelles valeurs ne cassera pas votre code existant. De plus, Unity dispose déjà d'outils intégrés pour rechercher, filtrer et organiser, tout comme n'importe quel autre actif.
En bonus, utiliser l'interface utilisateur de glisser-déposer de l'éditeur permet à vos concepteurs d'étendre les données de gameplay sans soutien supplémentaire d'un développeur logiciel. Vous devrez toujours coordonner comment configurer les champs au départ, mais les concepteurs peuvent ensuite remplir ces champs avec des données par eux-mêmes.

Les énumérations basées sur ScriptableObject sont une ressource supplémentaire que votre équipe peut utiliser pour améliorer la collaboration et l'efficacité.
Lisez-en plus sur les modèles de conception avec ScriptableObjects dans notre e-book technique Créer une architecture de jeu modulaire dans Unity avec ScriptableObjects. Vous pouvez également en savoir plus sur les modèles de conception de développement Unity courants dans Améliorez votre code avec des modèles de programmation de jeux.