Você está na página 1de 91

Best Practices for Creating

Your Own Editor Tools


Rune Skovbo Johansen
Creative Programmer
Unity Technologies

Inspector

GameObject Editor
(built-in)

Transform Editor
(built-in)

Generic Editor
Enemy

Generic Editor
Enemy
using UnityEngine;
public class Enemy : MonoBehaviour {


public float speed = 5;

public float maxHealth = 10;


void Update () {



}
}

Generic Editor
Enemy

Custom Editor
Enemy
+

Editor
EnemyEditor

Custom Editors

Enemy
using UnityEngine;
public class Enemy : MonoBehaviour {


public float speed = 5;

public float maxHealth = 10;


void Update () {



}
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

PropertyField creates control based on type


bool = toggle
string = TextField
etc.

Some additional controls take SerializedProperty


Slider
IntSlider
IntPopup

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.Slider (maxHealth, 0, 10);


serializedObject.ApplyModifiedProperties ();
}

Why
SerializedProperties?

SerializedProperty advantages

SerializedProperty advantages

Undo/Redo

SerializedProperty advantages

Undo/Redo
Automatic multi-object editing

SerializedProperty advantages

Undo/Redo
Automatic multi-object editing
Prefab styling / reverting

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
[CanEditMultipleObjects]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

EnemyEditor
using UnityEngine;
using UnityEditor;
[CustomEditor (typeof (Enemy))]
[CanEditMultipleObjects]
public class EnemyEditor : Editor {
















}

SerializedProperty speed;
SerializedProperty maxHealth;
public void OnEnable () {

speed = serializedObject.FindProperty ("speed");

maxHealth = serializedObject.FindProperty ("maxHealth");
}
public override void OnInspectorGUI () {

serializedObject.Update ();


EditorGUILayout.PropertyField (speed);

EditorGUILayout.PropertyField (maxHealth);


serializedObject.ApplyModifiedProperties ();
}

PropertyDrawers
Added in Unity 4

PropertyDrawers
Enemy
using UnityEngine;
public class Enemy : MonoBehaviour {


public float speed = 5;


[Range (0, 10)]

public float maxHealth = 10;


void Update () {



}
}

Game script

Reusable code

Enemy

RangeAttribute

Editor
RangeDrawer

RangeAttribute
public class RangeAttribute : PropertyAttribute {

public float min;

public float max;


public RangeAttribute (float min, float max) {


this.min = min;


this.max = max;

}
}

RangeDrawer
[CustomPropertyDrawer (typeof (RangeAttribute))]
public class RangeDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

RangeAttribute range = (RangeAttribute)attribute;


EditorGUI.Slider (position, property,





range.min, range.max, label);

RangeAttribute
public class RangeAttribute : PropertyAttribute {

public float min;

public float max;


public RangeAttribute (float min, float max) {


this.min = min;


this.max = max;

}
}

RangeDrawer
[CustomPropertyDrawer (typeof (RangeAttribute))]
public class RangeDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

RangeAttribute range = (RangeAttribute)attribute;


EditorGUI.Slider (position, property,





range.min, range.max, label);

RangeAttribute
public class RangeAttribute : PropertyAttribute {

public float min;

public float max;


public RangeAttribute (float min, float max) {


this.min = min;


this.max = max;

}
}

RangeDrawer
[CustomPropertyDrawer (typeof (RangeAttribute))]
public class RangeDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

RangeAttribute range = (RangeAttribute)attribute;


EditorGUI.Slider (position, property,





range.min, range.max, label);

RangeAttribute
public class RangeAttribute : PropertyAttribute {

public float min;

public float max;


public RangeAttribute (float min, float max) {


this.min = min;


this.max = max;

}
}

RangeDrawer
[CustomPropertyDrawer (typeof (RangeAttribute))]
public class RangeDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

RangeAttribute range = (RangeAttribute)attribute;


EditorGUI.Slider (position, property,





range.min, range.max, label);

RangeAttribute
public class RangeAttribute : PropertyAttribute {

public float min;

public float max;


public RangeAttribute (float min, float max) {


this.min = min;


this.max = max;

}
}

RangeDrawer
[CustomPropertyDrawer (typeof (RangeAttribute))]
public class RangeDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

RangeAttribute range = (RangeAttribute)attribute;


EditorGUI.Slider (position, property,





range.min, range.max, label);

Author Once,
Deploy Everywhere
Enemy
Player
Missile
CamBehaviour

[Range ( , )]

PropertyDrawers for classes

Customize the GUI of every instance


of a Serializable class.

Ingredient
[Serializable]
public class Ingredient {

public string name;

public int amount;
}

IngredientDrawer
[CustomPropertyDrawer (typeof (Ingredient))]
public class IngredientDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

SerializedProperty name = property.FindPropertyRelative ("name");


SerializedProperty amount = property.FindPropertyRelative ("amount");
// Show GUI the way you want it here

Ingredient
[Serializable]
public class Ingredient {

public string name;

public int amount;
}

