You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity如何重写Inspector面板中Vector向量的默认属性绘制逻辑

核心结论

直接为内置Vector2/Vector3类型标记[CustomPropertyDrawer(typeof(Vector2))]的写法完全不会生效。Unity对引擎内置基础值类型(向量、数值、布尔、字符串等)的属性绘制走原生层内置逻辑,优先级远高于C#层注册的自定义PropertyDrawer,你写的绘制器根本不会被系统调用,重写多少方法都没用。
你不需要必须创建自定义向量类/结构体,两种方案都能实现向量字段旁加自定义按钮的需求:

方案1:自定义特性标记字段(最轻量,无需改原有字段类型)

不需要替换现有Vector类型,只需要给需要加按钮的字段打个自定义特性标签,就能实现自定义绘制:

  1. 先定义一个继承PropertyAttribute的特性类,作为需要自定义绘制的字段标记
  2. 为这个特性编写对应的PropertyDrawer,绘制逻辑里先渲染默认的向量输入框,再在旁边预留位置渲染自定义按钮
    示例代码:
// 放在任意非Editor文件夹下,作为字段标记
public class VectorWithButtonAttribute : PropertyAttribute
{
    public string ButtonText;
    public VectorWithButtonAttribute(string btnText = "重置")
    {
        ButtonText = btnText;
    }
}
// 放在Editor文件夹下
[CustomPropertyDrawer(typeof(VectorWithButtonAttribute))]
public class VectorWithButtonDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // 拆分绘制区域:输入框占大部分宽度,右侧留50像素放按钮
        Rect fieldRect = new Rect(position.x, position.y, position.width - 60, position.height);
        Rect btnRect = new Rect(position.x + position.width - 55, position.y, 50, position.height);
        
        // 仅对Vector2/Vector3类型生效
        if (property.propertyType is SerializedPropertyType.Vector2 or SerializedPropertyType.Vector3)
        {
            EditorGUI.PropertyField(fieldRect, property, label);
            if (GUI.Button(btnRect, (attribute as VectorWithButtonAttribute).ButtonText))
            {
                // 这里写按钮点击逻辑,示例是把向量置为零
                if (property.propertyType == SerializedPropertyType.Vector2)
                    property.vector2Value = Vector2.zero;
                else
                    property.vector3Value = Vector3.zero;
            }
        }
        else
        {
            // 非向量字段走默认绘制,避免报错
            EditorGUI.PropertyField(position, property, label);
        }
    }
}

使用时直接在字段上加特性即可,原有Vector类型完全不用改,业务层代码不需要做任何调整:

public class TestComponent : MonoBehaviour
{
    [VectorWithButton("归零")]
    public Vector2 moveDir;
    [VectorWithButton("归一")]
    public Vector3 spawnPos;
}

方案2:自定义值类型包装器(适合全局统一替换向量绘制)

如果你需要所有用到自定义向量的地方都统一显示按钮,不想一个个给字段加特性,可以写个和Vector隐式互通的自定义结构体,再给这个结构体写CustomPropertyDrawer即可,完全不会和Unity内置绘制逻辑冲突:

// 放在非Editor文件夹
[Serializable]
public struct CustomVec3
{
    public float x, y, z;
    // 支持和Vector3隐式互转,业务代码里可以直接当Vector3用
    public static implicit operator Vector3(CustomVec3 v) => new Vector3(v.x, v.y, v.z);
    public static implicit operator CustomVec3(Vector3 v) => new CustomVec3{x = v.x, y = v.y, z = v.z};
}

之后给CustomVec3写CustomPropertyDrawer就能完全自定义绘制效果,使用时把对应字段类型改成CustomVec3就行,业务代码里不需要做额外类型转换。

不要尝试通过反射修改Unity内置的绘制器映射表来覆盖默认Vector绘制,不同Unity版本内部实现差异极大,很容易导致编辑器崩溃、版本兼容问题。

内容的提问来源于stack exchange,提问作者siraxtas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 03:54:20