Unite 2019 Shanghai:《不可思议之梦蝶》从 PC 版移植到 Nintendo Switch 经验分享

作者:转载小公举
2019-05-14
11 8 0

会议主题:技术专场 4
会议时间:2019 年 5 月 11 日
会议地点:上海国际会议中心

5 月 10 日晚,Unite Shanghai 2019 Keynote 主题演讲于上海国际会议中心盛大举行。从最前沿的技术到令人惊艳的 Made with Unity 案例,整场 Keynote 无不体现了 Unity 技术的每一个进步,都是服务于每一位创作者,以技术致敬每一位创作者 -Unity for all!

我们选择了一些演讲实录在这里分享给大家。这一次是队友游戏李喆分享的的《不可思议之梦蝶(Incredible Mandy)》从 PC 版移植到 Nintendo Switch 经验分享。

演讲内容

李喆:大家下午好。自我介绍一下,我是李喆,我在天津的一个独立工作室,之前做的游戏叫“鲤”,一开始两个人,后来为了做《不可思议之梦蝶》这个项目,我们扩大到 14 个人,因为在开发流程和分配上有更多工作要做。我们在“鲤”上挣到一些钱,现在想做更大更有挑战的事情。

这是《鲤》这个游戏,我们是为了发布到 PS 的平台,我们又重新开发了一遍,也是在 2015 年的时候第一次用到 Unity 的工具,同样的项目在两个平台上开发。

这个海报是保持画面比较清晰的风格,为什么要用这个风格呢?用这种美术风格是比较讨巧的,也可以充分发挥出美术人的优势,可以显示出比较有清晰亮点的游戏结果。接下来看一下美术游戏的宣传片。

李喆:在游戏里面做了2D 手绘画,这样的画面在 PC 平台也是常见的,很多玩家都买了 Switch,但是都没有玩,我们现在也是积极在移植。

我们在游戏开发过程当中,因为是第一次开发 3D 游戏,我们要用到 Unity 里面很多很多的插件,很多基础不了解看技术代码就可以了解很多知识。我之前在 Unity 分享了一篇文章,用了多少插件,也得到了很多认可。其实做这个项目 Unity 插件还是可以提高不少效率的。

现场图片

接下来就讲一下主要内容,就是把 PC 平台游戏怎么移植到 Switch 平台,先说一下基本的开发,Switch 需要大家提前知道一些知识,不能用标准的 Unity Input 来做,我们用了一个插件 Rewired,这个可以适应任何的手柄,我们还用了 HD 振动,还运用了 Joy-Con 等 5 种输入方式。玩过 Switch 平台都知道,Switch 两个手柄是可以拆出来变成两个手柄,然后它的按键位置都会发生变化,你要知道所有方式并对游戏设计做好很好的规划,像梦蝶是不支持 Joy-Con Left 和 Joy-Con Rirght。

接下来是存档问题,存档文件都是有读取要求的,需要根据范例重写 I/O 部分来做。在奖杯系统里面,做的 PC 版本是有奖杯系统的,大家会收集奖杯去玩游戏,这些奖杯在任天堂平台都没有,我们要自己制作弹窗和展示。

现场图片

接下来是声音格式。像 Switch 平台支持 Opus 格式硬解压,我们使用 Wwise 可以支持 OpusNX 格式。它自带功能有很多,这个很多平台的声音都是可以的支持,也可以对 Switch 平台有一个格式,甚至可以调用硬件,这个有一个压缩格式,是可以直接压缩进入内存的,在运行时占用内存会更低一些,如果做的游戏没有考虑内存问题可能会爆掉。

在说一下使用插件问题,像 Wwise 和 Rewird 是需要考虑授权和版本问题,像 Wwise 根据不同平台有折扣,Rewird 是免费的,是一次性支付可以使用的,在打包时并没有针对平台代码。这个代码怎么获得的,你要通过任天堂开发后台提交申请,是由任天堂提供给 Wwise 的开发商,再通过 Wwise 开发商提供信息给到你,这个东西是没有技术难度,是有时间考虑的。像 Wwise 是需要两个工作日的,这个东西就可以帮助大家节省时间。

