配合自定义特性或着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里如果有未定义其他类型,记得补充