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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:02:16