IngredientDrawer
[CustomPropertyDrawer (typeof (Ingredient))]
public class IngredientDrawer : PropertyDrawer {


public override void OnGUI ( Rect position,









SerializedProperty property,







GUIContent label) {

SerializedProperty name = property.FindPropertyRelative ("name");


SerializedProperty amount = property.FindPropertyRelative ("amount");
// Show GUI the way you want it here

Custom controls
with
SerializedProperties

What if existing controls


dont cut it?

Dial?

2D Slider?

Show bool, float, int, or string as a popup?

What if existing controls


dont cut it?
Example:
We want this bool...
[SpeedPopup]
bool isFast

...to be shown as this popup:

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer

[SpeedPopup]
bool isFast

[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]


public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

BAD:
newValue = Control (oldValue);
if (newValue != oldValue)
myProperty.value = newValue;

Doesnt work with multi-object editing,


because there are multiple values!

GOOD:
BeginChangeCheck ();
value = Control (value);
if (EndChangeCheck ())
myProperty.value = value;

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

SpeedPopupAttribute
public class SpeedPopupAttribute : PropertyAttribute { }

SpeedPopupDrawer
[CustomPropertyDrawer (typeof (SpeedPopupAttribute))]
public class SpeedPopupDrawer : PropertyDrawer {


enum SpeedOption { Slow, Fast }



public override void OnGUI ( Rect position,







SerializedProperty property,







GUIContent label) {



label = EditorGUI.BeginProperty (position, label, property);

EditorGUI.BeginChangeCheck ();

enumValue = (SpeedOption)EditorGUI.EnumPopup (position, label, enumValue);

if (EditorGUI.EndChangeCheck ())

property.boolValue = (enumValue == SpeedOption.Fast ? true : false);

SpeedOption enumValue =

(property.boolValue == true ? SpeedOption.Fast : SpeedOption.Slow);

EditorGUI.EndProperty ();

Bold prefab overrides


Revert to prefab menu
Dash when multiple values

Key takeaways

Key takeaways

Create and use PropertyDrawers for more


reusable customization components

Key takeaways

Create and use PropertyDrawers for more


reusable customization components

Check for changed values using

BeginChangeCheck / EndChangeCheck

Key takeaways

Create and use PropertyDrawers for more


reusable customization components

Check for changed values using

BeginChangeCheck / EndChangeCheck

Controls that dont take SerializedProperty


by themselves should be wrapped in
BeginProperty / EndProperty

Completely custom
controls

Completely custom controls


Example:
Button you can click and drag on to change
Vector2 value.

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}
Important!



break;


case EventType.MouseDrag:
- Other controls dont
get the focus.



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);
- Automatic repaint.




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();
Using delta has problems:



}



break;
- Edge of screen.


case EventType.MouseUp:



if (active) {
Good idea to implement




EditorGUIUtility.hotControl = 0;
cancel on Esc key event.




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;
BeginChangeCheck /


case EventType.MouseUp:
EndChangeCheck



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

private static Vector2 s_MouseDownPosition;


private static Vector2 s_MouseDownValue;
public static Vector2 VectorDragger (Rect position, Vector2 value) {

int id = GUIUtility.GetControlID ("Dragger".GetHashCode (), EditorGUIUtility.native, position);

Event evt = Event.current;

bool active = EditorGUIUtility.hotControl == id;


switch (evt.type) {


case EventType.MouseDown:



if (position.Contains (evt.mousePosition)) {




EditorGUIUtility.hotControl = id;




s_MouseDownValue = value;




s_MouseDownPosition = evt.mousePosition;




evt.Use ();



}



break;


case EventType.MouseDrag:



if (active) {




value = s_MouseDownValue + (evt.mousePosition - s_MouseDownPosition);




GUI.changed = true;




evt.Use ();



}



break;


case EventType.MouseUp:



if (active) {




EditorGUIUtility.hotControl = 0;




evt.Use ();



}



break;


case EventType.Repaint:



EditorStyles.miniButton.Draw (position, "drag", active, active, false, false);



break;

}


return value;
}

Other
editor scripting

OnSceneGUI

OnSceneGUI

OnSceneGUI

Use OnSceneGUI in custom editors

OnSceneGUI

Use OnSceneGUI in custom editors


Draw various handles in the SceneView
using the Handles class.

OnSceneGUI

Use OnSceneGUI in custom editors


Draw various handles in the SceneView
using the Handles class.

Called for each object - each OnSceneGUI


call handles only one object

OnSceneGUI

Use OnSceneGUI in custom editors


Draw various handles in the SceneView
using the Handles class.

Called for each object - each OnSceneGUI


call handles only one object

No need to use SerializedProperties

EditorWindows

EditorWindows

Create your own windows

EditorWindows

Create your own windows


No need to use SerializedProperties

AwesomeEditorWindow
using UnityEngine;
using UnityEditor;
public class AwesomeEditorWindow : EditorWindow {


[MenuItem ("Window/Awesome Window")]

public static void ShowAwesomeEditorWindow () {


GetWindow <AwesomeEditorWindow> ();

}


public void OnGUI () {


// Custom GUI

}
}

AwesomeEditorWindow
using UnityEngine;
using UnityEditor;
public class AwesomeEditorWindow : EditorWindow {


[MenuItem ("Window/Awesome Window")]

public static void ShowAwesomeEditorWindow () {


GetWindow <AwesomeEditorWindow> ();

}


public void OnGUI () {


// Custom GUI

}
}

AwesomeEditorWindow
using UnityEngine;
using UnityEditor;
public class AwesomeEditorWindow : EditorWindow {


[MenuItem ("Window/Awesome Window")]

public static void ShowAwesomeEditorWindow () {


GetWindow <AwesomeEditorWindow> ();

}


public void OnGUI () {


// Custom GUI

}
}

AwesomeEditorWindow
using UnityEngine;
using UnityEditor;
public class AwesomeEditorWindow : EditorWindow {


[MenuItem ("Window/Awesome Window")]

public static void ShowAwesomeEditorWindow () {


GetWindow <AwesomeEditorWindow> ();

}


public void OnGUI () {


// Custom GUI

}
}

Questions?
Lots of helpful people on the forums,
UnityAnswers and the Unity IRC channel.
If no help, PM me with link to your post.
(runevision in the forums)
twitter
@runevisioncom

Você também pode gostar