Unity真机TextAsset写入异常及初始化报错解决方案咨询
Unity商店系统真机修改解锁次数失效及报错解决方案
问题概述
- 开发商店系统,用户观看广告后需修改对应球体的解锁次数(例:观看3个视频解锁球体)
- Unity编辑器内修改TextAsset正常,但真机中解锁次数未递减
- 报错信息:
不要在构造函数或字段初始化器中使用此函数,请将初始化代码移至Awake或Start函数,报错行:BallItems ballItems = JsonUtility.FromJson<BallItems>(textAsset.text);
问题代码
public override void DecrementGameItemCount(BallItem selectedBallItem,int decrementCount) { BallItems ballItems = JsonUtility.FromJson<BallItems>(textAsset.text); List<BallItem> ballItemList = new List<BallItem>(); ballItemList.AddRange(ballItems.ballItems); BallItem ballItemFromJson = ballItemList.Find((item) => item.name == selectedBallItem.name); int index = Array.IndexOf(ballItems.ballItems, ballItemFromJson); selectedBallItem.count--; if(selectedBallItem.count==0){ selectedBallItem.isPurchased = true; } string updatedBallItemToJson = JsonUtility.ToJson(selectedBallItem); JsonUtility.FromJsonOverwrite(updatedBallItemToJson, ballItems.ballItems[index]); string path = Application.dataPath + "/Resources/Files/ball_list.json"; FileStream fileStream = new FileStream(path, FileMode.Create); using (StreamWriter writer = new StreamWriter(fileStream)) { writer.Write(JsonUtility.ToJson(ballItems)); } }
解决方案
1. 修复TextAsset加载时机错误
报错核心原因是textAsset的加载逻辑放在了构造函数或字段初始化阶段,Unity禁止在此阶段调用资源加载方法。需将加载逻辑移至Awake或Start:
private TextAsset textAsset; void Awake() { // 从Resources目录加载初始配置文件 textAsset = Resources.Load<TextAsset>("Files/ball_list"); }
2. 修正真机文件写入路径
Application.dataPath在真机上是只读目录,无法写入修改,必须改用Unity提供的可读写路径Application.persistentDataPath:
- 先添加初始化逻辑,第一次运行时将Resources里的初始JSON复制到可读写目录:
void Awake() { textAsset = Resources.Load<TextAsset>("Files/ball_list"); string persistentPath = Path.Combine(Application.persistentDataPath, "ball_list.json"); // 首次运行复制初始文件 if (!File.Exists(persistentPath)) { File.WriteAllText(persistentPath, textAsset.text); } }
- 修改
DecrementGameItemCount方法的读写路径:
public override void DecrementGameItemCount(BallItem selectedBallItem, int decrementCount) { string persistentPath = Path.Combine(Application.persistentDataPath, "ball_list.json"); // 从可读写路径读取最新配置 string jsonContent = File.ReadAllText(persistentPath); BallItems ballItems = JsonUtility.FromJson<BallItems>(jsonContent); // 查找对应球体项 int targetIndex = -1; for (int i = 0; i < ballItems.ballItems.Length; i++) { if (ballItems.ballItems[i].name == selectedBallItem.name) { targetIndex = i; break; } } if (targetIndex == -1) return; // 未找到对应项直接返回 // 更新解锁次数与状态 ballItems.ballItems[targetIndex].count -= decrementCount; if (ballItems.ballItems[targetIndex].count <= 0) { ballItems.ballItems[targetIndex].count = 0; ballItems.ballItems[targetIndex].isPurchased = true; } // 将修改写入可读写路径 using (StreamWriter writer = new StreamWriter(persistentPath, false)) { writer.Write(JsonUtility.ToJson(ballItems)); } }
3. 额外优化点
- 直接遍历数组查找目标项,避免List和Array的转换操作,提升性能
- 使用方法传入的
decrementCount而非固定--,符合方法参数设计逻辑 - 增加未找到目标项的判断,避免索引越界报错
内容的提问来源于stack exchange,提问作者emowise
相关产品推荐
相关产品推荐

