// IngredientDrawer [CustomPropertyDrawer(typeof(Ingredient))] publicclassIngredientDrawer : PropertyDrawer { // Draw the property inside the given rect publicoverridevoidOnGUI(Rect position, SerializedProperty property, GUIContent label) { // Using BeginProperty / EndProperty on the parent property means that // prefab override logic works on the entire property. EditorGUI.BeginProperty(position, label, property);
// Draw label position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// Don't make child fields be indented var indent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0;
// Calculate rects var amountRect = new Rect(position.x, position.y, 30, position.height); var unitRect = new Rect(position.x + 35, position.y, 50, position.height); var nameRect = new Rect(position.x + 90, position.y, position.width - 90, position.height);
// Draw fields - passs GUIContent.none to each so they are drawn without labels EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none); EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none); EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);
// Set indent back to what it was EditorGUI.indentLevel = indent;
// Tell the MyRangeDrawer that it is a drawer for properties with the MyRangeAttribute. [CustomPropertyDrawer(typeof(MyRangeAttribute))] publicclassRangeDrawer : PropertyDrawer { // Draw the property inside the given rect voidOnGUI(Rect position, SerializedProperty property, GUIContent label) { // First get the attribute since it contains the range for the slider MyRangeAttribute range = (MyRangeAttribute)attribute;
// Now draw the property as a Slider or an IntSlider based on whether it's a float or integer. if (property.propertyType == SerializedPropertyType.Float) EditorGUI.Slider(position, property, range.min, range.max, label); elseif (property.propertyType == SerializedPropertyType.Integer) EditorGUI.IntSlider(position, property, (int) range.min, (int) range.max, label); else EditorGUI.LabelField(position, label.text, "Use MyRange with float or int."); } }
因为性能的原因EditorGUILayout的函数不能于PropertyDrawer一起使用
自定义编辑器
编辑模式下运行简单的脚本
ExecuteInEditMode特性可以使游戏运行时的脚本在编辑器模式下执行。
1 2 3 4 5 6 7 8 9 10 11 12
//C# Example (LookAtPoint.cs) using UnityEngine; [ExecuteInEditMode] publicclassLookAtPoint : MonoBehaviour { public Vector3 lookAtPoint = Vector3.zero;
publicoverridevoidOnInspectorGUI() { 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)"); }
publicoverridevoidOnInspectorGUI() { 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(); }
publicvoidOnSceneGUI() { var t = (target as LookAtPoint);
classSimpleTreeView : TreeView { publicSimpleTreeView(TreeViewState treeViewState) : base(treeViewState) { Reload(); } protectedoverride TreeViewItem BuildRoot () { // BuildRoot is called every time Reload is called to ensure that TreeViewItems // are created from data. Here we create a fixed set of items. In a real world example, // a data model should be passed into the TreeView and the items created from the model.
// This section illustrates that IDs should be unique. The root item is required to // have a depth of -1, and the rest of the items increment from that. var root = new TreeViewItem {id = 0, depth = -1, displayName = "Root"}; var allItems = new List<TreeViewItem> { new TreeViewItem {id = 1, depth = 0, displayName = "Animals"}, new TreeViewItem {id = 2, depth = 1, displayName = "Mammals"}, new TreeViewItem {id = 3, depth = 2, displayName = "Tiger"}, new TreeViewItem {id = 4, depth = 2, displayName = "Elephant"}, new TreeViewItem {id = 5, depth = 2, displayName = "Okapi"}, new TreeViewItem {id = 6, depth = 2, displayName = "Armadillo"}, new TreeViewItem {id = 7, depth = 1, displayName = "Reptiles"}, new TreeViewItem {id = 8, depth = 2, displayName = "Crocodile"}, new TreeViewItem {id = 9, depth = 2, displayName = "Lizard"}, }; // Utility method that initializes the TreeViewItem.children and .parent for all items. SetupParentsAndChildrenFromDepths (root, allItems); // Return root of the tree return root; } }
protectedoverride TreeViewItem BuildRoot() { var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" }; var animals = new TreeViewItem { id = 1, displayName = "Animals" }; var mammals = new TreeViewItem { id = 2, displayName = "Mammals" }; var tiger = new TreeViewItem { id = 3, displayName = "Tiger" }; var elephant = new TreeViewItem { id = 4, displayName = "Elephant" }; var okapi = new TreeViewItem { id = 5, displayName = "Okapi" }; var armadillo = new TreeViewItem { id = 6, displayName = "Armadillo" }; var reptiles = new TreeViewItem { id = 7, displayName = "Reptiles" }; var croco = new TreeViewItem { id = 8, displayName = "Crocodile" }; var lizard = new TreeViewItem { id = 9, displayName = "Lizard" };
using System.Collections.Generic; using UnityEngine; using UnityEditor.IMGUI.Controls;
classSimpleTreeViewWindow : EditorWindow { // SerializeField is used to ensure the view state is written to the window // layout file. This means that the state survives restarting Unity as long as the window // is not closed. If the attribute is omitted then the state is still serialized/deserialized. [SerializeField] TreeViewState m_TreeViewState;
//The TreeView is not serializable, so it should be reconstructed from the tree data. SimpleTreeView m_SimpleTreeView;
voidOnEnable () { // Check whether there is already a serialized view state (state // that survived assembly reloading) if (m_TreeViewState == null) m_TreeViewState = new TreeViewState ();
m_SimpleTreeView = new SimpleTreeView(m_TreeViewState); }
// Add menu named "My Window" to the Window menu [MenuItem ("TreeView Examples/Simple Tree Window")] staticvoidShowWindow () { // Get existing open window or if none, make a new one: var window = GetWindow<SimpleTreeViewWindow> (); window.titleContent = new GUIContent ("My Window"); window.Show (); } }
[Serializable] //The TreeElement data class is extended to hold extra data, which you can show and edit in the front-end TreeView. internalclassMyTreeElement : TreeElement { publicfloat floatValue1, floatValue2, floatValue3; public Material material; publicstring text = ""; publicbool enabled = true;
publicMyTreeElement (string name, int depth, int id) : base (name, depth, id) { floatValue1 = Random.value; floatValue2 = Random.value; floatValue3 = Random.value; } }