Unity3D研究院之加密Assetbundle不占内存(一百零五)

https://www.xuanyusong.com/archives/4607

AssetBundle.LoadFromMemory基本上是无法在手机上用的,因为要多占一份内存,所以大多Unity项目都不进行资源加密。
Unity2017.2提供了一个新的API AssetBundle.LoadFromStream,通过名字就可以知道它是流加载,那么就不会像AssetBundle.LoadFromMemory那样多占一份很大的内存了。

打包Assetbundle的同时生成加密文件的两个文件分别加载它。

myab.unity3d
encypt_myab.unity3d

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

[MenuItem("Tools/BuildAB")]

static void BuildAB()

{

FileUtil.DeleteFileOrDirectory(Application.streamingAssetsPath);

Directory.CreateDirectory(Application.streamingAssetsPath);

var manifest  = BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.ForceRebuildAssetBundle, BuildTarget.iOS);

foreach (var name in manifest.GetAllAssetBundles())

{

var uniqueSalt = Encoding.UTF8.GetBytes(name);

var data = File.ReadAllBytes(Path.Combine(Application.streamingAssetsPath, name));

using (var myStream = new MyStream(Path.Combine(Application.streamingAssetsPath, "encypt_" + name),FileMode.Create))

{

myStream.Write(data, 0, data.Length);

}

}

AssetDatabase.Refresh();

}

这里测试的Assetbundle一共有20M, 使用LZ4压缩格式。

加密和解密我这里随便写个简单的异或 ^ 。后面也可以用一些更好的算法,总之加密可以慢,但是解密一定要快。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

using System.IO;

public class MyStream : FileStream

{

const byte KEY = 64;

public MyStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) : base(path, mode, access, share, bufferSize, useAsync)

{

}

public MyStream(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);

}

}

界面上放两个Image 分别加载它。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

using System.IO;

using UnityEngine;

using UnityEngine.UI;

public class TestStream : MonoBehaviour

{

[Header("是否启用Stream加载")]

public bool isStream = true;

float m_LoadTime ;

void Start()

{

if (isStream)

{

float t = Time.realtimeSinceStartup;

using (var 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));

}

}

}

如下图所示,在iPhone7上,基本上加载时间差不多。


加密以后资源就无法被打开了。

注意:Android下的streamingAssets目录不能使用,因为android下是放在jar里并不是文件系统。一定要用的话需要拷贝到 Application.persistentDataPath下。

原文地址:https://www.cnblogs.com/nafio/p/11811287.html

时间: 2024-10-14 02:15:46

Unity3D研究院之加密Assetbundle不占内存(一百零五)的相关文章

【转】Unity3D研究院之通过C#使用Advanced CSharp Messenger(五十)

http://www.xuanyusong.com/archives/2165 Advanced CSharp Messenger 属于C#事件的一种. 维基百科中由详细的说明http://wiki.unity3d.com/index.php?title=Advanced_CSharp_Messenger 上周的一天刚巧有朋友问到我这一块的知识,那么我研究出来将它贴在博客中,帮助了他也帮助我自己!哇咔咔. Advanced CSharp Messenger的特点可以将游戏对象做为参数发送.到底A

Unity3D研究院之Assetbundle的实战(六十三)

1.创建Assetbundle          无论是模型资源还是UI资源,最好是先把他们放在Prefab中,然后在做成Assetbundle.我们以模型来举例,Assetbundle中可以放一个模型.也可以放多个模型,它是非常灵活了那么最需要考虑的就是模型空间占用的问题. 比如我们有两个完全一样的模型,但是他们身上绑定的脚本不一样,此时需要把这两个模型放在两个不同Prefab中.如下图所示,我们分别对这两个Prefab打包,我们可以清晰的看到两个相同的Prefab打包在一起只占1M空间,而将

(转)Unity3D研究院之将场景导出XML或JSON或二进制并且解析还原场景

