Le Prefab, votre futur meilleur ami

banner

Dans le jeu vidéo, comme dans d’autres domaines informatiques d’ailleurs, certains éléments sont récurrents. C’est à dire que vous allez les retrouver plusieurs fois à des endroits différents. Mais ces éléments doivent avoir le même comportement de partout. Corollaire : on aimerait pouvoir modifier ce comportement une seule fois et qu’il soit répercuté partout où il est utilisé. Exemple le plus simple : une lampe. Elle doit éclairer de la même manière où qu’elle soit.

Si ce concept ne vous est pas familier, vous pourriez être tenté de faire du copié collé de partout sur votre scène, jusqu’au moment où… vous vous rendrez compte que vos objets ne sont pas à la bonne taille, qu’il y a un couac, que ce n’est pas tout à fait ce que vous vouliez.

Le Prefab est là pour ça, et c’est ce que nous allons voir ensemble dans cet article.

Disclaimer

Cet article a été originalement écrit le 27/06/2014 sur mon précédent blog. Certaines informations présentées ici peuvent donc ne plus fonctionner telles quelles.

Un Prefab c’est quoi ?

Commençons par le commencement avec un peu de théorie. Un Prefab, c’est quoi exactement ? Un Prefab, c’est un modèle / patron / schéma de GameObject (j’utiliserai le terme « patron » pour la suite). En gros, c’est comme un plan de montage Ikéa… mais pour Unity. 🙂

Un Prefab va donc contenir le patron d’un GameObject. Ce n’est pas une instance de ce GameObject mais sa représentation, c’est important de bien comprendre ça pour continuer : modifier l’instance d’un Prefab, ce n’est pas la même chose que modifier le Prefab lui même. Et cette nuance peut avoir de fortes conséquences alors prenez le temps de bien assimiler la différence.

Un peu partout, les gens font un abus de langage en utilisant le terme Prefab pour dénominer le patron ou l’instance selon le contexte. C’est un raccourcis qui peut induire en erreur, surtout si on creuse un peu en utilisant toutes les fonctionnalités. Je ferai donc clairement la distinction entre le Prefab et l’instance du Prefab.

C’est tout ce qu’il y a à savoir pour le moment : un Prefab, c’est un patron de GameObject.

Note importante : Lorsque l’on crée un Prefab, tout ce qui définit le GameObject et ses enfants est enregistré. Transform y compris. Nous verrons plus bas l’impact que ça peut avoir.

En avant la pratique

Créer un Prefab

Maintenant que vous savez ce qu’est un Prefab, il est temps d’en créer un. Il y a plusieurs manières de faire. La première est de le créer directement dans vos assets en faisant clic droit > Create > Prefab.

prefab1

Hop, vous voilà avec un Prefab fraîchement créé :

prefab2

 

Notez son icone, un cube gris. Dans les assets, un Prefab est représenté par un cube. Ici, on le voit en gris. Cela veut dire que le Prefab est vide, il ne représente donc rien (pour le moment).

La seconde façon de faire est de glisser – déposer un GameObject depuis la hiérarchie vers vos assets (l’inverse de ce que vous faites pour ajouter un asset sur la scène).

fromScene

En faisant comme ça, vous venez de créer un Prefab à partir de ce GameObject. Notez que le cube est cette fois bleu, ce qui nous indique que le patron contient quelque chose ! C’est la façon la plus simple et la plus rapide pour en créer un. Notez que dans la hiérarchie, la couleur du nom de ce GameObject est passée en bleu également. Cette couleur nous indique que ce GameObject est l’instance d’un Prefab.

Pour revenir à la première façon de faire, une fois que vous avez créé un Prefab vide, vous pouvez le lier à un élément de la scène. Sélectionnez un GameObject dans votre hiérarchie et faites un drag’n’drop sur le Prefab dans les assets. Le Prefab passera en bleu et contiendra le patron du GameObject que vous venez de lui « donner ».

La seconde méthode est selon moi la plus simple. En pratique dans un projet réel, vous allez créer un GameObject, le paramétrer en ajoutant tous les composants qui vous intéressent, puis enfin en faire un Prefab pour le réutiliser ailleurs. Une fois votre GameObject paramétré, il ne vous reste qu’à le déposer dans vos assets pour en créer un Prefab.

A partir de là, les choses commencent à être intéressantes.

Utiliser et mettre à jour son Prefab

Créons on Prefab simple pour la suite. Imaginons un cube lumineux avec une petite hiérarchie. Créez donc un GameObject vide qui sera notre parent et ajoutez y un cube et une source de lumière.

cube

Note importante : Il est tout à fait possible (et même conseillé) de créer des arborescences de GameObjects pour vos éléments complexes. Créer un Prefab à partir du GameObject parent prendra en compte tous ses enfants dans le patron.

Créez un Prefab de cette hiérarchie en sélectionnant bien le parent (LightCube ici). Notez que les éléments de la hiérarchie passent en bleu. Notez également que dans les Assets, vous pouvez voir la hiérarchie du patron, un peu comme dans la hiérarchie de la scène et que chaque enfant est un Prefab lui aussi :

hierarchy

Vous avez créé votre premier Prefab. Il est temps de peupler votre scène avec plusieurs instances de ce Prefab !

cubes

Vous avez maintenant plusieurs instances de ce Prefab sur votre scène, tout va bien dans le meilleur des mondes… jusqu’à ce que vous deviez ajuster des choses. Si vous n’utilisez pas de Prefabs, c’est à de moment là que vous commençez à paniquer vu la quantité d’objets de votre scène…

