标题Unity汉化字段重命名Inspector中字段属性时显示错位及其解决办法

众所周知,OnInspectorGUI()和OnGUI()是Unity的Editor和PropertyDrawer类里的相关函数,通过对该方法的重写,可以自定义对Inspector面板的绘制。于是乎,原本干净整洁的Unity Inspector开始越来越多的出现了中文。网上随便一搜,大街小巷的都是教程

如出一辙的重命名教程
不管教程怎么变,都是换汤不换药,就是指定自定义属性,然后重写OnInspectorGUI()或者OnGUI()修改字段的Label。但是默认情况下这种方法非常好使,不会出现怎么问题。

但是!,如果大家平时写代码的时候不拘泥与效果实现,在注重程序的可维护性时,一般都会建大量的底层类,而且存在大量组合关系的时候问题就出现了

当尝试序列化一个非Mono对象脚本时,视图出现了显示错误,高度不会自动更新。

通过阅读PropertyDrawer的源码发现了问题所在


public abstract class PropertyDrawer : GUIDrawer{internal PropertyAttribute m_Attribute;internal System.Reflection.FieldInfo m_FieldInfo;public PropertyAttribute attribute => this.m_Attribute;public System.Reflection.FieldInfo fieldInfo => this.m_FieldInfo;internal void OnGUISafe(Rect position, SerializedProperty property, GUIContent label){ScriptAttributeUtility.s_DrawerStack.Push(this);this.OnGUI(position, property, label);ScriptAttributeUtility.s_DrawerStack.Pop();}///
///Override this method to make your own IMGUI based GUI for the property.///
///Rectangle on the screen to use for the property GUI.///The SerializedProperty to make the custom GUI for.///The label of this property.public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label){EditorGUI.DefaultPropertyField(position, property, label);EditorGUI.LabelField(position, label, EditorGUIUtility.TempContent("No GUI Implemented"));}///
///Override this method to make your own UIElements based GUI for the property.///
///The SerializedProperty to make the custom GUI for.//The element containing the custom GUI.///public virtual VisualElement CreatePropertyGUI(SerializedProperty property) => (VisualElement) null;internal float GetPropertyHeightSafe(SerializedProperty property, GUIContent label){ScriptAttributeUtility.s_DrawerStack.Push(this);float propertyHeight = this.GetPropertyHeight(property, label);ScriptAttributeUtility.s_DrawerStack.Pop();return propertyHeight;}///
///Override this method to specify how tall the GUI for this field is in pixels.///
///The SerializedProperty to make the custom GUI for.///The label of this property.//The height in pixels.///public virtual float GetPropertyHeight(SerializedProperty property, GUIContent label) => 18f;internal bool CanCacheInspectorGUISafe(SerializedProperty property){ScriptAttributeUtility.s_DrawerStack.Push(this);bool flag = this.CanCacheInspectorGUI(property);ScriptAttributeUtility.s_DrawerStack.Pop();return flag;}///
///Override this method to determine whether the inspector GUI for your property can be cached.///
///The SerializedProperty to make the custom GUI for.//Whether the drawer's UI can be cached.///public virtual bool CanCacheInspectorGUI(SerializedProperty property) => true;}
}

一眼就能看出问题所在,百度的方法没有去重写GetPropertyHeight(SerializedProperty property, GUIContent label)方法,连方法都不重写,怎么让Editor知道怎么绘制你呢?

我们开始重写,首先调用基类的方法

float baseHeight = base.GetPropertyHeight(property,label);

然后发生问题大部分都是自定义类的序列化该序列化对象,通过阅读文档可知属于

SerializedPropertyType.Generic

然后发生问题大部分需要在Inspector中展开序列化对象时错位,阅读文档得知,通过SerializedProperty.isExpanded可以判断对象是否展开

得到代码:

public override float GetPropertyHeight(SerializedProperty property, GUIContent label){float baseHeight = base.GetPropertyHeight(property, label);if (property.isExpanded){if (property.propertyType == SerializedPropertyType.Generic){return baseHeight + EditorGUIUtility.singleLineHeight * property.CountInProperty();}}return baseHeight;
}

