注:转载请标明原文地址:https://segmentfault.com/a/11...
汉化效果
利用Attribute+Editor可以自定义一些属性,实现汉化:
用法示例
RenameTest.cs
using UnityEngine;
using UnityEngine.Events;
[System.Serializable]
public class Item {
[Rename("名称")]
public string name;
[Rename("类型")]
public Type type = Type.A;
public enum Type {
[Rename("消耗品")]
A,
[Rename("任务道具")]
B
}
}
/// <summary>
/// 重命名属性测试
/// <para>ZhangYu 2018-06-21</para>
/// </summary>
public class RenameTest : MonoBehaviour {
[Title("标题", "green")]
public string title;
[RenameInEditor("等级")]
public int level;
[RenameInEditor("姓名")]
public string name;
[Rename("武器")]
public Weapon weapon;
[Rename("铠甲")]
public Armor armor;
[RenameInEditor("道具列表")]
public Item[] items;
[RenameInEditor("死亡回调方法")]
public UnityEvent onDead;
[RenameInEditor("复活回调方法")]
public UnityEvent onRevive;
public enum Weapon {
[Rename("蛇矛")]
A,
[Rename("胜宗刀")]
B,
[Rename("青缸剑")]
C,
[Rename("李广弓")]
D
}
public enum Armor {
[Rename("钢甲")]
One,
[Rename("火焰甲")]
Two,
[Rename("青龙甲")]
Three,
[Rename("藤甲")]
Four
}
private void Start () {
}
}
CustomRenameEditors.cs
using UnityEditor;
[CustomEditor(typeof(RenameTest))][CanEditMultipleObjects]
public class RenameTestEditor : RenameEditor { }
使用方式
需要导入两个类: RenameEditor.cs和RenameAttribute.cs 配合使用
RenameEditor.cs要放在Editor文件夹下 RenameAttribute.cs不要放在Editor下
1.使用[RenameInEditor]标记需要重命名的属性
2.创建一个Editor继承RenameEditor 绑定需要重命名的类
这样Editor绘制Inspector的时候 检查到RenameInEditor的属性 会优先使用重命名的名称
注意:没有子集的属性 可以直接使用Rename 不需要Editor 但是有子集的属性 需要Editor和RenameInEditor配合使用才能正常改名 所以为了完全汉化 还是写一个Editor吧
由于RenameEditor和Attribute仅在Editor下有效,所以不用担心发布后的体积问题
RenameAttribute脚本
RenameAttribute.cs
using UnityEngine;
#if UNITY_EDITOR
using System;
using UnityEditor;
using System.Reflection;
using System.Text.RegularExpressions;
#endif
/// <summary>
/// 重命名属性
/// <para>ZhangYu 2018-06-21</para>
/// </summary>
#if UNITY_EDITOR
[AttributeUsage(AttributeTargets.Field)]
#endif
public class RenameAttribute : PropertyAttribute {
/// <summary> 枚举名称 </summary>
public string name = "";
/// <summary> 文本颜色 </summary>
public string htmlColor = "#000000";
/// <summary> 重命名属性 </summary>
/// <param name="name">新名称</param>
public RenameAttribute(string name) {
this.name = name;
}
/// <summary> 重命名属性 </summary>
/// <param name="name">新名称</param>
/// <param name="htmlColor">文本颜色 例如:"#FFFFFF" 或 "black"</param>
public RenameAttribute(string name, string htmlColor) {
this.name = name;
this.htmlColor = htmlColor;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(RenameAttribute))]
public class RenameDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
// 替换属性名称
RenameAttribute rename = (RenameAttribute)attribute;
label.text = rename.name;
// 重绘GUI
Color defaultColor = EditorStyles.label.normal.textColor;
EditorStyles.label.normal.textColor = htmlToColor(rename.htmlColor);
bool isElement = Regex.IsMatch(property.displayName, "Element \\d+");
if (isElement) label.text = property.displayName;
if (property.propertyType == SerializedPropertyType.Enum) {
drawEnum(position, property, label);
} else {
EditorGUI.PropertyField(position, property, label, true);
}
EditorStyles.label.normal.textColor = defaultColor;
}
// 绘制枚举类型
private void drawEnum(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginChangeCheck();
// 获取枚举相关属性
Type type = fieldInfo.FieldType;
string[] names = property.enumNames;
string[] values = new string[names.Length];
Array.Copy(names, values, names.Length);
while (type.IsArray) type = type.GetElementType();
// 获取枚举所对应的RenameAttribute
for (int i = 0; i < names.Length; i++) {
FieldInfo info = type.GetField(names[i]);
RenameAttribute[] atts = (RenameAttribute[])info.GetCustomAttributes(typeof(RenameAttribute), true);
if (atts.Length != 0) values[i] = atts[0].name;
}
// 重绘GUI
int index = EditorGUI.Popup(position, label.text, property.enumValueIndex, values);
if (EditorGUI.EndChangeCheck() && index != -1) property.enumValueIndex = index;
}
/// <summary> Html颜色转换为Color </summary>
/// <param name="hex"></param>
/// <returns></returns>
public static Color htmlToColor(string hex) {
// 编辑器默认颜色
if (string.IsNullOrEmpty(hex)) return new Color(0.705f, 0.705f, 0.705f);
#if UNITY_EDITOR
// 转换颜色
hex = hex.ToLower();
if (hex.IndexOf("#") == 0 && hex.Length == 7) {
int r = Convert.ToInt32(hex.Substring(1, 2), 16);
int g = Convert.ToInt32(hex.Substring(3, 2), 16);
int b = Convert.ToInt32(hex.Substring(5, 2), 16);
return new Color(r / 255f, g / 255f, b / 255f);
} else if (hex == "red") {
return Color.red;
} else if (hex == "green") {
return Color.green;
} else if (hex == "blue") {
return Color.blue;
} else if (hex == "yellow") {
return Color.yellow;
} else if (hex == "black") {
return Color.black;
} else if (hex == "white") {
return Color.white;
} else if (hex == "cyan") {
return Color.cyan;
} else if (hex == "gray") {
return Color.gray;
} else if (hex == "grey") {
return Color.grey;
} else if (hex == "magenta") {
return Color.magenta;
} else if (hex == "orange") {
return new Color(1, 165 / 255f, 0);
}
#endif
return new Color(0.705f, 0.705f, 0.705f);
}
}
#endif
/// <summary>
/// 添加标题属性
/// <para>ZhangYu 2018-06-21</para>
/// </summary>
#if UNITY_EDITOR
[AttributeUsage(AttributeTargets.Field)]
#endif
public class TitleAttribute : PropertyAttribute {
/// <summary> 标题名称 </summary>
public string title = "";
/// <summary> 文本颜色 </summary>
public string htmlColor = "#B3B3B3";
/// <summary> 在属性上方添加一个标题 </summary>
/// <param name="title">标题名称</param>
public TitleAttribute(string title) {
this.title = title;
}
/// <summary> 在属性上方添加一个标题 </summary>
/// <param name="title">标题名称</param>
/// <param name="htmlColor">文本颜色 例如:"#FFFFFF" 或 "black"</param>
public TitleAttribute(string title, string htmlColor) {
this.title = title;
this.htmlColor = htmlColor;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(TitleAttribute))]
public class TitleAttributeDrawer : DecoratorDrawer {
// 文本样式
private GUIStyle style = new GUIStyle(EditorStyles.label);
public override void OnGUI(Rect position) {
// 获取Attribute
TitleAttribute rename = (TitleAttribute)attribute;
style.fixedHeight = 18;
style.normal.textColor = RenameDrawer.htmlToColor(rename.htmlColor);
// 重绘GUI
position = EditorGUI.IndentedRect(position);
GUI.Label(position, rename.title, style);
}
public override float GetHeight() {
return base.GetHeight() - 3;
}
}
#endif
/// <summary>
/// 重命名脚本编辑器中的属性名称
/// <para>ZhangYu 2018-06-21</para>
/// </summary>
#if UNITY_EDITOR
[AttributeUsage(AttributeTargets.Field)]
#endif
public class RenameInEditorAttribute : PropertyAttribute {
/// <summary> 新名称 </summary>
public string name = "";
/// <summary> 重命名属性 </summary>
/// <param name="name">新名称</param>
public RenameInEditorAttribute(string name) {
this.name = name;
}
}
RenameEditor脚本
using UnityEditor;
using UnityEngine;
using System;
using System.Reflection;
using System.Collections.Generic;
/// <summary>
/// 重命名 编辑器
/// <para>ZhangYu 2018-06-21</para>
/// </summary>
//[CanEditMultipleObjects][CustomEditor(typeof(ClassName))]
public class RenameEditor : Editor {
// 绘制GUI
public override void OnInspectorGUI() {
EditorGUI.BeginChangeCheck();
drawProperties();
if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties();
}
// 绘制属性
protected virtual void drawProperty(string property, string label) {
SerializedProperty pro = serializedObject.FindProperty(property);
if (pro != null) EditorGUILayout.PropertyField(pro, new GUIContent(label), true);
}
// 绘制所有属性
protected virtual void drawProperties() {
// 获取类型和可序列化属性
Type type = target.GetType();
List<FieldInfo> fields = new List<FieldInfo>();
FieldInfo[] array = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
fields.AddRange(array);
// 获取父类的可序列化属性
while (IsTypeCompatible(type.BaseType) && type != type.BaseType) {
type = type.BaseType;
array = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
fields.InsertRange(0, array);
}
// 绘制所有属性
for (int i = 0; i < fields.Count; i++) {
FieldInfo field = fields[i];
// 非公有但是添加了[SerializeField]特性的属性
if (!field.IsPublic) {
object[] serials = field.GetCustomAttributes(typeof(SerializeField), true);
if (serials.Length == 0) continue;
}
// 公有但是添加了[HideInInspector]特性的属性
object[] hides = field.GetCustomAttributes(typeof(HideInInspector), true);
if (hides.Length != 0) continue;
// 绘制符合条件的属性
RenameInEditorAttribute[] atts = (RenameInEditorAttribute[])field.GetCustomAttributes(typeof(RenameInEditorAttribute), true);
drawProperty(field.Name, atts.Length == 0 ? field.Name : atts[0].name);
}
}
// 脚本类型是否符合序列化条件
protected virtual bool IsTypeCompatible(Type type) {
if (type == null || !(type.IsSubclassOf(typeof(MonoBehaviour)) || type.IsSubclassOf(typeof(ScriptableObject))))
return false;
return true;
}
}
以上实现了重命名的功能,其实利用Attribute+Editor还可以实现更丰富的效果,完全可以自定义一套模板,利用简单的特性添加,就可以实现丰富的编辑器样式
PS1:感谢雨松momo和他的文章:《Unity3D研究院之Inspector面板枚举的别名与排序(八十九)》
PS2:转载请注明原文地址:https://segmentfault.com/a/11...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。