Get it on Google Play


Wm뮤 :: 유니티 커스텀 인스펙터

블로그 이미지
가끔 그림그리거나 3D모델링하거나
취미로 로봇만드는
퇴직한 전자과 게임프로그래머
2020.3.48f1 , 2022.3.6f1 주로 사용
모카쨩
@Ahzkwid

Recent Comment

Archive


2020. 5. 19. 21:48 Unity/C#

//손이 많이가지만 많은 기능을 쓸수 있습니다.

 

 

 

 

기본형

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
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입