AssetBundle.LoadFromStream加载LZ压缩的资源导致编辑器崩溃

本文地址:https://blog.csdn.net/t163361/article/details/109534650
最近准备申请新星创作者,需要2000个粉丝关注,觉得文章有用的,请点一下左侧边栏的关注,谢谢。

项目需要对Assetbundle加密,准备使用AssetBundle.LoadFromStream这个接口
然而调用的时候总会导致编辑器的闪退,

最后发现是因为当Assetbundle是场景并且用LZ4压缩时,就会导致闪退
unity2018.4.1~28全版本崩溃,2019,2020貌似也会崩溃

继续查问题

注意到LoadFromStream这个接口可以设置一次的读取大小,当大于lz4文件大小的时候,就不会崩溃了
看来lz4由于是分块压缩导致分块部分没有解密导致的问题

继续查问题
把程序打包成运行时后,依然会出问题,不过没有闪退
就开始翻看log了
先提示 CanRead/CanSeek需要设置成true
修改后提示资源被Dispose了,这时候想起来官方文档里的说明

Do not dispose the Stream object while loading the AssetBundle or any assets from the bundle. 
Its lifetime should be longer than the AssetBundle. This means you dispose the Stream object after calling AssetBundle.Unload.

总结
由于当时创建FileStream的时候使用了using,当使用lzma压缩时,资源会同步加载完,所以FileStream释放的时候,资源已经不需要再加载了,不会有问题。但是当使用LZ4的时候,资源是分块加载的,FileStream释放的时候,资源还在加载中,然后就导致闪退的现象。

LoadFromStream这个接口是看雨松博客知道的,导致崩溃的using也是这里来的,下面类比提供也给不会崩溃的代码样例

using System.IO;
using UnityEngine;
using UnityEngine.UI;
 
public class TestStream : MonoBehaviour
{
    [Header("是否启用Stream加载")]
    public bool isStream = true;
    float m_LoadTime ;
    Mystream fileStream;
    void Start()
    {
        if (isStream)
        {
            float t = Time.realtimeSinceStartup;
            fileStream = new MyStream(Application.streamingAssetsPath + "/encypt_myab.unity3d", FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 4, false)
            {
                var myLoadedAssetBundle = AssetBundle.LoadFromStream(fileStream);
                m_LoadTime = Time.realtimeSinceStartup - t;
                GetComponent<Image>().sprite = myLoadedAssetBundle.LoadAsset<Sprite>("1");
                myLoadedAssetBundle.Unload(false);
            }
        }
        else
        {
            float t = Time.realtimeSinceStartup;
            var myLoadedAssetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/myab.unity3d");
            m_LoadTime = Time.realtimeSinceStartup - t;
            GetComponent<Image>().sprite = myLoadedAssetBundle.LoadAsset<Sprite>("1");
            myLoadedAssetBundle.Unload(false);
        }
    }
 
    private void OnGUI()
    {
        if (isStream)
        {
            GUILayout.Label(string.Format("<size=50>\nAssetBundle.LoadFromStream :{0} </size>", m_LoadTime));
        }
        else
        {
            GUILayout.Label(string.Format("<size=50>AssetBundle.LoadFromFile :{0} </size>", m_LoadTime));
        }
 
    }
}

把fileStream缓存起来,不需要的时候再释放掉

备注:
如果加密的算法不是简单的异或加密的,而是使用分组加密的话,LZ4由于是分块加密,所以读取的时候的Position位置也是不固定的,需要特殊处理才能使用
具体解决可以看我开源的库
https://github.com/t1633361/AssetbundleSm4Encrypt

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值