用PropertyDrawer自定义Inspector面板显示外观

本文介绍如何使用PropertyDrawer来自定义Unity的Inspector面板,通过实例展示如何将数组以二维矩阵形式显示,涉及属性绘制器的实现原理及高度计算。

用PropertyDrawer自定义Inspector面板显示外观

2019年02月13日 11:53:25 萧_然 阅读数:22更多

个人分类: 工具

版权声明:欢迎大家留言讨论共同进步,转载请注明出处 https://blog.youkuaiyun.com/qq_39108767/article/details/87170224

举栗如图,将数组以二维矩阵的方式显示到Inspector面板

 
  1. using UnityEngine;

  2. using UnityEditor;

  3.  
  4. [System.Serializable]

  5. public class InspectorGrid

  6. {

  7. public int rows;

  8. public int columns;

  9.  
  10. [SerializeField]

  11. bool[] enabledBools;

  12. }

  13.  
  14. // ------

  15.  
  16. //用PropertyDrawer自定义Inspector面板显示外观

  17. [CustomPropertyDrawer(typeof(InspectorGrid))]

  18. public class InspectorGridDrawer : PropertyDrawer

  19. {

  20. float gridWidth = 15f;

  21. float gridHeight = 15f;

  22. float gridSpace = 1f;

  23.  
  24. int rows;

  25. int columns;

  26.  
  27. //自定义面板显示

  28. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)

  29. {

  30. //position: 在Inspector面板的位置、大小

  31. //property: 待绘制的属性

  32. //label: 值的字段名

  33.  
  34. //绘制一个SerializedProperty的属性字段

  35. EditorGUI.PropertyField(position, property, label, true);

  36.  
  37. //获取属性信息

  38. SerializedProperty data = property.FindPropertyRelative("enabledBools");

  39. rows = property.FindPropertyRelative("rows").intValue;

  40. columns = property.FindPropertyRelative("columns").intValue;

  41.  
  42. if (rows < 0)

  43. rows = 0;

  44.  
  45. if (columns < 0)

  46. columns = 0;

  47.  
  48. //指定数组大小

  49. data.arraySize = rows * columns;

  50.  
  51. //自定义显示区域

  52. if (property.isExpanded)

  53. {

  54. int count = 0;

  55. float targetX;

  56. float targetY;

  57.  
  58. //遍历

  59. for (int r = 0; r < rows; r++)

  60. {

  61. for (int c = 0; c < columns; c++)

  62. {

  63. //计算位置

  64. targetX = position.xMin + ((gridWidth + gridSpace) * (c + 1));

  65. targetY = 60 + position.yMin + (gridHeight + gridSpace) * (r + 1);

  66. //位置、大小

  67. Rect rect = new Rect(targetX, targetY, 15f * (EditorGUI.indentLevel + 1), gridHeight);

  68. //绘制属性值

  69. EditorGUI.PropertyField(rect, data.GetArrayElementAtIndex(count), GUIContent.none);

  70.  
  71. count++;

  72. }

  73. }

  74. }

  75. }

  76.  
  77. //自定义高度

  78. public override float GetPropertyHeight(SerializedProperty property, GUIContent label)

  79. {

  80. //按照行数增加高度

  81. if (property.isExpanded)

  82. return EditorGUI.GetPropertyHeight(property) + 20 + (15 * (rows + 1));

  83.  
  84. return EditorGUI.GetPropertyHeight(property);

  85. }

  86.  
  87. }

// 测试,Inspector面板显示如上图

 
  1. using UnityEngine;

  2.  
  3. public class Test : MonoBehaviour

  4. {

  5. [SerializeField] InspectorGrid grid;

  6.  
  7. }

 

<think>好的,用户的问题是关于在Unity编辑器中如何让参数在Inspector面板显示但不可编辑,也就是让参数呈现灰色且无法修改。我需要回忆一下Unity的相关知识,并参考提供的引用内容来给出正确的解决方案。 首先,根据引用[1]提到的,打开Inspector的Debug视图可以显示私有变量,但它们是灰色的且不可编辑。但用户可能不希望开启Debug模式,而是希望在普通视图中实现类似效果。所以可能需要使用其他方法。 然后,我记得Unity中有几种属性可以用来控制Inspector中的显示。比如,SerializeField属性可以将私有变量显示Inspector中,但这样默认是可编辑的。要让其不可编辑,可能需要结合只读属性或者使用自定义属性。 另外,引用[2]提到在Inspector中修改对象名称会同步到Hierarchy窗口,但这里的问题是关于参数不可编辑,可能需要使用[ReadOnly]这样的自定义属性。不过Unity本身并没有内置的[ReadOnly]属性,但可以通过自定义PropertyAttribute来实现。 然后,我需要考虑如何实现这个自定义属性。通常的做法是创建一个继承自PropertyAttribute的类,然后创建一个对应的PropertyDrawer来重写绘制方式,将GUI设置为不可编辑。例如,在OnGUI方法中设置GUI.enabled = false,绘制后再恢复为true。 此外,还可以使用[SerializeField]配合[HideInInspector]或者其他属性,但关键是如何保持变量可见但不可编辑。可能还需要考虑是否在编辑模式下需要保持值不变,或者在运行时不可编辑等情况。 总结可能的步骤: 1. 使用SerializeField将私有变量显示Inspector。 2. 创建自定义的ReadOnly属性。 3. 实现对应的PropertyDrawer来禁用GUI编辑。 然后,检查是否有其他方法,比如使用[ReadOnly]属性,或者通过Editor脚本来实现,但用户可能需要的是不需要自定义编辑器脚本的简便方法。 另外,可能需要提醒用户,如果使用Debug视图,变量会灰色显示但无法更改,但用户可能希望不开启Debug模式,所以还是推荐自定义属性的方法。 最后,确保提供的代码示例正确,并且步骤清晰,用户能够按照指导操作。</think>### 在Unity中实现Inspector面板参数显示但不可编辑的方法 #### 方法一:使用`[SerializeField]`结合`[ReadOnly]`属性(需自定义) 1. **添加字段序列化** 使用`[SerializeField]`特性将私有变量显示Inspector面板: ```csharp [SerializeField] private int readOnlyValue; ``` 2. **创建自定义只读属性** 新建`ReadOnlyAttribute.cs`脚本: ```csharp using UnityEngine; public class ReadOnlyAttribute : PropertyAttribute { } ``` 3. **实现属性绘制器** 新建`ReadOnlyDrawer.cs`脚本: ```csharp #if UNITY_EDITOR using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(ReadOnlyAttribute))] public class ReadOnlyDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { GUI.enabled = false; // 禁用GUI编辑 EditorGUI.PropertyField(position, property, label, true); GUI.enabled = true; // 恢复GUI状态 } } #endif ``` 4. **应用效果** 最终在Inspector中变量会显示为灰色不可编辑状态: ```csharp [SerializeField, ReadOnly] private int readOnlyValue; ``` #### 方法二:使用`Debug`模式(原生支持) 1. **开启Debug视图** 在Inspector窗口右上角点击**⋮**图标,选择**Debug**模式[^1]。 2. **查看效果** 所有私有变量会以灰色显示且不可编辑,但此方法会同时显示所有隐藏变量。 #### 两种方法对比 | 方法 | 优点 | 缺点 | |------------|--------------------------|------------------------------| | 自定义属性 | 精准控制指定变量 | 需要编写额外代码 | | Debug模式 | 无需编码,一键启用 | 会暴露所有私有变量,信息过载 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值