Unity Scriptable Object运行时赋值未更新问题求助
问题描述
我用Scriptable Object作为单位数据库,每个单位通过UnitStats脚本的Start()方法加载数据库中的属性。此前运行正常,但今日修改Scriptable Object中的变量(如将maxHP从100改为110)后,UnitStats加载的数值仍为旧值。尝试过保存项目、提交Unity版本控制、重启Unity,Scriptable Object内的maxHP显示为110,但UnitStats加载的数值依旧是100。
附UnitStats脚本:
using System.Collections.Generic; using UnityEngine; public class UnitStats : MonoBehaviour { [HideInInspector] public string unitName; [HideInInspector] public float attackRange; [HideInInspector] public float movementSpeed; [HideInInspector] public int maxHP; [HideInInspector] public int currentHP; [HideInInspector] public string type; [HideInInspector] public float attackInterval; [HideInInspector] public int priority; [HideInInspector] public int dpa; //[HideInInspector] public int searchRange; [SerializeField] UnitDatabaseSO unitDatabase; [SerializeField] int ID; public Dictionary<GameObject, int> abilities; private UnitData unitData; [HideInInspector] public bool loaded; [HideInInspector] public float damageTime; [HideInInspector] public bool ranged; [HideInInspector] public float buildTime; [HideInInspector] public Sprite spriteIcon; [HideInInspector] public int visionRange; [HideInInspector] public int bloodDrop; [HideInInspector] public int bloodCost; [HideInInspector] public string description; [HideInInspector] public bool isWorker; [HideInInspector] public int MaxBloodPool; [HideInInspector] public int bloodAmount; [HideInInspector] public float height; void Start(){ if(!loaded){ unitData = unitDatabase.objectsData[ID]; unitName = unitData.Name; attackRange = unitData.AttackRange; movementSpeed = unitData.MovementSpeed; maxHP = unitData.maxHP; currentHP = maxHP; type = unitData.Type; attackInterval = unitData.AttackInerval; priority = unitData.Priority; dpa = unitData.DPH; searchRange = unitData.SearchRange; damageTime = unitData.DamageTime; ranged = unitData.ranged; spriteIcon = unitData.SpriteIcon; buildTime = unitData.buildTime; visionRange = unitData.VisionRange; bloodDrop = unitData.BloodDrop; bloodCost = unitData.BloodCost; description = unitData.Description; isWorker = unitData.IsWorker; MaxBloodPool = unitData.MaxBloodPool; bloodAmount = 0; height = unitData.height; loaded = true; } HPBarManager.instance.CreateHPBar(transform, currentHP/maxHP); } public void AssignID(int ID){ this.ID = ID; } public void ReceiveDmg(GameObject source, int damage){ currentHP -= damage; if(currentHP <= 0){ GetComponent<UnitStateMachine>().TransitState(UnitStateMachine.Unitstate.Dead); return; } HPBarManager.instance.UpdateHPBar(transform, currentHP/maxHP); } public void GainHP(int heal){ if(currentHP + heal >= maxHP){ currentHP = maxHP; }else{ currentHP += heal; } HPBarManager.instance.UpdateHPBar(transform, currentHP/maxHP); } public bool IsDead(){ return currentHP <= 0; } public int GetID(){ return ID; } }
解决方法
重置
loaded标志位:脚本里的loaded变量默认未初始化,可能在场景运行后被保留为true,导致后续无法重新加载数据。可以在OnEnable()方法里强制重置loaded为false,或者直接给变量初始值[HideInInspector] public bool loaded = false;。修改后的加载逻辑示例:void OnEnable() { loaded = false; } void Start(){ LoadUnitData(); // 转成float做除法,避免整数相除得到0或1的错误结果 HPBarManager.instance.CreateHPBar(transform, (float)currentHP/maxHP); } private void LoadUnitData() { if(!loaded && unitDatabase != null && ID >= 0 && ID < unitDatabase.objectsData.Count) { unitData = unitDatabase.objectsData[ID]; // 所有赋值逻辑保持不变 loaded = true; } }验证Scriptable Object引用:检查场景中每个挂载
UnitStats组件的对象,确认绑定的unitDatabase是你修改的那个SO文件,避免误绑定旧副本或其他SO。清理Unity缓存:
- 点击顶部菜单
Assets -> Refresh刷新所有资源 - 关闭Unity后,删除项目根目录下的
Library文件夹,重启Unity会自动重新生成缓存文件
- 点击顶部菜单
规范修改流程:不要在Play模式下修改Scriptable Object的数据,确保在Edit模式下修改并保存SO,再进入Play模式测试,避免数据未正确写入磁盘。
检查
UnitData序列化:确认UnitData类中的maxHP等字段是可序列化的——要么是public字段,要么加了[SerializeField]属性,且没有被[NonSerialized]标记,否则SO中的修改无法被正确读取。
内容的提问来源于stack exchange,提问作者TazDingo

