前言
本人在《龙之谷》负责资源管理工作一年多,积累相当多的打包经验。经验都写成博客,所以写一个总结篇,整理一下思路和感悟。
版本管理
版本管理,要从多平台、多渠道、多服务器、多语言等维度进行版本管理。
功能拆分
多平台,一般是3个平台(还有主机平台),如下
iOS
Android
PC
多渠道,一般是上线前夕需要部署到正式服上的模块,例如以下
huiwei
xiaomi
oppo
...
多服务器,一般游戏依据需要,通用的如下
内网测试服
(包括私人测试服)外网测试服
(用于接入外部渠道等需要的网络)商务服
(用于外部推广使用)审核服
(用于版号,ios等审核)准正式服
(跟正式服基本一致,一般比正式服提前一个版本)正式服
(对玩家开放的服务器)特殊服
实际上游戏运行时通过渠道、平台、版本等包体配置,来指定服务器请求服务器信息。
多语言,这个会根据需求,进行字符串、图片、语音等的替换。常用的方式是通过打包和资源导出时确定需要添加到当前渠道的语言包。
中文
繁体
English
...
多地区,如果全球发行的游戏,一般还要兼顾地区的多渠道(一般一个海外地区就一个渠道),笔者将其作为一个渠道处理。
CDN目录结构
对应上面的逻辑,我们CDN目录结构设计如下
--InTest
--Default
--IOS
--Android
--PC
--Test
--OutTest
--Default
--Test
--Ready
--Release
--Default
--IOS 一般只有一个IOS平台
--PC
--huawei 一般渠道都只有Android
--Android
--xiaomi
--Android
--Japanese 一般多地区,是跟渠道并行一个层级
--IOS
--Android
--PC
上述只是资源管理部分,在很多情况下,服务器很可能是同一台服务器,比如常见的iOS和Android数据互通。这样是根据游戏启动,游戏包体对应配置到服务端获取对应服务器地址,再连接对应服务器。
CDN文件目录
在平台之下是多版本的资源,会得到如下的目录结构
--PC 平台
--IOS
--Android
--1001000 当前版本的资源目录,包含所有资源
--Assets ab导出的目录
--xxx1.ab ab文件
--xxx2.ab
--xxx3.ab
--xxx4.ab
--Assets ab的manifast文件
--Bytes 二进制配置文件目录
--xxx1.bytes 二进制文件(加密)
--1001001 只导出比1001001增加和修改的文件
--Assets
--xxx1.ab 修改的保留
...xxx2.ab 相同的不放人目录
--xxx5.ab 增加的保留
--Assets
--1001002
--1001003
--1002000 换包需要新启midVer,会全部重新导出一遍资源
--1002001
--1001000.txt 版本文件表,包含所有文件信息
--1001001.txt
--1001002.txt
--1002000.txt
--1002001.txt
--version.txt 当前版本号
上面的表示就一目了然了
所有,管理维度依次是——服务器类型=》渠道=》平台=》版本
Git管理
应对上述的复杂情况,Git管理目前已经成为一个主流。
- 项目中最好只有一条主开发分支线,多服务器、多渠道、多语言、多平台的功能都被包含,关键节点拉出分支固定节点内容
- 要发布一个渠道,从开发主分支拉出分支作为xx渠道分支,导出package
- 热更xx渠道,从xx渠道分支拉出x.x.1版本,提交内容打patch,再从x.x.1 拉出x.x.2提交内容打patch
- xx渠道换包,将xx渠道合并回主开发分支,重复第2步
打包和资源文件
大包、小包和资源文件
游戏开发过程中,工程中资源分为可热更资源和不可热更资源。
可热更资源,一般包括
美术资源
音效资源
配置文件
脚本代码
不可热更资源
需编译代码
SDK,第三方库等
平台相关环境
打包,就是指将不可热更资源依据平台环境,导出成平台安装包(iOS,Android,PC),
资源导出,就是将可热更资源导出成平台相关的资源文件,进安装包或热更。
打包,分大包和小包。
大包指平台安装包包含所有的资源文件,一般包体非常大,iOS平台会要求使用大包。
小包指平台安装包只包含少量必要资源文件,其他资源文件通过热更下载的方式,一般Android、PC平台使用。
自动化Jenkins系统
自动化打包和资源导出,一般依赖Jenkins系统。
由上文,我们在多渠道、多平台、多服务器三个大维度,每个维度上还有版本维度。然后游戏工程一般非常大,如何解决n * n * n * n的需求呢?
笔者设计了以3个平台(iOS,Android,Pc)建立三个游戏工程目录,通过Git的快速切换分支功能,实现一键式自动化打包和热更:
- 基于指定分支拉出渠道分支,指定版本号,然后对三个平台打包和资源导出功能
- 基于指定分支(热更分支),导出热更资源的功能
当然,打包和资源导出都是相当耗时的操作。
平台安装包
不同平台都会生成对应的工程和安装包,然后上传CDN,并生成二维码用于下载。
资源文件
资源文件,一般更合适的名字叫可热更文件。一般包括三种
- 美术类资源,泛指贴图、模型、动作等,也包括语音、音效等,由美术制作
- 在导出过程中,一般需要依赖项切割、图集转换、数据压缩等流程,生成引擎和平台相关的资源
- 数据类资源,指保存数据的配置文件,一般策划维护
- 在导出过程中,一般需要导表、加密、压缩等流程,生成二进制流文件
- 代码类资源,指可以热更的脚本代码文件, 由程序开发
- 在导出过程中,一般需要混淆、加密等安全性流程,生成二进制流文件
最小化依赖树
在美术类资源导出过程中,解决冗余资源、资源复用、加载效率一直是一个难题。
我们知道,为了减少成本和资源大小,多个相似场景会复用大量相同的模型和材质,多个特效会复用相同的材质和贴图,多个角色会复用骨骼和动作,多个UI复用icon。
而这些资源复用,必然导致资源与资源之间的依赖关系,如果处理不好依赖关系,就会造成资源的冗余。问题就归结为需要一个算法实现对资源节点划分成不同的资源文件,保证每个资源节点只出现一次,而资源文件数量最少。
算法分以下几步:
- 提供资源路径列表作为输入节点(根节点)
- 对根节点分析依赖项,并将依赖项作节点,形成依赖图
- 对依赖图剪枝(去边),形成依赖树
- 对依赖树减点(去点),形成最小依赖树
- 对依赖树合点(合并点),优化最小依赖树
- 提取最小依赖树,生成打包节点列表
我们先对A,B两个资源root节点进行依赖分析, 经过第1步和第2步,我们实际上得到的图是这样的
注:圆角方形为root节点
当然,我们是不需要这么复杂的图结构的,开始剪枝。
第3步解决的重复依赖关系,简单讲就是父依赖子,子依赖孙,如果父也依赖孙,这条(父依赖孙)是不需要的,需要去除
。那么可以得到如下依赖树。
第4步特别难理解,又是依赖,又是被依赖,读者可以对照图加深理解。简单解释就是树删除一个子节点,孙节点全部挂在父节点下
。然后我们得到如下的图