虽然mono是支持unicode的。可以在枚举里写中文,但是我还是觉得写英文好一些。可是在编辑器上策划是希望看到的是中文的,还有就是枚举的展示排序功能,策划在编辑的时候为了方便希望把常用的枚举排上前面。
把如下代码放到你的工程里就可以直接用了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
using UnityEngine; using System; #if UNITY_EDITOR using UnityEditor; using System.Collections.Generic; using System.Linq; using System.Reflection; #endif [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)] public class EnumLabelAttribute : PropertyAttribute { public string label; public int[] order = new int[0] ; public EnumLabelAttribute(string label) { this.label = label; } public EnumLabelAttribute(string label,params int[] order) { this.label = label; this.order = order; } } #if UNITY_EDITOR [CustomPropertyDrawer(typeof(EnumLabelAttribute))] public class EnumLabelDrawer : PropertyDrawer { private Dictionary<string, string> customEnumNames = new Dictionary<string, string>(); public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SetUpCustomEnumNames(property, property.enumNames); if (property.propertyType == SerializedPropertyType.Enum) { EditorGUI.BeginChangeCheck(); string[] displayedOptions = property.enumNames .Where(enumName => customEnumNames.ContainsKey(enumName)) .Select<string, string>(enumName => customEnumNames[enumName]) .ToArray(); int[] indexArray = GetIndexArray (enumLabelAttribute.order); if(indexArray.Length != displayedOptions.Length) { indexArray = new int[displayedOptions.Length]; for(int i =0; i< indexArray.Length; i++){ indexArray[i] = i; } } string[] items = new string[displayedOptions.Length]; items[0] = displayedOptions[0]; for (int i=0; i<displayedOptions.Length; i++) { items[i] = displayedOptions[indexArray[i]]; } int index = -1; for (int i=0; i<indexArray.Length; i++) { if (indexArray[i] == property.enumValueIndex) { index = i; break; } } if ( (index == -1) && (property.enumValueIndex != -1) ) { SortingError (position,property,label); return; } index = EditorGUI.Popup(position, enumLabelAttribute.label,index, items); if (EditorGUI.EndChangeCheck()) { if (index >= 0) property.enumValueIndex = indexArray[index]; } } } private EnumLabelAttribute enumLabelAttribute { get { return (EnumLabelAttribute)attribute; } } public void SetUpCustomEnumNames(SerializedProperty property, string[] enumNames) { object[] customAttributes = fieldInfo.GetCustomAttributes(typeof(EnumLabelAttribute), false); foreach (EnumLabelAttribute customAttribute in customAttributes) { Type enumType = fieldInfo.FieldType; foreach (string enumName in enumNames) { FieldInfo field = enumType.GetField(enumName); if (field == null) continue; EnumLabelAttribute[] attrs = (EnumLabelAttribute[])field.GetCustomAttributes(customAttribute.GetType(), false); if (!customEnumNames.ContainsKey(enumName)) { foreach (EnumLabelAttribute labelAttribute in attrs) { customEnumNames.Add(enumName, labelAttribute.label); } } } } } int[] GetIndexArray (int[] order) { int[] indexArray = new int[order.Length]; for (int i = 0; i < order.Length; i++) { int index = 0; for (int j = 0; j < order.Length; j++) { if (order[i] > order[j]) { index++; } } indexArray[i] = index; } return (indexArray); } void SortingError (Rect position, SerializedProperty property, GUIContent label) { EditorGUI.PropertyField(position, property, new GUIContent(label.text + " (sorting error)")); EditorGUI.EndProperty(); } } public class EnumLabel { static public object GetEnum(Type type, SerializedObject serializedObject, string path) { SerializedProperty property = GetPropety(serializedObject,path); return System.Enum.GetValues(type).GetValue(property.enumValueIndex); } static public object DrawEnum(Type type, SerializedObject serializedObject, string path) { return DrawEnum(type,serializedObject, GetPropety(serializedObject,path)); } static public object DrawEnum(Type type, SerializedObject serializedObject,SerializedProperty property) { serializedObject.Update(); EditorGUILayout.PropertyField(property); serializedObject.ApplyModifiedProperties(); return System.Enum.GetValues(type).GetValue(property.enumValueIndex); } static public SerializedProperty GetPropety(SerializedObject serializedObject, string path) { string []contents = path.Split('/'); SerializedProperty property = serializedObject.FindProperty(contents[0]); for(int i=1; i< contents.Length; i++){ property = property.FindPropertyRelative(contents[i]); } return property; } } #endif |
使用是这样的,第二个参数就是排序。接收int的不固定参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { [EnumLabel("我是的类型",10,1,5,2)] public NewType newType = NewType.One; } public enum NewType : byte { [EnumLabel("我是1")] One = 10, [EnumLabel("我是2")] Two = 1, [EnumLabel("我是3")] Three = 5, [EnumLabel("我是4")] Four = 2 } |
OK 中文与排序都OK了。
但是,有时候我们做编辑器的时候是自己调用OnInspectorGUI来绘制面板的。而且我的枚举对象可能会在另外一个子对象里,或者在子对象里的一个List<T>里面的子对象里。
比如这样, class.data.newType 就是这个类对象的结构,你可以按照你自己类的结构去拼这个字符串。
1 2 3 4 5 6 7 8 9 10 11 12 |
public override void OnInspectorGU() { NewType oldType = (NewType)EnumLabel.GetEnum(typeof(NewType),serializedObject,"class/data/newType"); NewType newType = (NewType)EnumLabel.DrawEnum(typeof(NewType),serializedObject,"class/data/newType"); if(oldType != newType) { //类型发生改变 } } |
还有一种特殊的就是可能枚举在list<T>里,这样在绘制的时候是需要遍历的。
1 2 3 4 5 6 7 8 9 10 11 12 |
public override void OnInspectorGU() { SerializedProperty property = EnumLabel.GetPropety(serializedObject,"class/datas"); for(int i =0; i< count; i++) { SerializedProperty eProperty = property.GetArrayElementAtIndex(i); NewType newType = (NewType)EnumLabel.DrawEnum(typeof(NewType),serializedObject ,eProperty.FindPropertyRelative("newType")); } } |
OK大功告成。
参考文章:
https://github.com/anchan828/property-drawer-collection/blob/master/EnumLabel/EnumLabelAttribute.cs
http://forum.unity3d.com/threads/enum-inspector-sorting-attribute.357558/
- 本文固定链接: https://www.xuanyusong.com/archives/4213
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!
雨松大大,问个问题吗,有个需求是想在场景内的3D模型上显示一些UI信息,感觉UGUI的有些特性用2D的sprite无法完全表达,这个要咋个弄哦?
喔。。我好傻哦。。直接加个canvas就可以咯~~~~
哈哈
7月13日的,好新,充满希望!
新技能GET!
现在mmorpg手游的角色位置同步。应该传输摇杆的,还是坐标的信息到服务器去? 持续传还是出发传
其实都可以,但是我倾向客户端传输摇杆,比如摇杆一直朝着一个方向,就可以不用每一帧都发送。。
我也是这样想。去模拟摇杆还是比直接改位置好些,不然人可能都会跑地底下去
如果这样,那么后进入场景的玩家,怎么初始化已有玩家的位置信息,是个问题。服务器是不存玩家位置信息的,如果存,就要一直更新。现在想法是,进入时,服务器就把已有的人的位置信息请求一遍发给他,这样有延误。不知道有什么好的解决办法
服务器要存玩家位置。 回来的消息都是要带玩家的位置 如果客户端发现与服务器相差较大 直接拉回 采用服务器的位置。。
完成了。摇杆变化才会发送数据,对方接收到后以transform.Translate的方式移动。不过只有摇杆一直变化才能持续移动,又不愿在update里面写(如果没办法的话)。传统网游移动方式是什么
Get