我们最后只需要在if内判断该字段展开后的高度即可!出于通用性的原因考虑,这里使用

EditorGUIUtility.singleLineHeight * property.CountInProperty()来得到高度。

其中EditorGUIUtility.singleLineHeight是Unity字段在Inspector中的通用高度,property.CountInProperty()是当前序列化对象的子字段数量。

最后附上优化后的完整代码,支出绝大部分字段的重命名以及颜色修改。

using System;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;namespace Game.Attribute
{#if UNITY_EDITOR[AttributeUsage(AttributeTargets.Field)]
#endifpublic class RenameAttribute : PropertyAttribute {///  枚举名称 public readonly string Name = "";///  文本颜色 public readonly string HtmlColor = "#ffffff";///  重命名属性 /// 新名称public RenameAttribute(string name) {Name = name;}///  重命名属性 /// 新名称/// 文本颜色 例如:"#FFFFFF" 或 "black"public RenameAttribute(string name,string Color) {Name = name;HtmlColor = OrColor;}public RenameAttribute(string name, Color htmlColor) {Name = name;HtmlColor = htmlColor.ToString();}}#if UNITY_EDITOR[CustomPropertyDrawer(typeof(RenameAttribute))]public class RenameDrawer : PropertyDrawer {public override float GetPropertyHeight(SerializedProperty property, GUIContent label){float baseHeight = base.GetPropertyHeight(property, label);if (property.isExpanded){if (property.propertyType == SerializedPropertyType.Generic){return baseHeight + EditorGUIUtility.singleLineHeight * property.CountInProperty();}}return baseHeight;}public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {using (new EditorGUI.PropertyScope(position, label, property)){RenameAttribute rename = (RenameAttribute)attribute;label.text = rename.Name;// 重绘GUIColor defaultColor = EditorStyles.label.normal.textColor;EditorStyles.label.normal.textColor = htmlToColor(rename.HtmlColor);bool isElement = Regex.IsMatch(property.displayName, "Element \\d+");if (isElement) if (base.attribute != rename) label.text = property.displayName; else label.text += property.displayName.Substring(8);if (property.propertyType == SerializedPropertyType.Enum) {DrawEnum(position, property, label);} else if(property.propertyType==SerializedPropertyType.Generic){EditorGUI.PropertyField(position,property, label,true);} else{EditorGUI.PropertyField(position,  property, label);}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();// 获取枚举所对应的RenameAttributefor (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;}// 重绘GUIint index = EditorGUI.Popup(position, label.text, property.enumValueIndex, values);if (EditorGUI.EndChangeCheck() && index != -1) property.enumValueIndex = index;}///  Html颜色转换为Color /// 字符串颜色/// 返回Unity的Color类public static Color htmlToColor(string hex) {hex = hex.ToLower(); if(!String.IsNullOrEmpty(hex)){ColorUtility.TryParseHtmlString(hex, out Color color);return color;}return new Color(0.705f, 0.705f, 0.705f);}}
#endif

Unity汉化字段重命名Inspector中字段属性时显示错位及其解决办法——Unity常见问题相关推荐

  1. mysql字段重命名_MySQL中使用SQL语句对字段进行重命名

    MySQL中,如何使用SQL语句来对表中某一个字段进行重命名呢?我们将使用alter table 这一SQL语句. 重命名字段的语法为:alter table change . 现在我们来尝试把tes ...

  2. 关于虚拟机中安装Ubuntu时界面显示不全的解决办法

    如果帮助到您,还请点个关注吧,hahaha 楼主因为某种特别原因,需要重新装Ubuntu16.04,可是在分区的界面却看不到下一步的按钮了,瞬间头皮发麻.网上说默认分区方式不会遇到这种问题,但是强迫症 ...

  3. html ol 序号不出来,html中ol标签不显示序号的解决办法

    html ol 和 ul 区别之一就是 ol 标签下面的 li 标签会自动带上序号,而是 ul 下面的 li 标签不会.如果 ol li 标签没有序号,原因很简单, 就是你重置了 ol 标签的左内边距 ...

  4. AndroidStudio1.4 manifest 中注册Activity时的错误提示解决办法

    问题截图如下: 解决办法截图如下: 1: File->setting->Editor->Language Injections到如下界面 2:双击右侧选中的Item进入编辑界面 3: ...

  5. JOOQ学习笔记:分页、排序、字段重命名的写法

    环境 JOOQ: "3.9.6" java:1.8 springboot:1.5.10.RELEASE 前言 最近进小黑屋赶项目: 公司封装的分页方法,字段接收上,不能满足我,所以 ...

  6. Python之pandas:对dataframe数据的索引简介、应用大全(输出索引/重命名索引列/字段去重/设置复合索引/根据列名获取对应索引)、指定某字段为索引列等详细攻略

    Python之pandas:对dataframe数据的输出索引.重命名索引列/字段去重/设置复合索引/根据列名获取对应索引.指定某字段为索引列等详细攻略 目录 对pandas中dataframe数据中 ...

  7. pandas使用rename函数重命名dataframe中数据列的名称、从而创建一个包含重复列名称的dataframe数据集

    pandas使用rename函数重命名dataframe中数据列的名称.从而创建一个包含重复列名称的dataframe数据集 目录

  8. 批量重命名文件中的照片

    通过下列代码,可实现批量重命名文件中的照片 代码如下: import os import string main_path = './photo_new' picturelist = os.listd ...

  9. Java 对象转Json,@JSONField对象字段重命名和顺序问题

    一.引入maven依赖 <dependency><groupId>com.alibaba</groupId><artifactId>fastjson&l ...

  10. @hotmail.com 账户添加别名,重命名到@outlook.com 一系列问题,顺道附上个人解决方法

    @hotmail.com 账户添加别名,重命名到@outlook.com 一系列问题,顺道附上个人解决方法 参考文章: (1)@hotmail.com 账户添加别名,重命名到@outlook.com ...

最新文章

  1. 二叉树查找python_二叉搜索树的python实现
  2. AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager
  3. 成功解决Error: Cannot find module 'web3'
  4. agv matlab应用,简单介绍一下agv调度控制系统常见的软件应用
  5. [Socket网络编程]一个封锁操作被对 WSACancelBlockingCall 的调用中断。
  6. application/json 四种常见的 POST 提交数据方式
  7. ListView自适应实现表格
  8. VB制作OCX控件的步骤
  9. 最简洁的PHP把PHP生成HTML代码
  10. Android图片加载那些事(一)-实现加载手机中的所有图片
  11. 微信小程序 git代码管理使用的详细步骤
  12. Linux内核网络UDP数据包发送(四)——Linux netdevice 子系统
  13. (初学者)关于C语言中退格键(\b)的初步了解
  14. 软考中级之系统集成项目管理工程师备考
  15. 剑指offer面试题2:实现单例模式
  16. 显卡性能比较 GPU common sense
  17. 龙格库塔公式法解微分方程组初值问题实例
  18. 唐太宗管理之道:收人,收心,收天下
  19. 浅谈分页插件PageHelper
  20. x265编码格式的avi视频播放只有声音,图像不出来的一种解决方式

热门文章

  1. SQL server2008 安装教程
  2. 主流HTML5游戏框架的分析和对比(Construct2、ImpactJS、CreateJS、Cocos2d-html5……)
  3. 中南民族大学计算机组成原理实验,中南民族大学计算机组成原理试题及答案剖析.docx...
  4. 在线教学质量评价系统java web_基于JavaWeb的教师教学质量评价系统
  5. Android--关闭某个指定activity,android开发游戏
  6. 【论文笔记】Evolving Deep Neural Networks.
  7. 《Android框架揭秘》——2.2节搭建Android平台编译环境
  8. 混响运行于CPU或者DSP时的部分指标对比
  9. 开放源代码不得不知的一些事情
  10. Python实例练手项目源码 - 关不掉的窗口