Unity如何通过自定义编辑器实现布尔值控制Inspector变量显隐
Unity Inspector变量条件显隐实现方案
需求说明
开发中需要实现如下效果:当布尔变量a为true时,变量b在Inspector面板显示;当a为false时,b在面板隐藏。
初始示例脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MyScript: MonoBehaviour { public bool a; int b; }
实现步骤
- 修改原运行时脚本
原脚本中b是私有变量,默认不会被Unity序列化,编辑器无法识别该字段,首先给b添加[SerializeField]特性保证可序列化:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MyScript : MonoBehaviour { public bool a; [SerializeField] private int b; }
- 编写自定义编辑器脚本
新建脚本放到项目任意名为Editor的文件夹下(Unity只会编译该文件夹下的脚本为编辑器代码,不会打进运行时安装包),代码如下:
using UnityEditor; using UnityEngine; [CustomEditor(typeof(MyScript))] public class MyScriptEditor : Editor { public override void OnInspectorGUI() { MyScript targetIns = (MyScript)target; // 绘制除b之外的所有默认序列化字段(包含public的a字段、顶部脚本引用栏) DrawInspectorExclude("b"); // 满足a为true的条件时,才绘制b字段 if (targetIns.a) { serializedObject.Update(); SerializedProperty bProp = serializedObject.FindProperty("b"); EditorGUILayout.PropertyField(bProp); serializedObject.ApplyModifiedProperties(); } } private void DrawInspectorExclude(params string[] excludeFieldNames) { serializedObject.Update(); SerializedProperty it = serializedObject.GetIterator(); bool enterChild = true; while (it.NextVisible(enterChild)) { enterChild = false; bool isExclude = false; foreach (string field in excludeFieldNames) { if (it.name == field) { isExclude = true; break; } } if (isExclude) continue; EditorGUILayout.PropertyField(it, true); } serializedObject.ApplyModifiedProperties(); } }
补充说明
- 写完脚本回到Unity等待编译完成,切换
a的勾选状态就能看到b字段的显隐效果 - 如果项目中存在大量条件显隐需求,不用为每个脚本单独编写Editor,可以封装自定义特性
ConditionalShowAttribute配合PropertyDrawer实现通用逻辑,减少重复代码
内容的提问来源于stack exchange,提问作者Ian Wai Si
相关产品推荐
相关产品推荐

