[Unity 技巧] 如何自定义 Inspector 变量显示名称 (CustomLabel)

目录

[1. 概览](#1. 概览)

[2. 代码实现与详细注释](#2. 代码实现与详细注释)

[第一步:定义 Attribute](#第一步:定义 Attribute)

[第二步:实现 PropertyDrawer](#第二步:实现 PropertyDrawer)

第三步:实际应用测试 (Test.cs)

[3. 常见问题解析](#3. 常见问题解析)

[4. 实际效果​](#4. 实际效果)


在 Unity 开发中,为了保证代码规范,变量名通常使用英文**(如 playerHealth、isGameStarted)** 。但在 Inspector 面板中配置数值时,策划或美术人员可能更希望看到直观的中文标签**(如"玩家血量"、"游戏是否开始")。**

本文将介绍如何使用 Unity 的 PropertyAttributePropertyDrawer 功能,实现一个 **[CustomLabel]**特性,让我们既能保留规范的代码命名,又能拥有清晰的中文 Inspector 面板。

1. 概览

我们需要创建三个部分:

  1. Attribute(特性类): 用于在变量上打标签,存储我们需要显示的中文名称。

  2. Drawer(绘制类): 核心逻辑,告诉 Unity 编辑器当遇到这个标签时,该如何绘制界面。

  3. Usage(测试用例): 实际挂载使用的脚本。

2. 代码实现与详细注释

第一步:定义 Attribute

这个脚本定义了 [CustomLabel] 属性本身。它只负责存储数据(标签名称)。

文件名:CustomLabelAttribute.cs 存放位置:任意 Scripts 文件夹(不需要放在 Editor 文件夹)

可以参考我的目录

CustomLabelAttribute.cs 代码内容如下

cs 复制代码
using UnityEngine;

public class CustomLabelAttribute : PropertyAttribute
{
    public string label;

    public CustomLabelAttribute(string label)
    {
        this.label = label;
    }
}

第二步:实现 PropertyDrawer

这个脚本负责具体的绘制逻辑。通过反射机制,它能在 Inspector 渲染该属性时,截获并修改显示的 Label。

文件名:CustomLabelDrawer.cs 存放位置:必须放在 Editor 文件夹内

CustomLabelDrawer .cs 代码内容如下

cs 复制代码
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(CustomLabelAttribute))]
public class CustomLabelDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        CustomLabelAttribute customLabel = (CustomLabelAttribute)attribute;

        // --- 关键逻辑解析 ---
        // 检查当前属性的路径是否以 "]" 结尾。
        // 在 Unity 中,数组或 List 的元素路径通常是 "variableName.Array.data[0]" 这种格式。
        // 如果我们不加这个判断,当此 Attribute 应用于数组字段本身时,
        // Unity 可能会尝试将数组内部的 "Element 0", "Element 1" 也重命名为我们的 Label,
        // 导致所有元素都叫同一个名字,没法区分。
        // 加上这个判断,确保我们只修改字段本身的名称,而保留数组元素的索引名称。
        if (!property.propertyPath.EndsWith("]"))
        {
            label.text = customLabel.label;
        }

        // 标记属性绘制开始
        EditorGUI.BeginProperty(position, label, property);

        // 绘制属性字段
        // includeChildren: true 表示如果是结构体或类,会自动绘制其子字段
        EditorGUI.PropertyField(position, property, label, true);

        // 标记属性绘制结束
        EditorGUI.EndProperty();
    }

    // 重新计算属性高度
    // 这一步很重要,否则对于自定义类或数组,Inspector 可能会因为高度计算错误导致重叠
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return EditorGUI.GetPropertyHeight(property, label, true);
    }
}

第三步:实际应用测试 (Test.cs)

这里展示了在普通字段、自定义类内部字段、结构体、以及数组上的表现。

cs 复制代码
using UnityEngine;
using System.Collections.Generic;
using System;

[Serializable]
public class PlayerInfo
{
    [CustomLabel("血量")]
    public int health = 100;
    public int mana = 50;
    public string playerName = "Hero";
    public float speed = 5.0f;
}

public class Test : MonoBehaviour
{
    [CustomLabel("玩家信息")]
    public PlayerInfo player;

    public List<PlayerInfo> enemies;

    public PlayerInfo[] playerinfos;

    [CustomLabel("分数")]
    public int score;

    [CustomLabel("结构体")]
    public MyStruct myStruct;
}

[Serializable]
public struct MyStruct
{
    [CustomLabel("年龄")]
    public int age;
    [CustomLabel("性别")]
    public int sex;
    [CustomLabel("名字")]
    public string name;
    public string occupation;
}

3. 常见问题解析

为什么要判断 !property.propertyPath.EndsWith("]")

在 Unity 的序列化系统中:

1.普通变量路径:score

2.数组/列表变量本身路径:enemies、playerinfos

3.数组/列表内的元素路径:enemies.Array.data[0]、playerinfos.Array.data[0]

当你写下 **[CustomLabel("我的列表")] public int[] myList;**时:

1.Unity 绘制列表头,路径是 myList 。判断通过,名字变成**"我的列表"**。

2.如果不加那个判断,有些复杂的绘制情况下,Unity 可能会把 Attribute 的作用域延续到子元素上,导致你看到的列表变成了:

我的列表

我的列表 (本该是 Element 0)

我的列表 (本该是 Element 1)

3.加上 **EndsWith("]")**的判断,就显式地过滤掉了所有数组元素,保证了索引显示的正确性。

4. 实际效果

相关推荐
mxwin3 小时前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F4 小时前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身6 小时前
Lua脚本事件检查工具
unity·lua·工具
leo__5207 小时前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿9 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin9 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发9 小时前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安9 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
笑虾10 小时前
cocos2d-x lua 加载 Cocos Studio 导出的 csb
游戏引擎·lua·cocos2d
魔士于安10 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型