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

Unity中Try/Catch无法捕获AssetBundle.LoadFromFile异常的解决问询

解决Unity损坏AssetBundle导致的未捕获异常问题

首先明确:AssetBundle.LoadFromFile同步加载损坏的AssetBundle时,可能抛出非托管底层异常,这类异常无法被普通C# try/catch捕获,因为它来自Unity的C++底层实现。以下是两种可行的解决方案:

方案1:使用异步加载替代同步加载

异步加载API会将异常封装在加载结果中,不会直接导致程序崩溃,你可以通过检查加载状态来处理损坏的AssetBundle:

修改后的代码示例:

private IEnumerator GetFiles()
{
    List<string> files = new List<string>();
    EnumerateFiles(baseDir, ref files);

    foreach (string assetBundleName in files)
    {
        AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(assetBundleName);
        yield return request;

        if (request.assetBundle == null)
        {
            // 加载失败,记录日志或跳过该文件
            Debug.LogError($"加载AssetBundle失败:{assetBundleName}");
            continue;
        }

        try
        {
            var prefabNames = request.assetBundle.GetAllAssetNames()
                .ToList()
                .Where(s => s.ToUpper().EndsWith(".PREFAB"))
                .ToList();
            prefabs.Add(assetBundleName, prefabNames);
        }
        catch (Exception ex)
        {
            Debug.LogError($"处理AssetBundle内容失败:{assetBundleName},错误信息:{ex.Message}");
        }
        finally
        {
            request.assetBundle.Unload(true);
        }
    }
}

注意:因为使用了异步加载,需要将GetFiles改为协程方法,在Start中通过StartCoroutine(GetFiles())调用。

方案2:加载前先做合法性预校验

在调用加载API前,先检查文件的基本合法性,过滤明显损坏的文件:

  • 检查文件是否存在且大小大于0
  • 读取AssetBundle的魔数(文件开头4字节,合法AB的魔数为0x46535955)

示例校验代码:

private bool IsValidAssetBundle(string filePath)
{
    if (!File.Exists(filePath))
        return false;

    FileInfo fileInfo = new FileInfo(filePath);
    if (fileInfo.Length < 4) // AB头部至少包含4字节魔数
        return false;

    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    {
        byte[] magicBytes = new byte[4];
        fs.Read(magicBytes, 0, 4);
        uint magicNumber = BitConverter.ToUInt32(magicBytes, 0);
        return magicNumber == 0x46535955;
    }
}

然后在遍历文件时先调用校验方法:

private void GetFiles()
{
    List<string> files = new List<string>();
    EnumerateFiles(baseDir, ref files);

    foreach (string assetBundleName in files)
    {
        if (!IsValidAssetBundle(assetBundleName))
        {
            Debug.LogError($"无效的AssetBundle文件:{assetBundleName}");
            continue;
        }

        try
        {
            assetBundle = AssetBundle.LoadFromFile(assetBundleName);
            if (assetBundle == null)
            {
                Debug.LogError($"加载AssetBundle失败:{assetBundleName}");
                continue;
            }
            var prefabNames = assetBundle.GetAllAssetNames()
                .ToList()
                .Where(s => s.ToUpper().EndsWith(".PREFAB"))
                .ToList();
            prefabs.Add(assetBundleName, prefabNames);
        }
        catch (Exception ex)
        {
            Debug.LogError($"处理AssetBundle出错:{assetBundleName},错误:{ex.Message}");
        }
        finally
        {
            if (assetBundle != null)
                assetBundle.Unload(true);
        }
    }
}

补充说明

  • 优先推荐方案1,异步加载不仅能避免崩溃,还不会阻塞主线程,提升程序运行流畅度。
  • 方案2的预校验只能过滤明显损坏的文件,对于头部正常但内容损坏的AB,仍需结合异常捕获或加载结果检查处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:45:32