上面说的是一些具体基础上的经验,底下再说一下遇到的问题,这些问题如果没有动手做过,几乎是想不到的。如何选择 Unity 版本?这个版本随着 SDK 版本变化,你提交游戏的 Unity 版本要求很高,如果项目没有达到要求的最低版本的话提交就会失败,是会被拒绝的。我们遇到一个问题,可能有时候打包出来的游戏在 Switch 出现一些崩溃问题,而且只有非常少的信息提供给你,你去开发者论坛搜索根本就没有任何线索,我们要尝试切换一下更低版本,去测试这个打包是不是正常。我们的遭遇是,一开始是用 2018.1.1 去开发,开发时都是正常的。再切换到 2018.1.9 直接打出来的 Rewird 就是正常的,大家也可以分享一下经验,也许有其他办法可以直接解决。

如果用两个版本,比如说我开发功能,可以去调试,像《梦蝶》游戏是 56G,每次开发版本要重新导入其他资源,如果你在 SSD 硬盘导入一遍遍工程需要一个多小时,完全接受不了这个时间,所以就可以加入一个 Cache Server,但是时间还是长一些,最后又想出了 Git,这种方式是最快的。

接下来是载入时间的问题,Switch 平台存储实际上是用的一种慢速的存储方式,像梦蝶这种的游戏,第一关载入时间大概在 90 秒左右,你可以做一些载入动画什么的,这个时间还是太长了,没有办法忍受,我们只做一个东西就变成了 30 秒。这里我要提一个非常有名的游戏——ICEY,这个在发布时我正好和他们在办公室聊天,就发现程序员一直在调试,他发现游戏启动时太慢了,整个游戏前 60 秒都是黑屏的,很难调试。其实我就突发奇想,要不改一下声音格式,他就切了一下,直接就从 60 秒变成了十几秒的载入时间,瞬间可以接受了。因为 ICEY 是有很多的语音声音文件,打包还是在文件夹底下的,所以要把所有都载入内存。这种方式对 Switch 有压力的平台有更好的优化方式。

我们还遇到一个问题,第一次播放声音时有一个卡顿延迟,但是反复播就没有了。我们通过将《梦蝶》这个游戏声音的加载改成流式加载就可以将加载时间从 90 秒减少到到 30 秒,用最小的事情产生最好的结果。还有一个 Wwise 可以把不同音效打在不同的 SoundBank 里面,还有一些共同的音效可以打在公共的 Bank 里面,可以通过这种方式再次减少游戏运行时的这种声音资源带来的压力。

接下来说一下包体尺寸的优化。Switch 并没有太大的要求,我们也是顺便优化一下包体,主要的优化方式是用 Console 和 Open Editor Log 来做的,你很难发现是不是打入包里了,有些资源觉得根本没用,会通过材质球还会进入包的安装部分。所以通过这个东西完全清楚看到哪些在包里,哪些是不在包的,肯定要把包里的东西进行重点优化。像 Switch 平台是支持 ETC2 和 ASTC 这种模式的,会很快速载入的。你在压缩会产生非常大的压缩率。你找到纹理之后去覆盖平台设置,你可以切换不同压缩格式,压缩格式也不是越小越好,因为压缩的纹理是有显示效果的损失。

大家要平衡最终的显示效果和包体体积的关系,还有一个注意的东西就是你如果烘焙了,你可以对平台单独设置,这样可以大幅度减少包体容量,这些东西也可以很明显察觉到阴影的显示变化,你需要考虑在体积跟质量之间获得平衡。其实 Switch 的掌机平台是比较低的,下降一些不会有太大变化。

还有一个是比较容易忘掉的,Mip Maps,这个在后期迭代时会把贴图做得比较大,会做 1024*512 这种模式,如果把 Mip Maps 勾掉的话会有很多能量,所以不会产生实际上的效果。

这是我们一个 Buill Report,第一步是按照排序来的(英文),这个整体看下来打包之后是 1.8G,这个不是实际打包的,你看 Android 打包出来容量是这个,在里面还会继续压缩。像 Switch 压缩打包结果应该在 1.2G 左右,后续还会有一个打包压缩,在机器上就会占到 1.8G 的容量。

