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

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下。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值