Lors d’un projet, spécifique par définition, on se retrouve souvent à avoir des besoins qui ne sont pas prévus par l’éditeur. Il faut donc faire des séries de manipulations fastidieuses et répétitives pour arriver au résultat voulu.
Mais Unity3D comprends un système de scripts dynamiques intégrables à l’éditeur pour effectuer… toutes sortes de choses. Ce que vous voulez en fait !
Disclaimer
Cet article a été originalement écrit le 05/09/2014 sur mon précédent blog. Certaines informations présentées ici peuvent donc ne plus fonctionner telles quelles.
Introduction
Dans votre exploreur d’Assets, il y a deux noms de dossiers spéciaux : « Resources » et « Editor« . Il est conseillé de ne les utiliser que dans le cadre de ces spécificités, dans un but de clarté. Je ne vais pas parler de Resources car il ne nous intéresse pas ici. Nous allons parler de Editor.
Comme son nom l’indique, il y a un rapport avec l’éditeur. En effet, Unity va chercher dans tous les dossiers nommés « Editor » contenus dans votre dossier d’Assets (et ce récursivement) à la recherche de scripts plugin à brancher dans l’éditeur. Via ces scripts plugin, vous allez pouvoir :
- Créer un nouveau menu dans la barre d’état
- Créer un nouvel élément dans un menu existant
- Créer une fenêtre personnalisée avec ce que vous voulez dedans
Tout cela se fait via des scripts. Il va donc vous falloir mettre les mains dans le C# !
Créer un menu dynamiquement
Commençons par le commencement et créons un nouveau menu ! Pour se faire, voilà la marche à suivre. Commencez par créer une classe qui étend de ScriptableObject. Enlevez les méthodes Start et Update générées par défaut ainsi que l’héritage de MonoBehaviour pour avoir une classe toute simple (et vide pour le moment). La suite se complique un tout petit peu, il faut utiliser des attributs.
« Les attributs fournissent une méthode puissante pour associer des informations de déclaration au code C# (types, méthodes, propriétés, etc.) »
Pour faire simple, les attributs sont des meta informations que l’on peut insérer dans le code (pas n’importe où) pour indiquer au système des informations supplémentaires. C’est via ces attributs que nous allons définir nos menus et les actions associées au clic sur l’élément de menu : cliquer sur le menu exécutera une méthode statique de votre plugin.
Commençons par créer la méthode qui va exécuter nos traitements spécifiques :
public class MyCustomScript : ScriptableObject { public static void MyCustomAction() { Debug.Log("Hello !"); } }
A l’intérieur de cette méthode, vous pouvez accéder à tout votre projet ainsi que toutes les classes statiques de l’éditeur.
Ecrire cette simple méthode n’est pas suffisante pour générer un menu. C’est là que les attributs entrent en jeu. Maintenant que vous avez votre action, on va la lier dans les menus comme ceci :
using UnityEditor; public class MyCustomScript : ScriptableObject { [MenuItem("Mon menu/Mon bouton")] public static void MyCustomAction() { Debug.Log("Hello !"); } }
N’oubliez pas d’importer le package UnityEditor ! L’attribut MenuItem doit obligatoirement contenir un « / ». En effet, vous ne pouvez pas créer de menu-bouton. Votre élément de menu doit obligatoirement être dans un menu parent. Ici, le menu parent est « Mon menu », et l’élément de menu associé sera « Mon bouton ». Revenez à l’éditeur, laissez lui le temps de tout recompiler…
Vous devriez voir apparaître un nouveau menu dans la barre en haut. Si ce n’est pas le cas, cliquez quelque part dans le menu.
Et si vous cliquez sur le bouton…
Et voilà le travail, vous avez un menu personnalisé ! Notez que de la même manière vous pouvez ajouter des entrées également dans les menus « de base » de l’éditeur :
Après, tout n’est qu’une question d’organisation et de bon sens. A vous de voir !
Créer une fenêtre
Pouvoir appeler du code personnalisé directement depuis l’éditeur est très pratique. Mais pour des manipulation plus complexes, il est parfois nécessaire d’avoir un « wizard », une petite fenêtre dans laquelle saisir des informations. L’approche est identique : créer une méthode statique qui sera accessible depuis le menu. Dans cette méthode, nous allons instancier et afficher notre fenêtre.
Vous devrez créer une classe pour gérer la fenêtre en elle même. Il est possible de placer la méthode statique d’ouverture de la fenêtre dans la même classe. C’est ce que nous allons faire, c’est plus pratique dans le cadre de ce tutoriel. En revanche, si vous avez beaucoup de fenêtres et / ou menus personnalisés, il peut être intéressant de centraliser toutes les définitions de menus dans une classe à part.
Pour créer cette fenêtre il faut créer un script qui étend d’une autre classe : EditorWindow :
using UnityEditor; public class MyCustomWindow : EditorWindow { [MenuItem("Mon Menu/Ma fenêtre")] public static void MyCustomAction() { EditorWindow.GetWindow(typeof(MyCustomWindow)); } }
Pour instancier notre fenêtre il faut procéder comme ci dessus. En gros vous demandez à l’éditeur de vous « fournir » votre fenêtre personnalisée. La fenêtre est d’ores et déjà utilisable. Testez par vous même en cliquant sur le bouton dans votre menu…
Tada ! Vous voilà avec une fenêtre… vide ! La fenêtre est vide tout simplement parce que vous n’avez encore rien mis dedans. Et pour mettre des choses dedans, c’est relativement simple : il faut utiliser le moteur de GUI d’Unity (oui, le vieux).
Il vous faut donc créer votre méthode OnGUI et créer l’interface de vos rêves, ainsi que les contrôles et actions associées. Pour reprendre l’exemple du « Hello World » :
public class MyCustomWindow : EditorWindow { [MenuItem("Mon Menu/Ma fenêtre")] public static void MyCustomAction() { EditorWindow.GetWindow(typeof(MyCustomWindow)); } void OnGUI() { if (GUILayout.Button("Dire bonjour")) { Debug.Log("Bonjour !"); } } }
Ce qui nous donne le résultat suivant, si on clique sur le bouton :
Votre fenêtre est opérationnelle. Vous pouvez maintenant ajouter les champs qui vous seront utiles, faire des transformations sur un objet sélectionné… ou tout ce que vous pourriez avoir besoin dans vos projets !
Dernier point qui tient plus du détail que de l’utile (quoi que…), vous pouvez évidemment donner un nom à votre fenêtre. Pour se faire, il faut récupérer la fenêtre dans la méthode statique de création et initialiser ce qui vous intéresse :
[MenuItem("Mon Menu/Ma fenêtre")] public static void MyCustomAction() { var window = EditorWindow.GetWindow(typeof(MyCustomWindow)); window.title = "Ma fenêtre"; }
De cette manière, vous donnez un nom à votre fenêtre, ce qui est quand même beaucoup plus explicite !
Voilà de quoi modifier l’éditeur selon vos besoin. Sur ce, amusez-vous bien à personnaliser Unity3D !