//손이 많이가지만 많은 기능을 쓸수 있습니다.
기본형
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(RoomGoto))]
public class RoomGoto_Inspector : Editor
{
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("버튼조작을 위한 컴포넌트");
}
}
#endif
public class RoomGoto : MonoBehaviour
{
public void room_goto(string room_name)
{
SceneManager.LoadScene(room_name);
}
public void game_quit()
{
Application.Quit();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
기존 인스펙터 호출
public override void OnInspectorGUI()
{
DrawDefaultInspector();
}
혹은
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
}
버튼 조작시
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();//기본 인스펙터를 받아올때
serializedObject.Update();
{
if (GUILayout.Button("실행"))
{
((SampleClass)target).PressInspecterButton();
}
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.notice)), GUIContent.none);
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
public class SampleClass : MonoBehaviour
{
[HideInInspector]
[Header("주석")]
public string notice;
public void PressInspecterButton()
{
//버튼을 누를시 활성화될 코드
if (Application.isPlaying)
{
//게임중일때 실행될 코드
}
else
{
//인스펙터에서 수정중일때 실행될 코드
}
}
}
슬라이더 조작시
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();//기본 인스펙터를 받아올때
serializedObject.Update();
{
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.border)));
}
if (EditorGUI.EndChangeCheck())
{
((AccountSelect)target).SelectInspecterSlider();
}
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.border)), GUIContent.none);
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
public class SampleClass : MonoBehaviour
{
[HideInInspector]
[Header("주석")]
public string notice;
[HideInInspector]
[Range(0,6)]
public float border;
public void SelectInspecterSlider()
{
//값변경시 활성화될 코드
if (Application.isPlaying)
{
게임중일때 실행될 코드
}
else
{
인스펙터에서 수정중일때 실행될 코드
}
}
}
라벨필드
public override void OnInspectorGUI()
{
EditorGUILayout.LabelField("일반라벨");
EditorGUILayout.LabelField("굵은글씨", EditorStyles.boldLabel);
}
메뉴를 만들어야 할때
#if UNITY_EDITOR
using UnityEditor;
public class CustomMenuEditor : Editor
{
[MenuItem("MyMenu/Run")]
static void Run()
{
//실행되는 코드
}
}
#endif
커스텀 윈도우 프로퍼티 필드(수동 serializedObject)
public Object folder;
SerializedObject serializedObject;
void OnGUI()
{
if (serializedObject == null)
{
serializedObject = new SerializedObject(this);
}
serializedObject.Update();
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(folder)));
}
serializedObject.ApplyModifiedProperties();
}
비활성필드
GUI.enabled = false;
{
EditorGUILayout.TextField("Name", "value");
}
GUI.enabled = true;
NonSerialized 및 정적필드뷰어
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public void DrawHiddenInspectors()
{
serializedObject.Update();
{
var fields = target.GetType().GetFields();
GUI.enabled = false;
{
foreach (var field in fields)
{
if ((field.IsStatic) || (field.IsNotSerialized))
{
var fieldName = field.Name;
if (field.IsStatic)
{
fieldName += " (static)";
}
var fieldType = field.FieldType;
if ((fieldType.IsArray) || ((fieldType.IsGenericType) && fieldType.GetGenericTypeDefinition() == typeof(List<>)))
{
EditorGUI.indentLevel--;
{
EditorGUILayout.LabelField($"▼{field.Name}");
}
EditorGUI.indentLevel++;
EditorGUI.indentLevel++;
{
var arrDatas = (System.Collections.IList)field.GetValue(target);
if (arrDatas == null)
{
EditorGUILayout.LabelField("null");
}
else
{
EditorGUILayout.TextField($"Size", arrDatas.Count.ToString());
for (int i = 0; i < arrDatas.Count; i++)
{
EditorGUILayout.TextField($"Element {i}", arrDatas[i].ToString());
}
}
}
EditorGUI.indentLevel--;
}
else if (fieldType.IsClass && (fieldType.IsArray == false) && (fieldType.Equals(typeof(string)) == false))
{
EditorGUI.indentLevel--;
{
EditorGUILayout.LabelField($"▼{field.Name}");
}
EditorGUI.indentLevel++;
EditorGUI.indentLevel++;
{
var fieldValue = field.GetValue(target);
var subFields = fieldType.GetFields();
foreach (var subField in subFields)
{
//subField.GetValue(fieldValue).ToString()
EditorGUILayout.LabelField(subField.Name);
}
}
EditorGUI.indentLevel--;
}
else
{
EditorGUILayout.TextField($"{field.Name}", field.GetValue(target).ToString());
}
}
}
}
GUI.enabled = true;
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DrawHiddenInspectors();
}
}
#endif
public class SampleClass : MonoBehaviour
{
public int number = 1;
public int[] array = new int[] { 1, 2, 3 };
public static float realStatic = 1.5f;
public static int numberStatic = 2;
public static int[] arrayStatic = new int[] { 1,2,3 };
public static QuestionSelect questionSelect;
[System.Serializable]
public class QuestionSelect
{
public int number = 1;
public float real = 2f;
}
}
커스텀 readonly
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public void BaseInspectorGUI(params string[] readOnlyPropertyNames)
{
serializedObject.Update();
{
var fields = target.GetType().GetFields();
foreach (var field in fields)
{
if ((field.IsStatic) || (field.IsNotSerialized))
{
}
else
{
if (System.Array.FindIndex(readOnlyPropertyNames, x => x == field.Name) >= 0)
{
GUI.enabled = false;
}
EditorGUILayout.PropertyField(serializedObject.FindProperty(field.Name));
GUI.enabled = true;
}
}
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
BaseInspectorGUI(nameof(SampleClass.SampleVariable));
}
}
#endif
커스텀 readonly V2
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public void BaseOnInspectorGUI(params string[] readOnlyPropertyNames)
{
DrawPropertiesExcluding(serializedObject, readOnlyPropertyNames);
serializedObject.Update();
{
GUI.enabled = false;
foreach (var readOnlyPropertyName in readOnlyPropertyNames)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(readOnlyPropertyName));
}
GUI.enabled = true;
}
}
public override void OnInspectorGUI()
{
BaseOnInspectorGUI(nameof(SampleClass.SampleVariable));
}
}
#endif
커스텀 히든(v3)
이걸써야 디버그모드에서도 보인다
v2에 비해서 코드는 길어졌지만 script를 숨겨놓게 했다 (m_Script가 표시숨김)
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public override void OnInspectorGUI()
{
GUI.enabled = false;
{
var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
}
GUI.enabled = true;
serializedObject.Update();
{
DrawPropertiesExcluding(serializedObject, "m_Script",nameof(SampleClass.SampleVariable));
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
커스텀 히든(v1)
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public void BaseInspectorGUI(params string[] hiddenPropertyNames)
{
serializedObject.Update();
{
var fields = target.GetType().GetFields();
foreach (var field in fields)
{
if ((field.IsStatic) || (field.IsNotSerialized))
{
}
else
{
if ((System.Array.FindIndex(hiddenPropertyNames, x => x == field.Name) >= 0)==false)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(field.Name));
}
}
}
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
BaseInspectorGUI(nameof(SampleClass.SampleVariable));
}
}
#endif
커스텀 히든(v2)
이걸써야 디버그모드에서도 보인다
[HideInInspector]는 여전히 안보임
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
{
DrawPropertiesExcluding(serializedObject,nameof(SampleClass.SampleVariable));
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
값변경 미리보기
미리보기수준에서 끝나는게 아니라 실제로 적용하려면 더티플래그를 박아라
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
{
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.SampleValue)));
}
if (EditorGUI.EndChangeCheck())
{
//변경되었을때 실행
}
else
{
//인스펙터를 벗어났을때 실행
}
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
더티플래그를 이용한 프리팹상 저장
if (GUILayout.Button("Auto Setting"))
{
AutoFind();
EditorUtility.SetDirty(target); //이부분
}
ReorderableList 예제
튜토리얼 모드에서는 라이프 미표시하는 ReorderableList 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
Hashtable reorderableListTable = new Hashtable();
public void DrawStageDatas(string propertyPath)
{
var reorderableListProperty = serializedObject.FindProperty(propertyPath);
if (reorderableListTable[propertyPath] == null)
{
reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
}
var reorderableList = (ReorderableList)reorderableListTable[propertyPath];
serializedObject.Update();
{
//헤더명
reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");
//요소
var elementName = nameof(SampleClass.StageData.stageName);
reorderableList.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) =>
{
EditorGUI.PropertyField(rect, reorderableListProperty.GetArrayElementAtIndex(index).FindPropertyRelative(elementName));
};
reorderableList.DoLayoutList();
//선택된 필드
if (reorderableList.index >= 0)
{
var index = reorderableList.index;
if ((reorderableListProperty != null) && (reorderableListProperty.arraySize > 0) && (index < reorderableListProperty.arraySize))
{
var elementAtIndex = reorderableListProperty.GetArrayElementAtIndex(index);
if (elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)).boolValue)
{
//튜토리얼 모드라면 이름과 제한시간만 표시
EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)));
EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.timeLimit)));
}
else
{
//기본표시
foreach (var field in typeof(SampleClass.StageData).GetFields())
{
if ((field.IsStatic) || (field.IsNotSerialized))
{
}
else
{
if (field.Name != elementName)
{
EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(field.Name));
}
}
}
//life값은 0으로 초기화
{
var sampleClass = (SampleClass)target;
var field = sampleClass.GetType().GetField(propertyPath);
var datas = (SampleClass.StageData)field.GetValue(sampleClass);
datas[index].life = 0;
//구조체라면 field.SetValue(sampleClass, datas)를 사용한다
}
}
}
}
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DrawStageDatas(nameof(SampleClass.stageDatas));
DrawStageDatas(nameof(SampleClass.stageDatas2));
}
}
#endif
public class SampleClass : MonoBehaviour
{
[HideInInspector]
public StageData[] stageDatas;
[HideInInspector]
public StageData[] stageDatas2;
[System.Serializable]
public class StageData
{
public string stageName;
public bool isTutorial;
public int timeLimit;
public int life;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
한칸에 여러줄표시하는 ReorderableList 예제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{
Hashtable reorderableListTable = new Hashtable();
public void DrawStageDatas(string propertyPath)
{
var reorderableListProperty = serializedObject.FindProperty(propertyPath);
if (reorderableListTable[propertyPath] == null)
{
reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
}
var reorderableList = (ReorderableList)reorderableListTable[propertyPath];
serializedObject.Update();
{
//헤더명
reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");
//요소크기
reorderableList.elementHeight = EditorGUIUtility.singleLineHeight * 4;
reorderableList.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) =>
{
var elementProperty = reorderableListProperty.GetArrayElementAtIndex(index);
var fieldRect = rect;
fieldRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.stageName)));
fieldRect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)));
fieldRect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.timeLimit)));
fieldRect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.life)));
};
reorderableList.DoLayoutList();
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DrawStageDatas(nameof(SampleClass.stageDatas));
DrawStageDatas(nameof(SampleClass.stageDatas2));
}
}
#endif
public class SampleClass : MonoBehaviour
{
[HideInInspector]
public StageData[] stageDatas;
[HideInInspector]
public StageData[] stageDatas2;
[System.Serializable]
public class StageData
{
public string stageName;
public bool isTutorial;
public int timeLimit;
public int life;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
참고용 단순 예제
#if UNITY_EDITOR
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{
Hashtable reorderableListTable = new Hashtable();
public static System.Type GetType(SerializedProperty property)
{
var parentType = property.serializedObject.targetObject.GetType();
var fieldInfo = parentType.GetField(property.propertyPath);
return fieldInfo.FieldType;
}
public void DrawReorderableList(string propertyPath)
{
var reorderableListProperty = serializedObject.FindProperty(propertyPath);
if (reorderableListTable[propertyPath] == null)
{
reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
}
var reorderableList = (ReorderableList)reorderableListTable[propertyPath];
serializedObject.Update();
{
//헤더명
reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");
//요소
var targetType = GetType(reorderableListProperty).GetElementType();
reorderableList.elementHeight = EditorGUIUtility.singleLineHeight * Mathf.Max(1, targetType.GetFields().Length);
reorderableList.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) =>
{
var elementProperty = reorderableListProperty.GetArrayElementAtIndex(index);
var fieldRect = rect;
fieldRect.height = EditorGUIUtility.singleLineHeight;
fieldRect.y -= EditorGUIUtility.singleLineHeight;
foreach (var fields in targetType.GetFields())
{
fieldRect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(fields.Name));
}
};
reorderableList.DoLayoutList();
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
DrawReorderableList(nameof(SampleClass.stageDatas));
DrawReorderableList(nameof(SampleClass.stageDatas2));
}
}
#endif
public class SampleClass : MonoBehaviour
{
[HideInInspector]
public StageData[] stageDatas;
[HideInInspector]
public StageData[] stageDatas2;
[System.Serializable]
public class StageData
{
public string stageName;
public bool isTutorial;
public int timeLimit;
public int life;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
자동화 버전
배열길이 임의로 조정
var property=serializedObject.FindProperty(nameof(SampleClass.folders));
if(property.arraySize > 3)
{
property.arraySize = 3;
}
다중배열 표시
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
//Production Date 2022-10-10 from Ahzkwid
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
public void Draw2DArray(string targetFieldName)
{
bool IsArrayCustom(System.Type type)
{
return (type.IsArray) || ((type.IsGenericType) && type.GetGenericTypeDefinition() == typeof(List<>));
}
void DrawElement(string label,object ilistObject)
{
var ilist = (System.Collections.IList)ilistObject;
EditorGUI.indentLevel--;
{
EditorGUILayout.LabelField(label);
}
EditorGUI.indentLevel++;
EditorGUI.indentLevel++;
{
if (ilist == null)
{
EditorGUILayout.LabelField("null");
}
else
{
EditorGUILayout.TextField($"Size", ilist.Count.ToString());
for (int i = 0; i < ilist.Count; i++)
{
if (ilist[i] == null)
{
EditorGUI.indentLevel++;
EditorGUILayout.LabelField("null");
EditorGUI.indentLevel--;
continue;
}
var elementType = ilist[i].GetType();
if (IsArrayCustom(elementType))
{
DrawElement($"▼Element {i}", ilist[i]);
}
else
{
EditorGUILayout.TextField($"Element {i}", ilist[i].ToString());
}
}
}
}
EditorGUI.indentLevel--;
}
serializedObject.Update();
{
var fields = target.GetType().GetFields();
GUI.enabled = false;
{
foreach (var field in fields)
{
var fieldName = field.Name;
if (fieldName != targetFieldName)
{
continue;
}
if (field.IsStatic)
{
fieldName += " (static)";
}
var fieldType = field.FieldType;
if (IsArrayCustom(fieldType))
{
DrawElement($"▼{field.Name}", field.GetValue(target));
}
}
}
GUI.enabled = true;
}
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
Draw2DArray(nameof(SampleClass.sampleArray2));
Draw2DArray(nameof(SampleClass.sampleArray3));
Draw2DArray(nameof(SampleClass.sampleArray4));
}
}
#endif
public class SampleClass : MonoBehaviour
{
public string[] sampleArray;
public string[][] sampleArray2;
public string[][] sampleArray3 = new string[1][];
public string[][][] sampleArray4 = new string[2][][] { new string[1][], new string[1][] };
// Start is called before the first frame update
void Start()
{
sampleArray2 = new string[8][];
for (int i = 0; i < sampleArray.Length; i++)
{
sampleArray2[i] = new string[8];
}
sampleArray3 = new string[2][];
for (int i = 0; i < sampleArray3.Length; i++)
{
sampleArray3[i] = new string[3];
for (int j = 0; j < sampleArray3[i].Length; j++)
{
sampleArray3[i][j] = $"text[{i}][{j}]";
}
}
sampleArray4 = new string[2][][];
for (int i = 0; i < sampleArray4.Length; i++)
{
sampleArray4[i] = new string[2][];
for (int j = 0; j < sampleArray4[i].Length; j++)
{
sampleArray4[i][j] = new string[2];
for (int k = 0; k < sampleArray4[i][j].Length; k++)
{
sampleArray4[i][j][k] = $"text[{i}][{j}][{k}]";
}
}
}
}
// Update is called once per frame
void Update()
{
}
}
오른쪽으로 한칸 들여쓰기
EditorGUI.indentLevel++;
{
//들어갈 내용
}
EditorGUI.indentLevel--;
박스 레이아웃 두르기
GUILayout.Space(50);
EditorGUILayout.LabelField("제목", EditorStyles.boldLabel);
GUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUI.indentLevel++;
{
//들어갈 내용
}
EditorGUI.indentLevel--;
GUILayout.Space(20);
GUILayout.EndVertical();
자기 자신 스크립트를 표시
GUI.enabled = false;
{
var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
}
GUI.enabled = true;
SerializedProperty To Type
public static System.Type GetType(SerializedProperty property)
{
var parentType = property.serializedObject.targetObject.GetType();
var fieldInfo = parentType.GetField(property.propertyPath);
return fieldInfo.FieldType;
}
커스텀 드롭다운
하기는 레이어 드롭다운 예제이다.
var sampleClass = (SampleClass)target;
GUILayout.BeginHorizontal();
{
GUILayout.Label("Layer");
int layer = sampleClass.gameObject.layer;
if (EditorGUILayout.DropdownButton(new GUIContent( LayerMask.LayerToName(layer)), FocusType.Passive))
{
GenericMenu menu = new GenericMenu();
for (int i = 0; i < 32; i++)
{
var layerName = LayerMask.LayerToName(i);
if (string.IsNullOrWhiteSpace(layerName))
{
continue;
}
menu.AddItem(new GUIContent($"{i}: {layerName}"), false, Callback, i);
}
menu.ShowAsContext();
void Callback(object obj)
{
sampleClass.gameObject.layer = (int)obj;
}
}
}
GUILayout.EndHorizontal();
레이어마스크 드롭다운 예제
근데 내장변수 LayerMask 쓰면 된다 (뻘짓함)
인줄 알았는데 Unsupported type BitField버그때문에 다시 씀
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(Crosshair))]
public class CrosshairEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var targetClass = (Crosshair)target;
serializedObject.Update();
{
GUILayout.BeginHorizontal();
{
GUILayout.Label("Layer Mask");
var layerMask = targetClass.layerMask;
var layerNames = new List<string>();
for (int i = 0; i < 32; i++)
{
if ((layerMask & (1<<i))==0) //해당 레이어마스크가 미체크면 스킵
{
continue;
}
var layerName = LayerMask.LayerToName(i);
if (string.IsNullOrWhiteSpace(layerName))
{
layerName = i.ToString();
}
layerNames.Add(layerName);
}
var name = "";
switch (layerMask)
{
case 0: //Nothing
name = "Nothing";
break;
case -1: //Everything (-1,~0)
name = "Everything";
break;
default:
if (layerNames.Count>3)
{
name = "Mixed...";
}
else
{
name = string.Join(", ", layerNames);
}
break;
}
if (EditorGUILayout.DropdownButton(new GUIContent(name), FocusType.Passive))
{
var menu = new GenericMenu();
menu.AddItem(new GUIContent($"Nothing"), layerMask == 0, Callback, 0); //Nothing
menu.AddItem(new GUIContent($"Everything"), layerMask == -1, Callback, -1); //Everything
for (int i = 0; i < 32; i++)
{
var layerName = LayerMask.LayerToName(i);
var on = (layerMask & (1 << i)) != 0;
if (string.IsNullOrWhiteSpace(layerName))
{
continue;
}
menu.AddItem(new GUIContent($"{i}: {layerName}"), on, Callback, 1 << i);
}
menu.ShowAsContext();
void Callback(object obj)
{
switch ((int)obj)
{
case 0: //Nothing
case -1: //Everything (-1,~0)
targetClass.layerMask = (int)obj;
break;
default:
targetClass.layerMask ^= (int)obj;
break;
}
}
}
}
GUILayout.EndHorizontal();
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
enum to dropdown 예제
아주 가끔 쓰인다
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(PickupSystem))]
public class PickupSystemInspecter : Editor
{
public enum Piece
{
None, Pawn, Knight, Bishop, Rook, Queen, King
}
public override void OnInspectorGUI()
{
GUI.enabled = false;
{
var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
}
GUI.enabled = true;
serializedObject.Update();
{
DrawPropertiesExcluding(serializedObject, "m_Script", nameof(PickupSystem.piece));
GUILayout.BeginHorizontal();
{
GUILayout.Label(nameof(PickupSystem.piece));
var pickupSystem = target as PickupSystem;
var names = System.Enum.GetNames(typeof(Piece));
if (EditorGUILayout.DropdownButton(new GUIContent(names[pickupSystem.piece]), FocusType.Passive))
{
var menu = new GenericMenu();
for (int i = 0; i < names.Length; i++)
{
if (string.IsNullOrWhiteSpace(names[i]))
{
continue;
}
menu.AddItem(new GUIContent($"{i}: {names[i]}"), false, Callback, i);
}
menu.ShowAsContext();
void Callback(object obj)
{
pickupSystem.piece = (int)obj;
}
}
}
GUILayout.EndHorizontal();
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
텍스처 표시
{
var preview = AssetPreview.GetAssetPreview(loadComputeShader.renderTexture);
GUILayout.Label(preview);
EditorGUILayout.LabelField(nameof(LoadComputeShader.renderTexture));
}
MinMax슬라이더
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();//기본 인스펙터
serializedObject.Update();
{
var sampleClass = (SampleClass)target;
var minLimit = sampleClass.minLimit;
var maxLimit = sampleClass.maxLimit;
EditorGUILayout.LabelField($"MinMaxSlider ({minLimit},{sampleClass.minVal},{sampleClass.maxVal},{maxLimit})");
EditorGUILayout.MinMaxSlider(ref sampleClass.minVal, ref sampleClass.maxVal, minLimit, maxLimit);
}
serializedObject.ApplyModifiedProperties();
}
}
#endif
public class SampleClass : MonoBehaviour
{
public float minVal = -10;
public float minLimit = -20;
public float maxVal = 10;
public float maxLimit = 20;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
'Unity > C#' 카테고리의 다른 글
SQLite 유니티 사용방법 (0) | 2020.05.24 |
---|---|
유니티 어트리뷰트 (0) | 2020.05.19 |
UGui 관련 (0) | 2020.05.19 |