Custom Editors

Outras versões

Não é possível acessar outras versões offline!

Uma chave para aumentar a velocidade de criação do jogo é criar editores personalizados para componentes comumente usados. Por exemplo, vamos usar este script muito simples que sempre mantém um objeto olhando para um ponto. Adicione este script ao seu projeto, e coloque-o em um cubo do gameobject em sua cena. O script deve ser chamado “LookAtPoint”

//C# Example (LookAtPoint.cs)using UnityEngine;public class LookAtPoint : MonoBehaviour{ public Vector3 lookAtPoint = Vector3.zero; void Update() { transform.LookAt(lookAtPoint); }}
//JS Example (LookAtPoint.js)#pragma strictvar lookAtPoint = Vector3.zero;function Update(){ transform.LookAt(lookAtPoint);}

Isso manterá um objeto orientado para um ponto do espaço-mundo. Atualmente este script só ficará ativo no modo de jogo, ou seja, quando o jogo estiver rodando. Ao escrever scripts de editor é frequentemente útil ter certos scripts executados durante o modo de edição também, enquanto o jogo não está rodando. Você pode fazer isso adicionando um atributo ExecuteInEditMode a ele:

//C# Example (LookAtPoint.cs)using UnityEngine;public class LookAtPoint : MonoBehaviour{ public Vector3 lookAtPoint = Vector3.zero; void Update() { transform.LookAt(lookAtPoint); }}
//JS Example (LookAtPoint.js)#pragma strict@script ExecuteInEditMode()var lookAtPoint = Vector3.zero;function Update(){ transform.LookAt(lookAtPoint);}

Agora se você mover o objeto que tem esse script no editor, ou alterar os valores de “Look At Point” no inspetor – mesmo quando não está no modo de jogo – o objeto atualizará sua orientação de forma correspondente para que ele permaneça olhando para o ponto de destino no espaço mundial.

Fazer um Editor Personalizado

O acima demonstra como você pode ter scripts simples rodando durante o tempo de edição, porém isso sozinho não permite que você crie suas próprias ferramentas de edição. O próximo passo é criar um Editor Personalizado para script que acabamos de criar.

Quando você cria um script em Unidade, por padrão ele herda do MonoBehaviour, e portanto é um Componente que pode ser colocado em um objeto de jogo. Quando colocado em um objeto de jogo, o Inspetor exibe uma interface padrão para visualizar e editar todas as variáveis públicas que podem ser mostradas – como inteiros, floats, strings, Vector3’s, etc.

Aqui está como o inspetor padrão procura por nosso script acima:

Um inspetor padrão com um campo Vector3 público

Um editor personalizado é um script separado que substitui esse layout padrão por qualquer controle de editor que você escolher.

Para começar a criar o editor personalizado para nosso script LookAtPoint, você deve criar outro script com o mesmo nome, mas com “Editor” anexado. Então, para o nosso exemplo: “LookAtPointEditor”.

//c# Example (LookAtPointEditor.cs)using UnityEngine;using UnityEditor;public class LookAtPointEditor : Editor { SerializedProperty lookAtPoint; void OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); }}
//JS Example (LookAtPointEditor.js)#pragma strict@CustomEditor(LookAtPoint)@CanEditMultipleObjectsclass LookAtPointEditor extends Editor { var lookAtPoint : SerializedProperty; function OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } function OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); }}

Esta classe tem de derivar do Editor. O atributo CustomEditor informa a Unidade para qual componente ele deve atuar como editor. O atributo CanEditMultipleObjects diz ao Unity que você pode selecionar vários objetos com este editor e alterá-los todos ao mesmo tempo.

O código no OnInspectorGUI é executado sempre que o Unity exibe o editor no Inspector. Você pode colocar qualquer código GUI aqui – ele funciona exatamente como o OnGUI para jogos, mas é executado dentro do Inspector. O editor define a propriedade de destino que você pode usar para acessar o objeto que está sendo inspecionado. Aqui está como nosso inspetor personalizado se parece:

Não é muito interessante porque tudo que fizemos até agora foi recriar o campo Vector3, exatamente como o inspetor padrão nos mostra, então o resultado parece muito similar (embora o campo “Script” agora não esteja presente, pois não adicionamos nenhum código de inspetor para mostrá-lo).

No entanto agora que você tem controle sobre como o inspetor é exibido em um script do Editor, você pode usar qualquer código que você queira para dispor os campos do inspetor, permitir que o usuário ajuste os valores, e até mesmo exibir gráficos ou outros elementos visuais. Na verdade, todos os inspetores que você vê dentro do Unity Editor, incluindo os inspetores mais complexos como o sistema de terreno e as configurações de importação de animação, são todos feitos usando a mesma API à qual você tem acesso ao criar seus próprios Editores personalizados.

Aqui está um exemplo simples que estende seu script do editor para exibir uma mensagem indicando se o ponto de destino está acima ou abaixo do gameobject:

//c# Example (LookAtPointEditor.cs)using UnityEngine;using UnityEditor;public class LookAtPointEditor : Editor{ SerializedProperty lookAtPoint; void OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } }}
//JS Example (LookAtPointEditor.js)#pragma strict@CustomEditor(LookAtPoint)@CanEditMultipleObjectsclass LookAtPointEditor extends Editor { var lookAtPoint : SerializedProperty; function OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } function OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } }}

Então agora temos um novo elemento para nosso inspetor que imprime uma mensagem mostrando se o ponto de destino está acima ou abaixo do gameobject.

Isso é apenas arranhar a superfície do que você pode fazer com o script do Editor. Você tem acesso total a todos os comandos IMGUI para desenhar qualquer tipo de interface, incluindo cenas de renderização usando uma câmera dentro das janelas do editor.

Scene View Additions

Você pode adicionar código extra para a Scene View implementando um OnSceneGUI em seu editor personalizado.

OnSceneGUI funciona exatamente como OnInspectorGUI – exceto que ele é executado na vista de cena. Para ajudá-lo a fazer seus próprios controles de edição na visualização de cena, você pode usar as funções definidas na classe Handles. Todas as funções lá são projetadas para trabalhar em 3D SceneGUI.

//C# Example (LookAtPointEditor.cs)using UnityEngine;using UnityEditor;public class LookAtPointEditor : Editor{ SerializedProperty lookAtPoint; void OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } serializedObject.ApplyModifiedProperties(); } public void OnSceneGUI() { var t = (target as LookAtPoint); EditorGUI.BeginChangeCheck(); Vector3 pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Move point"); t.lookAtPoint = pos; t.Update(); } }}
//JS Example (LookAtPointEditor.js)#pragma strict@CustomEditor(LookAtPointJS)@CanEditMultipleObjectsclass LookAtPointEditorJS extends Editor { var lookAtPoint : SerializedProperty; function OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } function OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); if (lookAtPoint.vector3Value.y > (target as LookAtPointJS).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPointJS).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } } function OnSceneGUI() { var t : LookAtPointJS = (target as LookAtPointJS); EditorGUI.BeginChangeCheck(); var pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Move point"); t.lookAtPoint = pos; t.Update(); } }}

Se você quiser colocar objetos 2D GUI (GUI, EditorGUI e amigos), você precisa envolvê-los em chamadas para Handles.BeginGUI() e Handles.EndGUI().

Deixe uma resposta

O seu endereço de email não será publicado.