UnityEditor扩展-Odin Inspector---之(五)分享一个平替插件NaughtyAttributes

这是Odin Inspector揭秘系列第5个文章了

对的,前面文章4个你都看不到,因为还没发出

--------------------

Odin类插件NaughtyAttributes

这几天,有点被Odin 各种信息和各种入门视频恶心到(drawer和 processor),所以找了个平替

以下是标签,但又不全然是Odin

就是这么一个插件NaughtyAttributes ,使用 DropDown(非Odin)标签

	[System.Serializable]
	public class DropdownNest2
	{
		[Dropdown("GetVectorValues")]
		public Vector3 vectorValue;

		private DropdownList<Vector3> GetVectorValues()
		{
			return new DropdownList<Vector3>()
			{
				{ "Right", Vector3.right },
				{ "Up", Vector3.up },
				{ "Forward", Vector3.forward }
			};
		}
	}

居然是免费的

居然是开源的

居然和Odin是一摸一样

居然网上所有人都没提,但所有人都心里知道

居然作者老哥现在在微软工作

居然这老哥还有好几个库是前缀Naughty命名的

居然这老哥还涉猎很多图形学相关知识+项目

(操作:只要在场景中,添加一个GameObject,然后在添加Dropdown Test组件)

上面的黄色标签如何出现呢?

只要故意这么写的

	[System.Serializable]
	public class DropdownNest2
	{
		[Dropdown("GetVectorValues11")]
		public Vector3 vectorValue;

		private DropdownList<Vector3> GetVectorValues()
		{
			return new DropdownList<Vector3>()
			{
				{ "Right", Vector3.right },
				{ "Up", Vector3.up },
				{ "Forward", Vector3.forward }
			};
		}
	}

全局搜索代码

居然发现2个,和Sirenix.OdinInspector一摸一样

//参考:DropdownPropertyDrawer//(NaugthyAttribute)

/// <summary>
/// 直接指向一个类,例如:UBlackboardNaugthyCondition
/// 还是直接指向一个Attribute,(比较靠谱),参考:DropdownPropertyDrawer//(NaugthyAttribute)
/// </summary>
//伪代码,关键在实现: PropertyDrawer 即可OnGUI 绘制。。。
[CustomPropertyDrawer(typeof(UBlackboardNaugthyCondition))]
public class NaugthyConditionDrawer :PropertyDrawerBase//: PropertyDrawer
{
    //继承: PropertyDrawer 的写法
    // public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    // {
    //     base.OnGUI(position, property, label);

    //     var so = property.serializedObject;//这个so 会获取到上一层了,:NaugthyCondition<-LeafTransitionCheck
    //                                     //想获取当前属性(for GUI),用: prop.FindPropertyRelative()
    //                                     //经典的”上下文“或者问题,经常容易”指向错误“
    //     // Debug.LogWarning(property.FindPropertyRelative("title"));
    //     // Debug.LogWarning(so.targetObject.name);//打印看看 so 上一层的错误
    //     // Debug.LogWarning(so.FindProperty("title2"));


    //     //EditorGUILayout.PropertyField(so.FindProperty("title2"));//出错??上一层,所以没有 string title2 =

    //     //EditorGUILayout.PropertyField(property);//绘制自己,可以的!!!

    //     EditorGUILayout.PropertyField(property.FindPropertyRelative("title"));

    //     Debug.LogError(attribute);
    // }

    protected override void OnGUI_Internal(Rect rect, SerializedProperty property, GUIContent label)
    {
        throw new System.NotImplementedException();
    }
}

上图的代码如下

		private object GetValues(SerializedProperty property, string valuesName)
		{
			object target = PropertyUtility.GetTargetObjectWithProperty(property);

			FieldInfo valuesFieldInfo = ReflectionUtility.GetField(target, valuesName);
			if (valuesFieldInfo != null)
			{
				return valuesFieldInfo.GetValue(target);
			}

			PropertyInfo valuesPropertyInfo = ReflectionUtility.GetProperty(target, valuesName);
			if (valuesPropertyInfo != null)
			{
				return valuesPropertyInfo.GetValue(target);
			}

			MethodInfo methodValuesInfo = ReflectionUtility.GetMethod(target, valuesName);
			if (methodValuesInfo != null &&
				methodValuesInfo.ReturnType != typeof(void) &&
				methodValuesInfo.GetParameters().Length == 0)
			{
				return methodValuesInfo.Invoke(target, null);
			}

			return null;
		}

关键在于第一个方法的第一行代码

再深入定位一下代码 

		/// <summary>
		/// Gets the object that the property is a member of
		/// </summary>
		/// <param name="property"></param>
		/// <returns></returns>
		public static object GetTargetObjectWithProperty(SerializedProperty property)
		{
			string path = property.propertyPath.Replace(".Array.data[", "[");
			object obj = property.serializedObject.targetObject;
			string[] elements = path.Split('.');

			for (int i = 0; i < elements.Length - 1; i++)
			{
				string element = elements[i];
				if (element.Contains("["))
				{
					string elementName = element.Substring(0, element.IndexOf("["));
					int index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
					obj = GetValue_Imp(obj, elementName, index);
				}
				else
				{
					obj = GetValue_Imp(obj, element);
				}
			}

			return obj;
		}

//上面这个代码也解决了我多天对Odin的Override写法疑惑

很多天,都被Odin恶心到,是因为要或者各种上下文,而总是出现各种意外情况

因为他们(无论是Odin还是NaughtyAttributes)是通过【一定的命名规则】,就是.XXXX.data;甚至是 XXX.#name这样的命名定位的

(或者这就是标签?)

也很暴力的解决方法

就是string.Replace('','')

//非常“微软”

结果

(其实,关键,是你已经得到一个免费的开源的反射帮助类 ReflectionUtil)

而关键在于第一行代码,就是要先“找到” SerializedProperty 

所以不知道为什么Odin 不暴露SerializedProperty,而非要整自己的花活。。。。???为什么??

(当然我前面4个文章有解释为什么)

Odin始终提供了巨量的API,巨量的标签,一个良好的封装,各种文档,各种新手视频

(虽然视频没说很清楚,看了更疑惑了)

个人结论

一开始对Odin无感,是刚好项目做不成,也是因为Editor编辑器的问题

现在对Odin无感,更多是因为十多年前已经学习过 html + CSS

是一个很复杂的情感(所以才写了总共5个文章,深入分析Odin)

无论是Odin还是NaughtyAttributes的代码,看着这样的代码,都让我回到了初学C#是的思绪,大量无用的API,大量的文档,大量的知识,量大管饱。。。。。。。。。。。。。。。。。

但是如果你是一个程序界新人,C#新人,或者Odin是一个不错的入门学习资料

当然,Odin的平替,这个开源的NaughtyAttributes更是你的入门学习资料

而且,这个老哥,更是你学习的榜样。。。。。。。。

(但是这个老哥,的NaughtyAttributes 写法是很保守,很严谨的,很规范的,微软式的代码)

https://github.com/dbrizov

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

avi9111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值