排第一的是 60Mb、40Mb、25Mb,我们并没有进行太多处理。第二位是 otf,支持多语言的,你要有特殊字体放进去,每个字体都有容量,针对中国,不支持多语言切换的话都可以删掉。第三,Fbx 文件,里面有很多动画,都是比较大的。

最后说一下 Levels,《梦蝶》场景里有很多 Mesh,它的存储不会占用太多的地方。为什么需要优化呢?你就算切换到静态模式的话,静态合批会被动态物体打断,你在 Framedebugger 里面可以看到是被打成一段一段的。这个 DrawCall 数非常高,对 CPU 压力非常大,这个东西在 PC 是几乎没有影响的,在 Switch 平台和移动平台压力是非常大的。

我们做了一个合并工作,就是烘焙工作,我们通过第三方工具来做的,叫做 MeshBaker,但是真的是非常有效果。你可以把想合并的静态的 Mesh 选入进去,在工具里去设定每个球的半径大小,这个球半径包含的都可以形成一个簇,可以通过 MeshBaker 自动合并。为什么合并呢?因为在运行前就已经处理好了,再有一个就是说遮挡剔除功能,在摄像机渲染上是可以直接拿掉的,这个可以极大的提高渲染性能,这是合并 Mesh 的目的。合并 Mesh 之后有一个结果可以让场景变得非常大。大家可以想象一个石头大概有 100 面,我这个场景里面石头块有 1000 个,我分的时候板这一块地方一共会有 50 个物体,会合成一个,合成一个之后原来 Mesh 的就不用了,就单独形成了一个顶点数新的模型,存储容量会大幅度提升,会变得非常大。为了提高渲染性能,为了整体的结果,你肯定是要丢失一些东西。在纹理压缩上做了很大处理,让出了很多空间。纹理从一开始,没有优化之前,就包括所有的 Levels 加起来有 2G 多。大家一定要记住这个东西,这是非常非常大的减少包体的办法。

提升渲染性能。大家玩的 3D 游戏多了之后只认为显卡对游戏性能比较大,我问过很多开发者,其实项目一开始优化时,CPU 跑不动带来的结果几乎都是百分之百的。一般都不会去考虑 CPU 问题。它有一个单独的工具,叫做 NxGraphicDebugger,这个使用起来和他们差不多。我们通过自己的努力优化,没有针对游戏有改动,可以从 Switch 平台优化起来,我可以跟大家分享一个经验,Unity 打包出来的程序,如果使用 Standard Shader,在 Switch 平台到底能运行几个 Cube?就在动态物体,不是静态物体,最后测下来只能运行 6 个,超过 6 个之后就不能稳定在 60 帧了。所以大家在 Switch,在掌机模式下也不用求 60 帧,我觉得 30 帧就已经不错了。

看一个视频(编者:此视频暂无),这是在 2018 年 6 月 9 日运行的,这是《梦蝶》游戏第一次在运行。在这个时间之前大概经历了一个星期的时间,当时根本运行不了,每次都是闪退。你使用第三方插件时,一定要先把插件关上,看看游戏到底能不能运行,有没有问题,我们一开始闪退花了 3-4 天,是发现插件的原因,而且第三方引擎库输出是非常非常少的,其实是完全一个瞎调试的状态。后来通过项目经验开始关东西,最后排除发现是第三方插件的问题,就可以折半查找,关掉之后看有没有问题用快速查找来看有没有问题。

这是在一个星期之后,还是这个场景,大家看到全功能已经跑起来了,已经可以稳定在 30 帧以上了,就是这么一个状态。这个过程之中经历了太多太多的调试和处理,最后再经过大概一个月的时间,我后来后来安排了程序员做全职工作,后来整个《梦蝶》每个场景都可以稳定在 30 帧以上,有一些东西其实再说一下经验。比如说 Switch 可以归为移动平台,经过我们调试,像后处理的屏幕 AO 等占用都是比较大的,最后一定要想替代方案。

我的分享就结束了,谢谢大家。大家如果有什么技术上的问题,可以邮件找我,咱们一起切磋,一起交流,谢谢大家。