这是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 写法是很保守,很严谨的,很规范的,微软式的代码)