# 构建与产物

小游戏现在能支持超大型小游戏的瞬时开启,实现了完全流式按需下载游戏资源,能支持资源数量庞大的游戏的即开即玩。整个构建过程会高度自动化,用户在不需要配置的情况下即可实现。同时为了让开发者能根据游戏场景保证最优的下载速度以及缓存利用率,我们也提供了 assetsBundle 和定制的分析工具。

构建资源系统提供了如下特性

  • 自动资源分包
  • 自动版本控制
  • 流式下载
  • 代码对资源分包无感知
  • 自动化缓存与淘汰
  • assetsBundle
  • 资源下载分析工具

点击资源系统新手引导,直接在工具中按流程学习,并查看Demo。

# 构建

构建流程指的游戏的资源需要处理成最适合用户使用的数据格式,最后让用户在不同的平台都能得到最好的游戏性能。构建流程会进行资源的编译,比如图片需要合并,编译成压缩纹理,模型的二进制需要统一打包,甚至是将动画模块提前烘培成对真机性能最佳的数据格式,这些编译的流程会把用户的 assets 目录下的游戏资源进行按平台处理好,并且自动根据平台使用最佳的方案。整个过程用户可以无需感知,同时也可以让用户自定义一些配置,比如压缩纹理的精度类型。

构建界面

# 命令行构建

除了从 UI 启动构建,还可以通过命令行调用安装完成的工具,进行引擎项目的构建、预览、上传等操作,方便开发者编写脚本自动化构建发版流程。

要使用命令行,注意首先需要在开发者工具的设置 -> 安全设置中开启服务端口。

命令行工具所在位置:

macOS: <安装路径>/Contents/MacOS/cli

Windows: <安装路径>/cli.bat

# 命令索引

可以使用 cli -h 查看所有命令,使用 cli --lang zh -h 可以使用中文版本的帮助。

全部命令可以点这里参考本文只列出构建相关的。

引擎构建的命令是:cli engine build "项目目录"

命令行构建可以定义一些配置,开发者可以在Project Setting标签的构建配置中自定命令行构建的配置。

或是直接书写在项目中 engine.ide.json 内,如下:

// engine.ide.json 参考内容
{
  engineVersion:'1.1.0',
  // ...其他配置
  "build": {
    "mainScene": {
      "3d":"assets/Assets/Resources/example3D.scene",
      "2d": "assets/Assets/Resources/example2D.scene"
    },
    "textureCompressionEncodeQuality": {
      "pvr": "pvrtcnormal",
      "etc": "etcfastperceptual",
      "astc": "astcmedium",
    },
  }
}

build.mainScene:通过命令行构建时,声明主2D,3D场景。

build.textureCompressionEncodeQuality:压缩纹理配置,可不填。可选的有:

pvr:'pvrtcfastest'|'pvrtcfast'|'pvrtcnormal'|'pvrtchigh'|'pvrtcbest'
etc:'etcfast'|'etcslow'|'etcfastperceptual'|'etcslowperceptual'
astc:'astcveryfast'|'astcfast'|'astcmedium'|'astcthorough'|'astcexhaustive

# 产物

和 app 游戏不同的是,开发者不能将大量的游戏资源都放置到游戏的 app 里面,这样会导致游戏启动变慢,用户流失。所以小游戏的构建结果会分为主包,代码分包以及资源包。

主包,玩家在点击进入小游戏以后直接下载的游戏资源内容,比如可能是游戏登录页。包括了主要需要的代码,以及第一个入口的2D/3D场景及其依赖的资源。代码包下载到客户端后会被缓存起来,以便于下次离线打开。代码包清理的时机由算法动态计算,但可以认为在手机存储空间足够的情况下,代码包都不会被主动清理。当用户主动在历史列表删除小游戏(下拉任务栏删除不算)时,代码包会被清理。可以参考代码包文档

代码分包,玩家在玩的过程中,不需要立刻使用的代码,可以单独打包成一个分包,然后在需要用的时候,异步下载再使用。可以参考代码分包文档

资源包,非代码的游戏资源非常大,没有必要全部被放在微信平台。构建的之后开发者要把这些编译结果(minigame/assets/IDEPack)放在 CDN 上,然后游戏真机在运行时动态从 CDN 下载。为了达到最好的流式加载效果,整体的构建和加载都被小游戏工具封装了起来。资源包本质是由许许多多的碎包组成,用户玩到哪里,才下载对应的碎包。开发者也可以把部分资源包放到小游戏主包里面。这样当小游戏下载好了就能直接用,不需要从远程再拉取。在资源的import setting中"Pack In BuildIn When Is Entry Resource"设置。

# 入口场景以及入口资源

对于资源,我们也有一些不同的定义,来帮助开发者理解,比如入口场景,入口资源。

入口场景,构建的配置中,用户需要定义入口场景,作为整个游戏启动的首场景。工具会自动依赖分析找到这个场景静态依赖的所有美术资源,然后打包在主包里面。一般用来作为登录界面或是 loading 页面,这样玩家能最快的进入游戏。

入口资源,开发者在游戏运行的过程中,常常需要用代码去动态加载资源进行使用。这些资源少部分可能需要在主包里面,大部分在 CDN 包内,我们允许用户去配置。因为这些资源是使用代码动态加载的,工具本身没有办法分析出来,所以需要开发者去定义这些资源出来,我们叫这种资源叫做入口资源。开发者可以通过资源文件的Import Setting去设置为入口资源。入口资源尽可能不要设置过多,虽然这些资源并不会打包在用户的主包里面,但是小游戏工具需要给它们生成一个映射表(register_xxx.json),去存储路径和 CDN 包的映射。在加载资源之前,必须要先加载这个映射表,如果太大会影响加载速度,所以建议不要太大。

