Bootstrap

Unity编辑拓展显示自定义类型

        配合自定义特性或着header可以添加注解

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System;
using Unity.VisualScripting;

#if UNITY_EDITOR

public class EditorRender
{
    public static Enum RenderEnum(FieldInfo fieldInfo, Enum value, Type type, params GUILayoutOption[] style)
    {
        var array = Enum.GetValues(type);// 直接使用  Enum[] EnumValueArr =   (Enum[])Enum.GetValues(type);  不行,这里不能用enum,存在类型转换异常,只能指定枚举类型
        Enum[] EnumValueArr = new Enum[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            EnumValueArr[i] = (Enum)Enum.Parse(type, array.GetValue(i).ToString());
        }
        int[] IntValueArr = new int[EnumValueArr.Length];
        string[] EnumDescArr = new string[EnumValueArr.Length];

        for (int i = 0; i < EnumValueArr.Length; i++)
        {
            Enum e = EnumValueArr[i];
            IntValueArr[i] = (int)Enum.Parse(type, e.ToString());
            var field = type.GetField(e.ToString());
            HeaderAttribute header = field.GetAttribute<HeaderAttribute>();
            if (header != null)
            {
                EnumDescArr[i] = header.header;
            }
            else
            {
                EnumDescArr[i] = "未定义";
            }
        }
        int selectValue = (int)Enum.Parse(type, value.ToString());
        selectValue = EditorGUILayout.IntPopup(selectValue, EnumDescArr, IntValueArr, style);
        value = (Enum)Enum.Parse(type, selectValue.ToString());
        return value;
    }

    public static object RenderValue(FieldInfo fieldInfo, Type type, object value, object defaultValue = null, params GUILayoutOption[] style)
    {
        SetDefaultValue(type, ref value, defaultValue);

        if (type == typeof(int))
        {
            return EditorGUILayout.IntField(int.Parse(value.ToString()), style);
        }
        else if (type == typeof(float))
        {
            return EditorGUILayout.FloatField(float.Parse(value.ToString()), style);
        }
        else if (type == typeof(long))
        {
            return EditorGUILayout.LongField(long.Parse(value.ToString()), style);
        }
        else if (type == typeof(string))
        {
            return GUILayout.TextArea(value as string, style);
        }
        else if (type == typeof(bool))
        {
            return GUILayout.Toggle(bool.Parse(value.ToString()), "", style);
        }
        else if (type.IsEnum)
        {
            value = EditorRender.RenderEnum(fieldInfo, (Enum)value, type, style);
            return value;
        }
        else if (value is IList)
        {
            value = RenderList(type.GetGenericArguments()[0], value as IList);
            return value;
        }
        if (value == null)
        {
            return Activator.CreateInstance(type);
        }


        return null;
    }

    public static object RenderList(Type type, IList list)
    {
        if (list == null)
        {
            return Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
        }
        for (int i = 0; i < list.Count; i++)
        {

            list[i] = RenderValue(null, type, list[i], style: GUILayout.MaxWidth(400));
            if (GUILayout.Button("X", GUILayout.MaxWidth(50)))
            {
                list.RemoveAt(i);
                GUILayout.EndHorizontal();
                break;
            }
        }
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Add", GUILayout.MaxWidth(500)))
        {
            list.Add(Activator.CreateInstance(type));
        }
        GUILayout.EndHorizontal();
        return list;

    }

    public static void SetDefaultValue(Type type, ref object value, object defaultValue)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            if (defaultValue != null)
            {
                value = defaultValue;
                return;
            }
            if (type == typeof(int))
            {
                value = 0;
            }
            else if (type == typeof(float))
            {
                value = 0;
            }
            else if (type == typeof(long))
            {
                value = 0;
            }
            else if (type == typeof(Single))
            {
                value = 0;
            }
            else if (type == typeof(string))
            {
                value = string.Empty;
            }
            else if (type == typeof(bool))
            {
                value = false;
            }
            else if (type == typeof(Vector3))
            {
                value = Vector3.zero;
            }
            else if (type == typeof(Vector2))
            {
                value = Vector2.zero;
            }
            else if (type.IsEnum)
            {

            }
        }
    }

    public static object RenderField(FieldInfo fieldInfo, HeaderAttribute header, object obj, params GUILayoutOption[] style)
    {
        GUILayout.BeginHorizontal(GUI.skin.button);

        GUILayout.BeginVertical();
        Type t = fieldInfo.FieldType;
        GUILayout.Label($"{fieldInfo.Name}({t.Name})");

        if (header!= null)
        {
            GUILayout.Label(header.header);
        }
        GUILayout.EndVertical();

        
        var value = RenderValue(fieldInfo, t, obj, style: style);
        GUILayout.EndHorizontal();

        return value;
    }

    public static object RenderObject(object value)
    {
        var propertyInfos = value.GetType().GetFields();
        for (int i = 0; i < propertyInfos.Length; i++)
        {
            var property = propertyInfos[i];
            object obj = property.GetValue(value);
            obj = EditorRender.RenderField(property, null, obj, GUILayout.MaxWidth(400));
            property.SetValue(value, obj);

            GUILayout.Space(5);
        }


        return value;
    }
}

#endif

        使用方式,直接调用RenderObject就行

    private class CustomClass
    {
        public string Name;
        public int Age;
        public bool Sex;
    }
    private CustomClass m_CustomClass;


    private void OnGUI()
    {
        m_CustomClass = (CustomClass)EditorRender.RenderObject(m_CustomClass);
    }

        这里用的都是变量,如果使用属性的话,将获取属性,获取属性值,写入属性值的方式修改源代码即可,RenderValue里如果有未定义其他类型,记得补充

;