Unity3d开发中Custom Attributes(C#)的应用
来源:互联网 发布:war包解析源码 编辑:程序博客网 时间:2024/04/30 03:21
1. Unity3d中Attributes应用
特性(Attribute): 官方解释:特性是给指定的某一声明的一则附加的声明性信息。 允许类似关键字的描述声明。它对程序中的元素进行标注,如类型、字段、方法、属性等。特性是一种类,这些类继承于System.Attribute类,用于对类、属性、方法、事件等进行描述,主要用在反射中。但从面向对象的级别看,其实Attribute是类型级别的,而不是对象级别。
在Unity编程中,我们经常使用到Attributes1)序列化一个自定义数据类,该类才会显示在Inspector,内容才能被存储。
[System.Serializable]public class CustomData{ public Color color; public Vector3 position}2) Plugins功能,允许使用unity脚本调用C、C++、ObjectC方法。[DllImport ("__Internal", CharSet=CharSet.Ansi)]public static extern void CustomPluginFunction();
2. Unity3d中的Custom Attributes的应用。
自定义特性(Custom Attribute): 通过定义一个特性类,可以创建您自己的自定义特性。该特性类直接或间接地从Attribute派生,有助于方便快捷地在元数据中标识特性定义。
以下列出常用的几项,更多信息请参考Unity Scripting API : UnityEngine -> Attributes
1)添加一个项目到Unity的菜单栏。
[MenuItem ("MyMenu/Do Something")]public static function DoSomething() { Debug.Log ("Doing Something...");}2)[ContextMenu(name)]
添加一个选项名字为name的选项到component的context menu中,选择name选项会运行特性关联的方法。[ContextMenu(MyMenu/Do Something;)]public static function DoSomething() { Debug.Log ("Doing Something...");}3)[HideInInspector] and [SerializeField]
第一个是在Inspector隐藏公共变量,第二个是在Inspector显示私有变量。public class ExampleClass : MonoBehaviour { [HideInInspector] public int a = 5; [SerializeField] private int b = 1;}4) [Range(float, float)]
限制变量的范围,改变变量用划动条操作。
3. 使用Custom Attributes和Reflection,在Inspector中映射方法名。
在开发中,我们有时需求在脚本中可以配置一个事件的回调函数,当事件触发时,回调这个方法。方法名一般以字符串的形式写在变量中。 这样很容易出错。如果是一个下拉的选择框,这样就不容易出错了。实现这个功能我们需要用到Custom Attributes,Reflection和Unity3d的Property Drawers技术。
1) 我们要定义一个TriggerEvent类,这个类存储要发送目标对象和发送的方法名。
TriggerEventAttribute是一个自定义的特性类,其中变量_name用来存储回调方法的名字。
using UnityEngine;using System.Collections;[System.Serializable]public class TriggerEvent {public GameObject _target;public string _method;public void Invoke(){if (_target != null && !string.IsNullOrEmpty(_method))_target.SendMessage(_method, SendMessageOptions.RequireReceiver);}}public class TriggerEventAttribute : System.Attribute{public string _name;public TriggerEventAttribute(){}public TriggerEventAttribute(string name){_name = name;}}2) 使用PropertyDrawer处理TriggerEvent类在Inspector中的显示
OnGUI函数三个参数的意思分别为:第一个绘制组件的起点坐标,第二个参数返回一个property,通过它我们能得到TriggerEvent类中定义变量的属性。第三个参数是这个属性使用的标签,返回的是定义TriggerEvent类变量的名字。
[CustomPropertyDrawer(typeof(TriggerEvent))]public class TriggerEventDrawer : PropertyDrawer {public override void OnGUI (Rect position, SerializedProperty property, GUIContent label){EditorGUI.BeginProperty(position, label, property);Rect prefabRect = new Rect(position.x, position.y + position.height / 3, position.width * 0.25f, position.height / 3);Rect valueRect = new Rect(prefabRect.x + prefabRect.width/2, prefabRect.y, position.width * 0.75f, position.height / 3);GUI.Label(prefabRect, "Target", EditorStyles.miniLabel);SerializedProperty targetProperty = property.FindPropertyRelative("_target");targetProperty.objectReferenceValue = EditorGUI.ObjectField(valueRect, targetProperty.objectReferenceValue, typeof(GameObject), true);prefabRect.y += prefabRect.height + 2;valueRect.y += valueRect.height + 2;SerializedProperty methodProperty = property.FindPropertyRelative("_method");GUI.Label(prefabRect, "Method", EditorStyles.miniLabel);List<string> names = new List<string>();List<string> methodNames = new List<string>();names.Add("None");methodNames.Add(null);int index = 0;GameObject obj = targetProperty.objectReferenceValue as GameObject;if (obj != null){MonoBehaviour[] components = obj.GetComponents<MonoBehaviour>();foreach(MonoBehaviour component in components){Type type = component.GetType();MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);foreach (MethodInfo method in methods){object[] attributes = method.GetCustomAttributes(typeof(TriggerEventAttribute), true);if (attributes.Length > 0){ParameterInfo[] parameters = method.GetParameters();bool addMethod = false;if(parameters.Length <= 1){addMethod = true;}if(addMethod){TriggerEventAttribute attribute = (TriggerEventAttribute)attributes[0];if (string.IsNullOrEmpty(attribute._name)){string name = ObjectNames.NicifyVariableName(method.Name);names.Add(type.Name + ": " + name);}else{names.Add(type.Name + ": " + attribute._name);}if (methodProperty.stringValue == method.Name)index = methodNames.Count;methodNames.Add(method.Name);}}}}if (names.Count > 1){EditorGUI.BeginChangeCheck();index = EditorGUI.Popup(valueRect, index, names.ToArray());if (EditorGUI.EndChangeCheck())methodProperty.stringValue = methodNames[index];}else{GUI.Label(valueRect, "None");}}else{GUI.Label(valueRect, "None");}EditorGUI.EndProperty();}public override float GetPropertyHeight(SerializedProperty property, GUIContent label){return base.GetPropertyHeight(property, label) * 3;}}3)如何使用
如下图所示,TriggerEventComponent中target中拖入要通知的gameobject,在下面的Method变量中就会显示目标gameobject中,标记了[TriggerEvent] 属性的方法。
using UnityEngine;using System.Collections;public class TriggerEventComponent : MonoBehaviour {public TriggerEvent _trigger;[ContextMenu("Trigger")]void Trigger(){_trigger.Invoke();}}using UnityEngine;using System.Collections;public class DoSomething : MonoBehaviour {[TriggerEvent]void DoSomething1(){Debug.Log("DoSomething1");}[TriggerEvent("DoSomethingTest")]void DoSomething2(){Debug.Log("DoSomething2");}}通过以上的思路,我们也可以实现,向Inspector中一个string类型变量输入一个标识,找到对应的枚举类型后,才输入生效;Custom Attributes可以看做一个标识,我再代码中加入这个标识,我们可以在检索出所有标识代码所附属的prefab。
- Unity3d开发中Custom Attributes(C#)的应用
- MS Chart Control的自定义属性(custom attributes)
- yii中attributes属性的巧妙应用
- Android开发之自定义属性(Define Custom Attributes)
- Android开发之自定义属性(Define Custom Attributes)
- .Net——自定义特性(Custom Attributes)的创建与查看
- Magento - get custom attributes
- Using custom client attributes
- Attributes and custom properties
- Objective-C创建目录接口createDirectoryAtPath:withIntermediateDirectories:attributes:error:中参数attributes的设置
- Objective-C创建目录接口createDirectoryAtPath:withIntermediateDirectories:attributes:error:中参数attributes的设置
- Unity3D Attributes用法小结(一)
- Form Builder开发中可视属性集(Visual Attributes)
- C#中Attributes的用法
- C#中 Attributes的用法
- C#Attributes
- windows metro中Custom Control的开发和使用
- unity3d开发的android应用中加入AD系统的具体步骤
- NAND FLASH ECC校验原理与实现
- 一个字符串中出现次数最多的单词 java语言实现
- UNIX基本命令-目录及文件操作
- 2.TAU
- zend studio修改默认的workspace
- Unity3d开发中Custom Attributes(C#)的应用
- 超长位数的字符数的加法与乘法
- linux 性能分析常规逻辑和手段总结
- 【比特币】大数的紧凑表示法
- 3a.Service Request(UE triggered
- odex转成dex
- 2014.9.9 布局属性
- Android Studio快捷键设置成跟Eclipse一样
- freeRADIUS RLM_UNIX模块说明