为何无法在Mono脚本中访问PropertyDrawer创建的GapRangeDrawer属性?
解决Unity自定义Range属性无法访问的问题
问题根源
你混淆了**自定义特性(Attribute)和属性抽屉(PropertyDrawer)**的作用:GapRangeDrawer是负责绘制Inspector UI的抽屉类,不能直接作为特性标注在字段上,必须先定义一个对应的自定义特性,再让抽屉类关联这个特性。
修复步骤
1. 创建自定义特性类
在Assets根目录下(不要放在Editor文件夹)新建脚本GapRangeAttribute.cs,代码如下:
using UnityEngine; public class GapRangeAttribute : PropertyAttribute { public float MinRange { get; private set; } public float MaxRange { get; private set; } public float Sensitivity { get; private set; } public GapRangeAttribute(float minRange, float maxRange, float sensitivity = 0.1f) { MinRange = minRange; MaxRange = maxRange; Sensitivity = sensitivity; } }
2. 修改属性抽屉类
更新Assets/Editor/GapRangeDrawer.cs的代码,让它关联上面的特性,并从特性中获取参数:
using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(GapRangeAttribute))] // 关联自定义特性 public class GapRangeDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // 获取关联的特性参数 var gapRangeAttribute = attribute as GapRangeAttribute; if (property.propertyType == SerializedPropertyType.Float) { EditorGUI.BeginProperty(position, label, property); EditorGUI.Slider(position, property, gapRangeAttribute.MinRange, gapRangeAttribute.MaxRange, label); property.floatValue = RoundValue(property.floatValue, gapRangeAttribute.Sensitivity); EditorGUI.EndProperty(); } else { EditorGUI.LabelField(position, label.text, "Use [GapRange] with float values only!"); } } private float RoundValue(float value, float sensitivity) { return Mathf.Round(value / sensitivity) * sensitivity; } }
注意:移除了原来的构造函数,因为PropertyDrawer的参数是通过关联的Attribute传递的,不需要自定义构造。
3. 在Mono脚本中正确使用
现在可以在CubeSpawner里正常使用自定义特性了:
public class CubeSpawner : MonoBehaviour { public GameObject cubePrefab; [GapRange(0f, 10f, 0.5f)] // 最小值0,最大值10,步长0.5 public float spawnGap; }
额外说明
- 自定义特性类必须放在非Editor目录,这样运行时和编辑时的脚本都能访问到。
- PropertyDrawer类必须放在
Assets/Editor目录下,Unity会自动识别并应用它的绘制逻辑。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

