1.打包流程
1)特殊文件处理
1.scene文件,移除除了初始场景的所有.unity文件
2.图集文件,自动生成对应的图集
3.不支持的文件格式转换为bytes读取(如lua和dll)
2) 为所有的文件生成abName
移除meta文件和manifest文件
shader打一个包,shader变体处理
文件资源拷贝目录相关
2.读取流程
1)mainfest文件
unity所有的资源引用关系都在mainfest文件内
2)依赖关系
先加载所有的依赖对象,再加载对应的对象,最后实例化对象
3)引用计数器
引用计数器处理
1) 使用unity的弱引用来处理资源的引用计数关系
2) 需自己维护所有的对象的引用计数,例如texture,animator,spriteAtlas等;不过spriteAtlas相对会比较难以维护,需全部加载
3) GameObject的引用计数相对来说久比较好处理了、、
4)加载进度条
基础的对象loading progress和多个对象的loading progress处理
3.卸载流程
assetBundle.unload(false) 仅卸载AssetBundle(包头和对应的引用关系)
assetBundle.unload(true) 同时卸载引用的资源
Resource.UnloadUnusedAssets() 卸载未引用的资源
Resources.UnloadAsset(asset) 直接卸载资源
GameObject.DestroyImmediate(assetObj, true) 卸载prefab
通常来说需要维护对应的assetBundle引用计数器和asset引用计数器,
asset引用计数不好维护,可使用Resource.UnloadUnusedAssets()处理
4.加密
1.unity打包bundle自带加密方式
//此方法会造成每次的MD5值不会跟之前的重复,对于热更不友好,暂时没相对比较好的解决方案
AssetBundle.SetAssetBundleDecryptKey("0123456789abcdef")
AssetBundle.SetAssetBundleDecryptKey(null)
2.二进制混淆
//会生成两份内存,不推荐
AssetBundle abBundle = AssetBundle.LoadFromMemory(File.ReadAllBytes(filePath));
//推荐的读取方式
AssetBundle abBundle = AssetBundle.LoadFromStream(File.ReadAllBytes(filePath));
//示例,简单异或加密。每次解密会有一定的性能消耗
using System.IO;
public class ABStream : FileStream
{
const byte KEY = 64;
public ABStream (string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) : base(path, mode, access, share, bufferSize, useAsync)
{
}
public ABStream (string path, FileMode mode) : base(path, mode)
{
}
public override int Read(byte[] array, int offset, int count)
{
var index = base.Read(array, offset, count);
for (int i = 0 ; i < array.Length; i++)
{
array[i] ^= KEY;
}
return index;
}
public override void Write(byte[] array, int offset, int count)
{
for (int i = 0; i < array.Length; i ++)
{
array[i] ^= KEY;
}
base.Write(array, offset, count);
}
}
3.字节偏移
//速度最快,但是容易被破解
AssetBundle.LoadFromFileAsync(this.filePath,0,8);