微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Unity 编辑器脚本:如何使用同一个按钮执行两个不同的操作?

如何解决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 举报,一经查实,本站将立刻删除。