入口资源与资源包,资源包的碎包是由入口资源打包而成,我们称这些碎包为资源组。默认情况下,在构建的时候,工具自动依赖分析出入口资源以及他的全部静态依赖资源,打包成一个资源组,也就是一个 CDN 碎包,这样只有代码加载这个入口资源的情况下才会从网络下载这个包,并且缓存到文件系统,再把文件加载到内存并实例化成入口资源对应的内存对象。下次再请求就会从文件系统中直接读取缓存。默认的规则下,在依赖分析的过程中,如果多个入口资源依赖了相同的资源,那么就会把重复的资源单独成包,这样去规避重复下载。

# 流式下载

小游戏框架默认以http2.0的协议去下载资源,开发者的 CDN 服务需要开启对应的能力,如果没有开启则自动降级为http1.0。开启之后开发者的下载流程则完全使用多路复用的技术流式下载,天然达到最快的下载速度。

# AssetsBundle

资源系统同时也提供了assets bundle能力帮助开发者合并资源包,合并主要有两种作用

  • 规避10个请求并发限制(http1.0)
  • 减少从磁盘读取文件的次数

我们可以给入口资源设置Assets Bundle Name,这样就可以告诉工具将相同名称字符串的多个入口资源以及它们的依赖打包成一个大包。开发者在工具的 Project 中选择一个文件,然后可以在 inspector 的importSetting中配置它的Asset bundle name。在没有开启http2.0的情况下,大包可以规避小游戏的10个请求并发限制,从而提高下载速度。针对游戏中常常需要同时下载的入口资源,设置成assets bundle,可以提升用户体验,

下载到本地磁盘后,文件依然是按照 bundle 的大文件存储,当游戏需要实例化这个游戏对象的时候,会从磁盘中读取。如果是多个文件的话,则会读取多次,如果是大文件则读取次数会减少。但是因为读取磁盘是整体读取的,内存占用会升高,应该避免暂时用不到的资源打包在一起。开发者需要根据自己的业务定制合理的 bundle 方案。

同时也提供资源包的分析工具,开发者可以在模拟器中使用。

# 上传资源到CDN

默认情况下,资源包会被构建到项目根目录/assets/minigame/IDEPack目录下,也就是主包内。如果开发者什么都不设置,游戏运行时会自动从项目根目录/assets/minigame/IDEPack这个目录读取资源。这时候并没有使用 CDN 能力。

分析报告,构建完成后,可以查看构建分析报告。分析报告中会帮你分析主包,代码分包,资源包的大小情况,是否超过限制,以及提供解决方案。

分析报告

主包和代码分包,里面可能代码过多,开发者可以通过右上角 >> 详情 >> 本地设置 >> 上传代码时自动压缩混淆压缩自己的代码。也可以精简自己的业务代码。

资源包,体积很可能超过小游戏包大小限制,所以开发者需要将这个 IDEPack 文件夹上传到CDN,并配置 CDN 的资源路径前缀,让小游戏运行时加载的时候去拉取。

开发者需要做三件事情

  • 上传资源到CDN: 在 CDN 上面需要把 IDEPack 文件夹保留为对应的资源根目录,名字不变。
  • 配置上传小游戏忽略 IDEPack 文件夹:可以使用分析报告中的一键设置。也可以自己在project.config.json中配置 packOptions 的ignore属性。忽略后的文件夹就不会被打包到主包中。
  • 配置 CDN 网络前缀:Project Setting标签 >> 游戏设置 >> baseURL中配置https://cdn/,下载的时候会请求https://cdn/IDEPack/xxx。配置完以后需要重新构建项目。

分析报告中推荐了三种 CDN 方案及其快速设置能力。

  • 云开发存储CDN。使用云开发提供的 CDN 服务,有5G的免费流量,可以快速体验构建游戏。(测试号不行)
  • 自定义CDN。也可以选择开发者自定的 CDN 服务,但是要记得配置 baseUrl 以及忽略 IDEPack 文件夹。
  • 局域网本地CDN,开发者可以一键启用,在模拟器和开发版本直接使用。但是要保证手机和工具在一个局域网。

# 备份CDN

出于游戏稳定性的考虑,开发者可能会想将资源上传至多个 CDN 中,在一个服务器出问题后,可以自动由其他 CDN 来替补。

想要配置多CDN,只需要:

  1. 开发者可以在Project Setting标签 >> 游戏设置 >> backupURLs中配置。

  2. 在Loader.load()调用的额外参数里,指定httpRetryCount = 3

这样的话每次下载失败之后,都会重试3次,每次重试都会自动尝试下一个CDN。

# 资源包版本控制

开发者的游戏需要不停地迭代,主包以及代码分包的版本管理以及审核发布都部署在了微信公众平台后台,不需要开发者自己维护。

但是资源包的发布由开发者自行发布管理。框架使用 hash 后缀来进行版本管理,构建出来的资源包会在文件结尾自动加上 hash 后缀,真机的缓存机制也依赖于hash。同时构建出来的小游戏的主包版本里面会生成一个入口资源和资源包路径的映射表,下载到这个主包的小游戏用户会去拉取这个有 hash 后缀的路径的资源。每次构建,如果资源没有变更,那么 hash 值也不会改变,自然能复用原本的 CDN 缓存。

在每次审核通过后,准备正式发布小游戏之前,开发者资源包递归合并到上一次部署的相同目录下。合并之后,新增的包会第一次部署到CDN,如果是和上一个版本同样内容的资源组,那么他们的 hash 以及网络路径也相同,就能继续利用文件系统或是 CDN 的缓存。

不建议删除原来的 CDN 包,因为真机的用户可能还在使用旧版本的主包,也就是会拉取上一个版本需要的资源组路径。部署成功后再在微信后台发布小游戏。