Unity的PropertyDrawer和PropertyAttribute

本文详细介绍Unity中自定义编辑器的两种方式:PropertyDrawer和PropertyAttributeInspector。PropertyDrawer适用于统一修改特定类型属性的显示,示例展示了如何为所有字符串属性添加文件选择按钮。PropertyAttribute结合PropertyAttribute,用于修改特定类的指定类型属性显示,如为int或float属性添加自定义滑动条。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Inspector面板的显示编辑的两种方式

PropertyDrawer

介绍

PropertyDrawer官方文档
修改某种特定类型的显示,使用继承Editor的方式就会变得很麻烦,因为所有使用特定类型的asset都需要去实现一个自定义的Editor,效率非常低。这种情况就可以通过继承PropertyDrawer的方式,对指定类型的属性,进行统一显示。

示例代码
[CustomPropertyDrawer(typeof(string))]
public class StringPropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        Rect btnRect = new Rect(position);
        position.width -= 60;
        btnRect.x += btnRect.width - 60;
        btnRect.width = 60;
        EditorGUI.BeginProperty(position, label, property);
        EditorGUI.PropertyField(position, property, true);
        if (GUI.Button(btnRect, "select"))
        {
            string path = property.stringValue;
            string selectStr = EditorUtility.OpenFilePanel("选择文件", path, "");
            if (!string.IsNullOrEmpty(selectStr))
            {
                property.stringValue = selectStr;
            }
        }
        EditorGUI.EndProperty();
    }
}
效果

为Inspector面板中的所有string属性添加一个选择文件按钮,选中文件的路径直接赋值给该变量。

注意事项
  1. PropertyDrawer只对可序列化的类有效,非可序列化的类没法在Inspector面板中显示。
  2. OnGUI方法里只能使用GUI相关方法,不能使用Layout相关方法。
  3. PropertyDrawer对应类型的所有属性的显示方式都会修改,例如创建一个带string属性的MonoBehaviour。

PropertyAttribute

介绍

PropertyAttribute官方文档
想要修改部分类的指定类型的属性的显示,直接使用PropertyDrawer就无法满足条件,这时可以结合PropertyAttribute和PropertyAttribute来实现需求。

示例代码
public class RangeAttribute : PropertyAttribute
{
    public float min;
    public float max;

    public RangeAttribute(float min, float max)
    {
        this.min = min;
        this.max = max;
    }
}

[CustomPropertyDrawer(typeof(RangeAttribute))]
public class RangeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        RangeAttribute range = attribute as RangeAttribute;
        if (property.propertyType == SerializedPropertyType.Float)
            EditorGUI.Slider(position, property, range.min, range.max, label);
        else if (property.propertyType == SerializedPropertyType.Integer)
            EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max, label);
        else
            EditorGUI.LabelField(position, label.text, "Use Range with float or int.");
    }
}
效果

为部分指定类的int或float属性的显示添加滑动条,滑动条的上下限可根据类和属性自行设置。

原文链接

https://blog.csdn.net/wuwangxinan/article/details/72773297

### 如何在Unity中创建或自定义Tooltip #### 使用UGUI实现简单的Tooltip效果 为了实现在Unity中的简单Tooltip功能,可以利用Unity的UI系统(UGUI)。通过脚本控制来显示隐藏带有提示信息的游戏对象。 ```csharp using UnityEngine; using UnityEngine.UI; public class SimpleTooltip : MonoBehaviour { public GameObject tooltipPanel; // 绑定一个Canvas下的空物体作为tooltip容器 private RectTransform canvasRectTransform; void Start() { canvasRectTransform = Canvas.main.GetComponent<RectTransform>(); HideTooltip(); } public void ShowTooltip(string message) { tooltipPanel.SetActive(true); tooltipPanel.transform.GetChild(0).GetComponent<Text>().text = message; UpdateTooltipPosition(Input.mousePosition); // 显示时立即更新位置 Vector2 localMousePos; RectTransformUtility.ScreenPointToLocalPointInRectangle( canvasRectTransform, Input.mousePosition, null, out localMousePos); tooltipPanel.transform.localPosition = new Vector3(localMousePos.x + 15f, localMousePos.y - 15f, 0f); } public void HideTooltip() { tooltipPanel.SetActive(false); } } ``` 此代码片段展示了如何基于鼠标指针的位置动态调整`tooltipPanel`的位置[^1]。当调用`ShowTooltip()`方法并传入想要展示的消息字符串参数时,会激活绑定好的面板,并设置其子Text组件的内容为指定消息;而`HideTooltip()`用于关闭该提示框。 #### 自定义Inspector属性绘制以支持Tooltip特性 对于编辑器端更复杂的场景下,可以通过继承`PropertyDrawer`来自定义字段上的工具提示行为: ```csharp using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(MyAttribute))] public class MyAttributeDrawer : PropertyDrawer { public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return base.GetPropertyHeight(property, label); } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { var myAttr = (MyAttribute)this.attribute; if (!string.IsNullOrEmpty(myAttr.tooltip)) { TooltipHelper.Add(position, myAttr.tooltip); } EditorGUI.PropertyField(position, property, true); } } // Helper Class for adding tooltips in editor static class TooltipHelper { static readonly Dictionary<int, string> _tooltips = new Dictionary<int, string>(); internal static void Add(Rect rect, string text) { int id = GUIUtility.GetControlID(FocusType.Passive); _tooltips[id] = text; Event e = Event.current; switch (e.type) { case EventType.Repaint: HandleRepaint(rect, id); break; case EventType.MouseMove: HandleMouseMove(id); break; } } static void HandleRepaint(Rect rect, int controlId) { Handles.BeginGUI(); GUIStyle style = "window"; foreach (var pair in _tooltips.Where(p => p.Key == controlId)) { GUIContent content = new GUIContent(pair.Value); Vector2 size = style.CalcSize(content); Rect r = new Rect(Event.current.mousePosition.x + 8, Screen.height - Event.current.mousePosition.y - 8 - size.y, size.x, size.y); GUI.Label(r, content, style); } Handles.EndGUI(); } static void HandleMouseMove(int currentId) { if (_tooltips.ContainsKey(currentId)) { RepaintAll(); } } static void RepaintAll() { EditorWindow.focusedWindow?.Repaint(); } } ``` 上述代码实现了对特定属性添加自定义的Editor窗口内悬浮提示功能[^3]。这里的关键在于使用了静态字典存储临时性的提示文字映射关系,在每次重绘(`Repaint`)期间检查当前是否有匹配项存在,则会在屏幕相应坐标处渲染对应的文本标签。 #### 配合Dialogue System处理带Tooltip的对话界面 如果项目中有集成类似的对话管理系统,那么还需要特别注意确保所有涉及交互控件都已正确定位并且能够响应用户的输入操作。这通常涉及到验证对话系统的布局设定以及各个元素之间的相对尺寸配置等问题[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值