如何解决Unity 编辑器脚本:如何使用同一个按钮执行两个不同的操作?
我编写了一些代码来向 Unity 中的自定义编辑器添加一个按钮。我想要的是以下内容。当我单击该按钮一次时,会添加一个组件,当我再次单击时,该组件将被删除。在下面的简单代码中,我只是尝试在单击按钮时打印“添加”或“删除”。我注意到变量toggleRigidBody 取值为true,然后立即取值为false。即使我从未在代码中明确更改它,它也不会保持“真实”。 “否则如果”永远不会被解雇。我不知道为什么。
using UnityEditor;
using UnityEngine;
using SS3D.Engine.Inventory;
[CustomEditor(typeof(ContainerController))]
public class ContainerControllerEditor : Editor
{
private bool toggleRigidBody = false;
public override void OnInspectorGUI()
{
DrawDefaultInspector();
ContainerController containerController = (ContainerController)target;
Debug.Log(toggleRigidBody);
bool buttonpressed = GUILayout.Button("AddAttachedContainer");
if (buttonpressed && toggleRigidBody == false)
{
Debug.Log("Add");
toggleRigidBody = true;
}
else if (buttonpressed && toggleRigidBody == true)
{
Debug.Log("Remove");
toggleRigidBody = false;
}
}
}
解决方法
这里的主要问题是编辑器实例是在单击对象并加载 Inspector 时创建的。然后一旦对象失去焦点并且不再为该对象显示检查器,它就会被销毁。
=> 您的标志 toggleRigidBody
不持久!
您更愿意做的是序列化对象内的标志,或者更好:序列化引用本身。
这样你
- 已经可以访问脚本中的引用,以防您在运行时需要它
- 在编辑器中有引用,用于 a) 检查它是否存在和 b) 能够直接删除它
所以你的班级很喜欢
public class ContainerController : MonoBehaviour
{
// Store the reference in a field
[SerializeField] private Rigidbody _rigidbody;
...
}
编辑器看起来像
[CustomEditor(typeof(ContainerController))]
public class ContainerControllerEditor : Editor
{
private SerializedProperty _rigidbody;
ContainerController containerController;
private void OnEnable()
{
_rigidbody = serializedObject.FindProperty("_rigidbody");
containerController = (ContainerController)target;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
// Loads all current serialized values from the target into the serialized properties
serializedObject.Update();
// If the _rigidbody field is not assigned
// try GetComponent as fallback
if(!_rigidbody.objectReferenceValue) _rigidbody.objectReferenceValue = containerController.GetComponent<Rigidbody>();
// simply put everything that belongs to one button click inside one if block
// this is easier to maintain and read
// Of course alternatively you could also simply have two completely different buttons to display
// depending on the value of "_rigidbody.objectReferenceValue"
if(GUILayout.Button(_rigidbody.objectReferenceValue ? "Remove Rigidbody" : "Add Rigidbody")
{
// Is there a Rigidbody?
if(_rigidbody.objectReferenceValue)
{
// Yes -> destroy it
// There are two different destroy methods depending whether you are
// in Play mode or Edit mode
if(Application.isPlaying)
{
Destroy(_rigidbody.objectReferenceValue);
}
else
{
DestroyImmediate(_rigidbody.objectReferenceValue);
}
}
// Otherwise the field is currently not set and no component was found using GetComponent
else
{
// Add the component via the ObjectFactory
// this enabled undo/redo and marks the scene dirty etc
// and assign it to the serialized property
_rigidbody.objectReferenceValue = ObjectFactory.AddComponent<Rigidbody>(target.gameObject);
}
}
// Writes back all modified properties to the target and takes care of Undo/Redo and marking dirty
serializedObject.ApplyModifiedProperties ();
}
}
,
编辑器对象在显示时创建,不显示时销毁,因此要持久保存数据,您需要将值存储在其他地方。所以这绝对是正在发生的事情。在会话之间保持变量值的最简单方法是使用 EditorPrefs
来保存变量值。这是最简单的方法,因此您可以使用它来保存 toggleRigidBody
值。
https://docs.unity3d.com/ScriptReference/EditorPrefs.SetBool.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。