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

Unity中ScriptableObject内抽象类bool变量默认值失效如何解决

Unity任务系统条件判断模块问题解决方案

所有问题均和Unity序列化机制、ScriptableObject资产特性、引用类型赋值逻辑有关,和抽象类无关。

问题原因拆解

  1. 可序列化类初始值被忽略:Unity对标记[Serializable]的类实例执行序列化时,字段的C#代码初始值会被序列化文件中存储的历史值覆盖,代码声明时的默认赋值不会生效。如果conditionMet曾经被运行时修改为true并被序列化保存,后续加载时就会返回true。
  2. 运行时修改同步影响ScriptableObject:你在创建Quest实例时直接引用了ScriptableObject中存储的Condition实例,引用类型赋值传递的是内存地址,修改Quest中的Condition字段本质就是修改ScriptableObject资产中的原对象,Unity会自动持久化ScriptableObject的改动,导致运行时状态被保存。

解决方案

1. 禁止序列化运行时状态字段

给conditionMet添加[NonSerialized]特性,让Unity完全忽略该字段的序列化,代码中的初始值= false就会正常生效,同时该字段的改动不会被保存到ScriptableObject资产中。

2. 实例化Quest时深拷贝Condition配置

给Condition抽象类添加克隆方法,每个子类实现深拷贝逻辑,创建Quest实例时复制所有Condition的配置字段生成新实例,实现运行时实例和ScriptableObject配置的隔离,避免修改原资产。

修改后代码示例

public abstract class Condition
{
    [SerializeField] protected string parameter;
    public string Parameter => parameter;
    
    // 禁止序列化运行时状态,代码初始值生效
    [System.NonSerialized]
    protected bool conditionMet = false;
    public bool ConditionMet => conditionMet;

    public abstract void CheckCondition(string eventMessage);
    // 抽象克隆方法,用于深拷贝配置
    public abstract Condition Clone();
}

[System.Serializable]
public class IntCondition : Condition
{
    [SerializeField] private NumberComparisonType comparison;
    [SerializeField] private int expectedInt;
    
    public override void CheckCondition(string eventMessage)
    {
        int count = int.Parse(eventMessage.Split(':')[1]);
        conditionMet = comparison switch
        {
            NumberComparisonType.GreaterOrEqual => count >= expectedInt,
            NumberComparisonType.Less => count < expectedInt,
            _ => conditionMet
        };
    }

    public override Condition Clone()
    {
        return new IntCondition()
        {
            parameter = this.parameter,
            comparison = this.comparison,
            expectedInt = this.expectedInt
        };
    }
}

Quest实例化示例代码

public class Quest
{
    public List<Condition> RuntimeConditions { get; private set; }

    public Quest(QuestData questData)
    {
        // 深拷贝所有条件配置,和SO原资产隔离
        RuntimeConditions = questData.Conditions.Select(cond => cond.Clone()).ToList();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:51:01