unity中会有像[range(0,1)]这样的特性写法,其非常便利的限制了变量范畴但是。我一直很好奇这是怎么实现的,所以翻了翻其他博主对其的解释和应用。
一,什么是特性
有一种解释我很能接受,特性就像牡蛎附在东西上。其素质也是一种东西,特殊之处在于其编译时就存在了,也就是在措施运行之前就存在了。
二,如何界说一个特性
1 namespace UnityEngine 2 { 3 4 [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] 5 6 public abstract class PropertyAttribute : Attribute 7 { 8 protected PropertyAttribute(); 9 10 public int order { get; set; } 11 } 12 }
只是啥=。= 不就是一个东西吗,我copy了unity中的一段特性代码。事实上所有的特性都担任 Attribute,unity在中多封装了一层 PropertyAttribute ,且给每个特性加上了一个ID。
所以界说一个特性只需要担任 Attribute 就可以了。
那么其上面的特性 AttributeUsage又暗示什么呢,
三,特性的使用
AttributeUsage=。=直接说明了特性的使用范畴嘛,后面标注了几个属性 AttributeTargets.Field代表可以附着在字段上,其他处所不能加不上这个标签特性。AttributeTargets自己是枚举值,且其是c#预制的特性变量。 Inherited 是否可以担任这就很好理解了 AllowMultiple 是否能够混合使用,也就是一个类上挂俩三个特性。理解可这些参数之后就可以本身写一个特性玩玩了,这里我写一个自界说的debuginfo在unity中挪用
(1)声明
using System; using UnityEngine; //特性所能使用的范畴 [AttributeUsage(AttributeTargets.Method|AttributeTargets.Field , AllowMultiple =true)] public class DebugerCoderAttribute : UnityEngine.PropertyAttribute { private string codename; private string codeLasttime; private bool Ischeck; private string message; public DebugerCoderAttribute(string CoderName, string CodeLastTime, bool Checked) { codename = CoderName; codeLasttime = CodeLastTime; Ischeck = Checked; message = ""; } public DebugerCoderAttribute(string CoderName, string CodeLastTime,string OtherInfo, bool Checked) { codename = CoderName; codeLasttime = CodeLastTime; Ischeck = Checked; message = OtherInfo; } public string ScriptsCoder { get { return codename; } } public string ScriptsTime { get { return codeLasttime; } } public bool ScriptsIsChecked { set { Ischeck = value; } get { return Ischeck; } } public string Message { set { message = value; } get { return message; } } }
(2)脚本挪用
public class TempReadJobScrpts : MonoBehaviour { [DebugerCoder("yang", "1995", false, Message = "只能注释要领名,在MyinfoDebug中可以改削完成指定位置信息读取")] public void MyMethod() { } }
(3)反射挪用(更好点可以写到editor中运行到达自行检测运行脚本要领挨次的目的)
/*此类可以写在editor中运行到达自运行检测的目的*/ public class MyInfoDebuger : MonoBehaviour { public GameObject SelectObj; /*目前只能读取脚本为 SelectObj中 TempReadJobScrpts的注释信息*/ public readonly string TempReadJobScrpts= "TempReadJobScrpts"; public bool IsReadBug = true; public bool ShowAllMehodOfScripts = false; // Use this for initialization void Start () { if (IsReadBug) ShowDebugInfo(); } void GetAllMyPrivareScripts() { //获取所有自界说脚本的名字 } public void ShowDebugInfo() {//这里需要改削成获取所有脚本的信息参数 try { //仅在unity 中需要使用 此处非自执行。。便当脚本效率对照低 //当要领插手public时 此处可以获取 MonoBehaviour[] monos = SelectObj.GetComponents<MonoBehaviour>(); foreach (var item in monos) { if (item.GetType().ToString().EndsWith(TempReadJobScrpts)) { Debug.Log("is reading>>:" + ((MonoBehaviour)item).GetType()); //显示有标签的要领 此处只能用在要领上 此处设置的是私有和共有要领 MethodInfo[] meths = ((MonoBehaviour)item).GetType().GetMethods(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public); foreach (MethodInfo met in meths) { if (Attribute.GetCustomAttributes(met).Length>0) { if (ShowAllMehodOfScripts) Debug.Log(met.Name); Attribute[] attris = Attribute.GetCustomAttributes(met); foreach (Attribute at in attris) { if (at.GetType() == typeof(DebugerCoderAttribute)) { DebugerCoderAttribute info = (DebugerCoderAttribute)at; Debug.Log("coder:" + info.ScriptsCoder + "," + " message:" + info.Message+" date:"+info.ScriptsTime); } } } } } } } catch (System.Exception ex) { Debug.Log(this.name+" "+ ex.ToString()); } } }
运行布局:
,