本文地址: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