Heureusement, vous suivez ce tuto et utilisez donc des Prefabs ! Mais comment modifier ce patron et l’appliquer à toutes ses instances ?

C’est très simple mais on peut vite faire n’importe quoi alors suivez bien. Sélectionnez le GameObject parent de l’instance du Prefab dans la hiérarchie. Dans l’inspecteur, tout en haut, vous devez voir apparaître 3 boutons supplémentaires, juste en dessus du composant Transform :

 prefab_buttons

D’ailleurs, des fois qu’on soit pas sûr, il est bien précisé qu’il est question de Prefab ici !

Select

Ce bouton n’est pas celui qui vous intéressera le plus. Il permet de sélectionner dans les assets le Prefab concerné. Ce n’est pas inutile, loin de là. Lorsque vous aurez des assets dans tous les sens, de la musique, des Prefabs, des sprites, des shaders… il y a de fortes chances que plus le temps passe, plus la structure de vos dossiers d’assets se complexifie… et que les choses commencent à se cacher dedans, même en classant bien. Ce bouton est un bon moyen de retrouver la trace du Prefab associé.

Revert

Celui là est déjà beaucoup plus utile. Il permet tout simplement de réinitialiser l’instance du Prefab courant aux paramètres actuels du Prefab. En gros, c’est la même chose qu’une réinitialisation des paramètres d’usine pour un smartphone. Le GameObject reprendra alors l’état défini dans le Prefab.

Ce bouton est intéressant pour faire des essais. Vous partez d’une base (le Prefab) et vous pouvez modifier des choses pour tester, voir si ça va bien… Et si vous cassez tout… hop ! Revert et tout est de retour à la normale.

Apply

Ce bouton permet d’appliquer toutes les modifications que vous avez faite sur cette instance au Prefab associé. Ce faisant, toutes les instances de ce Prefab sur la scène seront immédiatement mises à jour avec les nouveaux paramètres.

Si vous suivez un peu, vous devez constater un problème majeur : si tout est copié du GameObject, alors toutes mes instances de ce Prefab vont se retrouver au même endroit sur la scène ! Et ça c’est pas cool du tout ! Ben oui, on copie aussi le composant Transform

Et bien… non ! Le composant Transform du parent est une exception à la règle. Lui et seulement lui. Les composants Transform des enfants sont, eux, mis à jour (nous verrons ça plus bas). Si vous déplacez une instance de Prefab sur la scène et appuyez sur Apply, vous pouvez constater en sélectionnant le Prefab que son composant Transform est modifié en conséquence, mais que ça n’a absolument aucun impact sur les autres instances de ce Prefab de la scène.

L’intérêt de l’enregistrement du composant Transform dans un Prefab est assez faible et (à ma connaissance) ne sert que dans un cas de figure : le spawn d’une instance du Prefab sur la scène. Si vous faites un drag’n’drop du Prefab dans la hiérarchie de la scène, l’instance sera placée à la position du Transform défini dans le Prefab. Mais il y a de très fortes chances pour que vous le déplaciez après coup selon vos besoins… De même, si vous créez une instance d’un Prefab à la volée dans vos scripts, si vous ne donnez pas de position de spawn, l’instance apparaîtra à la position du Transform définie dans le Prefab. Mais là encore, dans la plupart des cas, vous allez spécifier un point de spawn. Donc c’est là… mais ça sert pas à grand chose.

Faisons un essai en tournant le cube sur lui même (rotation xyz de 45, 45, 0):

update1

En appliquant les modifications… BAM ! Toutes les instances s’alignent !

update2

Allons maintenant plus loin avec la personnalisation d’instances de Prefabs. Dans certains cas particuliers, vous allez avoir besoin de modifier quelques paramètres d’une seule instance d’un Prefab commun. Par exemple : l’un de nos cube lumineux éclairera en rouge parce qu’il est cassé. Mais vous voulez quand même qu’il soit mis à jour lorsque vous allez ajuster le Prefab, en conservant cette valeur précise.

C’est tout à fait possible. Lorsque vous sélectionnez l’instance d’un Prefab et que vous modifiez une valeur dans l’inspecteur, vous remarquerez que cette propriété est passée en gras. Cela signifie que cette valeur est différente de celle du Prefab associé. Cela veut dire deux choses :

  • Soit on a oublié de mettre à jour le patron à partir des nouvelles valeurs
  • Soit c’est une instance personnalisée et dans ce cas, les valeurs en gras ne seront plus jamais mises à jour en cas de modification du patron.

Pour revenir en arrière, c’est possible en faisant un Revert global sur toute l’instance via le bouton vu plus haut, soit sur un seul composant en passant par le menu contextuel sur la roue dentée :

modifs

ci en rouge à gauche, on peut voir que la propriété Center a été modifiée par rapport au Prefab, et plus précisément que c’est la composante en X qui est différente.

Faisons un essai avec nos cubes. Prenez en un et changez sa couleur. La ligne apparaît maintenant en gras :

color

Sélectionnez un autre Prefab et modifiez la taille du cube et la couleur de l’éclairage puis cliquez sur Apply. Constatez le résultat :

green

green2

Seule la couleur des instances non personnalisées ont été mises à jour. Essayons maintenant de modifier la taille du cube.

cubesscale

cubesscale2

Cette fois, tous les cubes ont été mis à jour, y compris celui dont l’instance est personnalisée… Mais elle conserve bien sa couleur.

Vous voilà maintenant bien armé pour vous attaquer à un projet plus conséquent. Aller, au travail maintenant !

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s