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

Unity使用UnityWebRequest下载多AssetBundle缓存丢失无法离线加载问题

问题根因

你遇到的缓存丢失问题主要由两个原因导致:

  1. Unity默认的AssetBundle全局缓存有空间上限,当新下载的包体总大小超出上限时,系统会自动删除最早下载的旧缓存,就会出现下载B后A被清理、多包先后加载都丢失的情况。
  2. 移动端系统的存储空间清理机制也可能会主动清理Unity的默认缓存目录,完全依赖默认缓存很容易出现离线加载失败的问题。

解决方案

1. 调整默认缓存规则,避免自动清理

在项目初始化阶段(比如启动页Awake逻辑中)先修改默认缓存的配置,根据业务需求设置足够大的容量,或者设置缓存永不过期:

// 设置缓存最大容量为10GB,单位为字节,可根据实际需求调整
Caching.defaultCache.maximumAvailableDiskSpace = 10L * 1024 * 1024 * 1024;
// 额外设置缓存永不过期,不会被系统自动清理
Caching.defaultCache.expirationDelay = -1;

2. 增加自主持久化存储逻辑(最稳妥方案,完全规避缓存被清理问题)

不要完全依赖Unity的默认缓存,下载到AB包后主动把包体字节存到Application.persistentDataPath下的自定义目录,离线加载时优先读本地文件,只有本地没有对应版本的包时才走联网下载。

注意:自主存储AB包时,建议同时把对应包的版本号、CRC值存在本地配置文件里,加载前先校验本地包的版本是否和服务端一致,避免加载旧资源。

3. 优化代码逻辑

调整后的完整实现示例如下,同时兼容缓存加载、本地存储加载、联网下载三种场景:

// 先判断对应版本的AB包是否已经在缓存里,存在的话可以直接加载不需要联网
if (Caching.IsVersionCached(url, bundleData.version, bundleData.crc))
{
    using UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(url, bundleData.version, bundleData.crc);
    yield return uwr.SendWebRequest();
    LoadAssetAndCallback(uwr, bundleData, levelText, isDiff, callback);
    yield break;
}

// 缓存不存在,先尝试读本地持久化存储的包
string localSavePath = Path.Combine(Application.persistentDataPath, "AssetBundles", bundleData.name);
if (File.Exists(localSavePath))
{
    AssetBundle localBundle = AssetBundle.LoadFromFile(localSavePath);
    if (localBundle != null)
    {
        Sprite sprite = isDiff ? localBundle.LoadAsset<Sprite>(levelText + "Diff") : localBundle.LoadAsset<Sprite>(levelText);
        callback(sprite);
        localBundle.Unload(false);
        yield break;
    }
}

// 本地也没有,走联网下载逻辑
using UnityWebRequest downloadUwr = UnityWebRequestAssetBundle.GetAssetBundle(url, bundleData.version, bundleData.crc);
yield return downloadUwr.SendWebRequest();
if (downloadUwr.result != UnityWebRequest.Result.Success)
{
    Debug.Log("下载失败:" + downloadUwr.error);
    callback(null);
    yield break;
}
// 下载成功后主动存到本地持久化目录
Directory.CreateDirectory(Path.GetDirectoryName(localSavePath));
File.WriteAllBytes(localSavePath, downloadUwr.downloadHandler.data);
LoadAssetAndCallback(downloadUwr, bundleData, levelText, isDiff, callback);

// 封装统一的资源加载回调方法
void LoadAssetAndCallback(UnityWebRequest uwr, BundleData bundleData, string levelText, bool isDiff, Action<Sprite> callback)
{
    AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
    if (bundle == null)
    {
        Debug.Log("COULDN'T LOAD ASSET BUNDLE");
        callback(null);
        return;
    }
    Sprite sprite = isDiff ? bundle.LoadAsset<Sprite>(levelText + "Diff") : bundle.LoadAsset<Sprite>(levelText);
    callback(sprite);
    // 资源加载完成后卸载AB包,避免内存泄漏,false表示仅卸载包体不卸载已加载的资源
    bundle.Unload(false);
}

内容的提问来源于stack exchange,提问作者Volkan Ege Dindar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 03:30:03