自:http://www.xuanyusong.com/archives/1919 导出Unity场景的所有游戏对象信息,一种是XML一种是JSON.本篇文章我们把游戏场景中游戏对象的.旋转.缩放.平移与Prefab的名称导出在XML与JSON中.然后解析刚刚导出的XML或JSON通过脚本把导出的游戏场景还原.在Unity官网上下载随便下载一个demo Project,如下图所示这是我刚刚在官网上下载的一个范例程序.           接着将层次视图中的所有游戏对象都封装成Prefab保存在资

Unity3D 研究院之IOS高级界面发送消息与Unity3D消息的接收

今天和盆友们讨论IOS的高级界面与unity3d游戏引擎的交互,这个在开发中是非常重要的,unity3d 毕竟是一个面向多平台的一个游戏引擎,它不可能全部为IOS 考虑的面面俱到,引擎中也不存在针对IOS的高级界面的控件的使用. 本例实现游戏背景是Unity3D 的游戏世界,前面添加4个IOS的高级界面的按钮,并且点击这些按钮可以将消息传递给背景的Unity3D ,让它做一些事情. 上一章介绍了触摸IOS屏幕 移动摄像机的位置,下面有盆友问我说他不想移动摄像机的位置,就想移动物体的位置,我在这里

结构体所占内存大小

结构体所占内存大小划分原则: 1.划分字节,按照当前结构体中,字节数最大的类型作为划分单元.[这里面还有一些前提.下面的例子会详细说到] 2.以矩形块儿的形式划分. #include <stdio.h> /**划分示意图: 最小单元是 double所以 这个 地方按照8个字节作为最小单元来划分. */ struct student1 { double avgMark; int ID; }; /**划分示意图: 最小单元不能是数组这个地方的最小单元是 1个字节 */ struct student

C++中的类所占内存空间总结

C++中的类所占内存空间总结 最近在复习c++的一些基础,感觉这篇文章很不错,转载来,大家看看! 类所占内存的大小是由成员变量(静态变量除外)决定的,成员函数(这是笼统的说,后面会细说)是不计算在内的. 摘抄部分: 成员函数还是以一般的函数一样的存在.a.fun()是通过fun(a.this)来调用的.所谓成员函数只是在名义上是类里的.其实成员函数的大小不在类的对象里面,同一个类的多个对象共享函数代码.而我们访问类的成员函数是通过类里面的一个指针实现,而这个指针指向的是一个table,table

C++类所占内存大小计算

C++类所占内存大小计算 转载时请注明出处和作者联系方式文章出处:http://blog.csdn.net/chenchong08作者联系方式:[email protected] 说明:笔者的操作系统是32位的. class A {}; sizeof( A ) = ?sizeof( A ) = 1明明是空类,为什么编译器说它是1呢?空类同样可以实例化,每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所

【C语言】C语言程序所占内存分类

参考"http://blog.sina.com.cn/s/blog_63d4849c01014qg3.html" C语言内存分为5部分:堆.栈.全局(静态)区.常量区(只读)和代码区. 堆,需要人工申请和释放内存,其他均为系统自动释放. 全局(静态)区.常量区:全局可见! #include <stdio.h> #include <malloc.h> int a=0;//初始化全局变量,存在“全局(静态)区(data)初始化”中,程序结束后由系统释放 char *

Unity3D研究院之IOS本地消息通知LocalNotification的使用

原地址:http://www.xuanyusong.com/archives/2632   现在的游戏里一般都会有本地消息,比如每天定时12点或者下午6点告诉玩家进入游戏领取体力.这种东西没必要服务器去推送,客户端就可以完成.Unity里面提供了本地任务的功能但是只有IOS上才支持,开始我有点不解为什么Android上不支持,当我把Android的本地通知做完后,我才明白.IOS源生的API中就支持固定时间循环推送,而Android上需要自己开启一个Services,启动一个AlarmManag