Addressable

Unity Addressables 系统在 Asset Bundle 之上,提供了异步加载,依赖管理以及内存管理等更加丰富的资源管理功能,也让开发者实现远程资源更新更加的便捷。但是,再灵活的系统设计也很难满足开发者各种应用场景的需求,比如,有的开发者希望能够定制 Catalog,有些开发者希望资源能够加密。为了达到某些特定需求,对 Addressables 系统进行适当的扩展也就在所难免。本文希望通过一个加密功能的实际案例来帮助大家更深入的理解 Addressables 系统,以及如何对其进行扩展。

本文所介绍的加密功能已添加到 Addressables.CN 插件包中,大家可以下载使用。使用方式也很简单,只需在 Group 属性中设置相应加密方式即可实现资源包加密。更多详情请参考使用手册:

https://ucgbucket.unitychina.cn/AssetStreaming/AddressablesCN.pdf

Addressable

下面我们就来看看如何实现 Asset Bundle 的加密,我们需要实现在打包的时候对资源包进行加密,在加载的时候对资源包进行解密。为了实现这两个过程,我们就需要了解资源加载和资源打包的过程。首先我们来看如何在打包的时候对资源包进行加密。

Asset Bundle 加密

01 Asset Bundle 构建过程

资源包构建主要由AddressableAssetSettings.BuildPlayerContent()函数完成,该函数用于构建 Asset Bundles 和相应的 ContentCatalog。

配置资源包构建参数

如下图所示,资源包的构建参数主要由 AddressableAssetSettings 保存,各个 Group 的信息保存在 BundledAssetGroupSchema 类中,因此我们可以在这里保存加密类型 DataStreamProcessorType。

Addressable

扩展资源包构建

在 Addressables 中,资源包的构建包含几种模式,分别对应 BuildScriptPackedMode,BuildScriptFastMode 和 BuildScriptVirtualMode,AddressableAssetSettings 会保存当前使用的模式。正式资源包的构建对应 BuildScriptPackedMode,因此,如果要添加资源包加密功能,可以考虑对 BuildScriptPackedMode 中的功能进行扩展。

02 添加加密功能

在资源包的后处理中进行数据加密

BuildScriptPackedMode:PostProcessBundles 函数负责 AssetBundle 构建完成后的一些处理,其中会调用 CopyFileWithTimestampIfDifferent 函数对资源包进行保存。在资源包保存时,创建加密数据流,并将资源包复制到该加密数据流中进行文件保存,就实现了资源包加密。

Addressable

实现自定义加密数据流

加密数据流主要提供两个接口,CreateWriteStream 和 CreateReadStream,用于数据对加密和解密,然后就可以根据项目需要对接口进行实现。在 AddressableCN 版本中,加密数据流的实现位于 EncryptedAssetBundleProvider 文件中。

Addressable

Asset Bundle 解密

接下来,我们再来看如何在加载的时候实现资源包的解密。

01 Asset Bundle 加载过程

LoadAssetAsync 是 Addressables 系统常用的异步加载接口,加载结果(AsyncOperationHandle)会通过回调函数返回。下面这段代码就简单展示了异步加载的全过程。

using System.Collections; using System.Collections.Generic; using UnityEngine.AddressableAssets; using UnityEngine; public class AddressablesExample : MonoBehaviour { GameObject myGameObject; ... Addressables.LoadAssetAsync("AssetAddress").Completed += onl oadDone; } private void onl oadDone(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle obj) { // In a production environment, you should add exception handling to catch scenarios such as a null result. myGameObject = obj.Result; } }

整个加载过程大概分为 3 个步骤:

创建异步操作

LoadAssetAsync 接口实际上会调用 ResouceManager.ProvideResouce 来请求资源,并在该函数中创建一个与资源类型对应的异步操作,该操作以 AsyncOperationBase 作为基类。创建好后,ResourceManager 会调用 StartOperation 启动该操作。

通过 Provider 完成资源请求

AsyncOperation 会将实际资源请求交给继承于 IResourceProvider 接口的Provider,Provider 与资源类型对应,比如 Asset Bundle 由 AssetBundleProvider 完成资源下载。

资源请求完成

资源请求完成后,异步操作会触发完成事件,并将 AsyncOperationHandle 返回给用户。

下图所示时序图简单表示了上述所示的资源请求过程,实际逻辑会考虑操作依赖关系,要复杂一些。

Addressable

02 添加解密功能

了解了资源加载过程后,我们只需要在读取数据的时候创建读取加密数据流的对象,将数据流进行解密即可。以下代码函数实现位于 AssetBundleResource 类中,该类实际调用 WebRequest 请求 Asset Bundle。

Addressable

以上就是对如何扩展资源包加密功能的简要介绍。

上一篇:JQuery Mobile + Cordova 实战一


下一篇:python学习记录2