You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Unity中修改Inspector面板布尔值时如何触发属性Set方法

问题原因

  • Unity 序列化系统仅对字段做序列化处理,你在 Inspector 面板看到的复选框对应的是标记了[SerializeField]的私有字段aBool,而非自定义的ABool属性。直接修改 Inspector 中的值是直接修改底层字段,不会触发属性的set逻辑,属于 Unity 正常行为,你的属性定义本身没有语法错误,只是没有和 Inspector 修改行为做绑定。
  • 另外你当前的属性set逻辑是先判断旧字段值与新值的差异再更新字段,如果你直接将修改后的字段值传入属性,会因为字段已经是最新值,导致差异判断无法触发。

解决方法

方法1:配合缓存旧值使用OnValidate回调(全版本通用,无需自定义编辑器)

OnValidate是 Unity 内置生命周期方法,Inspector 中的序列化字段被修改时会自动触发,我们额外缓存一个旧值做差异判断即可触发正确的set逻辑:

public class SomeClass : MonoBehaviour
{
    [SerializeField]
    private bool aBool;
    // 缓存字段旧值
    private bool _oldABool;

    public bool ABool 
    {
        get 
        {
            return aBool;
        }
        set 
        {
            // 值无变化直接退出
            if (aBool == value) return;

            Debug.Log("we are setting the bool!");
            
            // 从false改为true时触发
            if (aBool == false && value == true) 
            {
                // do stuff
            }

            // 从true改为false时触发
            if (aBool == true && value == false)
            {
                // do stuff
            }

            aBool = value;
            // 更新缓存旧值
            _oldABool = value;
        } 
    }

    private void Awake()
    {
        // 初始化缓存旧值
        _oldABool = aBool;
    }

    private void OnValidate()
    {
        // 可选:仅运行模式下触发逻辑可以加这句判断
        // if (!Application.isPlaying) return;
        
        // 字段值与缓存旧值不同,说明是Inspector修改触发
        if (aBool != _oldABool)
        {
            // 先把字段还原为旧值,再赋值给属性触发正确的差异判断
            var newValue = aBool;
            aBool = _oldABool;
            ABool = newValue;
        }
    }

    // 其余业务代码省略
}

方法2:自定义Inspector(逻辑最直观,无版本限制)

将私有序列化字段标记为[HideInInspector]隐藏Inspector显示,再通过自定义编辑器直接操作ABool属性,修改时自动触发set逻辑:
首先是主类代码:

public class SomeClass : MonoBehaviour
{
    // 隐藏原字段的Inspector显示
    [HideInInspector]
    [SerializeField]
    private bool aBool;

    public bool ABool 
    {
        get 
        {
            return aBool;
        }
        set 
        {
            if (aBool == value) return;

            Debug.Log("we are setting the bool!");
            
            if (aBool == false && value == true) 
            {
                // do stuff
            }

            if (aBool == true && value == false)
            {
                // do stuff
            }

            aBool = value;
        } 
    }

    // 其余业务代码省略
}

然后在Editor文件夹下新建编辑器脚本:

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(SomeClass))]
public class SomeClassEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var someClass = (SomeClass)target;

        // 绘制ABool属性的复选框
        bool newABool = EditorGUILayout.Toggle("ABool", someClass.ABool);
        if (newABool != someClass.ABool)
        {
            // 记录撤销操作
            Undo.RecordObject(someClass, "Change ABool");
            // 直接赋值给属性触发set逻辑
            someClass.ABool = newABool;
            // 标记对象为已修改
            EditorUtility.SetDirty(someClass);
        }
    }
}

这种写法逻辑最直观,不需要额外缓存旧值,不管是代码赋值还是Inspector修改都会触发set逻辑。

内容的提问来源于stack exchange,提问作者MoreFoam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:36:10