unity3d - unity 条件字段自定义编辑器
问题描述
我的目标:我有一个脚本
public class MyScript: MonoBehaviour
{
public bool A;
public bool B;
}
仅当 A 为 TRUE 时,我才需要 B 可见
我对脚本进行了扩展并在标题中添加了 UnityEditor
[CustomEditor(typeof(MyScript))]
public class MyEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
MyScript tool = (MyScript) target;
tool.A = GUILayout.Toggle(tool.A, "Flag");
if(tool.A)
{
tool.B= EditorGUILayout.Toggle(tool.B, "Flag");
}
}
}
但没有什么真正改变。我做错了什么?
解决方案
首先你的类定义是错误的。如果它应该附加到游戏对象,您需要[Serializable]
或者该类应该继承自。MonoBehaviour
无论哪种方式删除()
[Serializable]
public class MyScript
{
public bool A;
public bool B;
}
或者
public class MyScript : MonoBehaviour
{
public bool A;
public bool B;
}
然后请注意, aCustom Editor
仅适用于从 aMonoBehaviour
或 a继承的类ScriptableObject
。在其他情况下,您将不得不实现CustomPropertyDrawer
。
您应该始终尽量不要直接在target
. 您将不得不自己处理很多事情,例如标记为脏,撤消/重做等......
而是总是通过SerializedProperty
s。
另请注意,base.OnInspectorGUI();
将绘制默认检查器
所以假设MyScript
是一个MonoBehaviour
类
[CustomEditor(typeof(MyScript))]
public class MyEditor : Editor
{
SerializedProperty a;
SerializedProperty b;
// is called once when according object gains focus in the hierachy
private void OnEnable()
{
// link serialized properties to the target's fields
// more efficient doing this only once
a = serializedObject.FindProperty("A");
b = serializedObject.FindProperty("B");
}
public override void OnInspectorGUI()
{
// fetch current values from the real instance into the serialized "clone"
serializedObject.Update();
// Draw field for A
EditorGUILayout.PropertyField(a);
if(a.boolValue)
{
// Draw field for B
EditorGUILayout.PropertyField(b);
}
// write back serialized values to the real instance
// automatically handles all marking dirty and undo/redo
serializedObject.ApplyModifiedProperties();
}
}
或者 ifMyScript
实际上不是 a MonoBehaviour
then asPropertyDrawer
它的工作原理基本上非常相似,除非您必须使用EditorGUI
始终需要位置Rect
作为参数的字段版本:
[CustomPropertyDrawer(typeof(MyScript), true)]
public class MyEditor : PropertyDrawer
{
private bool isUnFolded;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// draw folder for the entire class
isUnFolded = EditorGUI.Foldout(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), isUnFolded, label);
// go to the next line
position.y += EditorGUIUtility.singleLineHeight;
// only draw the rest if unfolded
if (isUnFolded)
{
// draw fields indented
EditorGUI.indentLevel++;
// similar to before get the according serialized properties for the fields
var a = property.FindPropertyRelative("A");
var b = property.FindPropertyRelative("B");
// Draw A field
EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), a);
position.y += EditorGUIUtility.singleLineHeight;
if (a.boolValue)
{
// Draw B field
EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), b);
}
// reset indentation
EditorGUI.indentLevel--;
}
}
// IMPORTANT you have to implement this since your new property is
// higher then 1 single line
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
// default is 1 single line
var height = 1;
// if unfolded at least 1 line more, if a is true 2 lines more
if(isUnFolded) height += (property.FindPropertyRelative("A").boolValue ? 2 : 1);
return height * EditorGUIUtility.singleLineHeight;
}
}
推荐阅读
- webpack - Webpack 开发服务器在热时重新编译,但捆绑包实际上并没有改变
- python - 我不知道为什么更改列表别名时原始列表会更改
- c++ - union int bits to float bits 有时解释错误
- javascript - 如何设置关闭菜单的事件监听器
- python - 如何在 Python 中使用 SOAP API(XML 格式)?
- c# - 如何从该项目引用的程序集中获取项目中引用的所有程序集?
- android - 未处理的异常:System.NullReferenceException:
发生了 - c++ - 如何使用 std::variant 保证复制省略?
- javascript - android移动浏览器中的html输入框打开并快速关闭触摸键盘
- css - 如何使用css均匀地布局多个动态出现的按钮?