使用 Unity 开发 Android 游戏时如何追踪性能问题

两周前我开始用 Unity 开发一个叫 SkyBlocks 的 Android 游戏。游戏已经在 Google Play 上架了,如果你有时间可以下载来玩一玩儿。

开发的过程中遇到的最大的问题就是性能问题。我开始慢慢尝试分析到底是什么导致的性能问题以及我该怎么解决它。

Sky Blocks 游戏机制

这个游戏(SkyBlocks)有点像倒过来的俄罗斯方块和太空入侵者的合体。游戏的玩法就是把方块摆成一行,这是这行方块就会移到游戏面板的最上方。但是这行方块不会像俄罗斯方块那样完全消失。你有60秒的时候来摆出行数尽可能多的方块。UFO 会入侵“地面”(游戏面板的下方),还会极力破坏你建好的一切东西。一旦它们穿过你的防御,就开始破坏地球,当地球血量到 0 的时候,游戏就结束了。
听起来简单,做出来难,但是非常有意思,有趣极了!

不要忘记做设计

重要的事情是永远不要忘记先做设计。当我开始开发 SkyBlocks 是我也不知道我想要做什么,我更不知道这个游戏应该是个什么样子, 但是我从没想过该怎么去处理这个问题。幸好我以前用 JavaScript 和 HTML5 做过俄罗斯方块,我仅仅通过复制粘贴,并且修改了一些小 BUG,像旋转时的碰撞检测的方式把这些写过的代码移植到 C# 而没有考虑从 2D 到 3D 的区别。

自从在每次更新的时候,我不再一次性的绘制整个游戏面板,我就不得不创建每一行到一个 GameObject 中,并且用创建的简单的立方体渲染在网格中已经被锁定的块。网格每次更新的时候我都得销毁所有的块,并且又从新创建这些块。对于我来说,我觉得这已经够好了,游戏在电脑上运行的还挺好的。

然而,我没考虑到的是,游戏面板(网格)有 10 行 20 列,这有可能要有 200 个立方体不停地渲染,销毁,重建。这还不是最坏的,如果有必要的话行数会变得更多。并且每个立方体也有它自己的引用资源这使得每个立方体都会调用一次绘图。 想象一下,铺满一个游戏面板大约需要 150 到 200 个块被渲染。这就需要大约调用 200 次绘图。

如果在我移植代码之前做了设计,我就知道这个游戏不能长时间的运行。如果在开始动手之前有这就有想法,我就不会浪费那么多时间了。

解决问题

解决问题的最好的办法是先勾勒出你的想法,然后再逐步深入。怎样让各个部分结合起来像一个整体一样的工作?这些不同的部分都做些什么?在 Sky Blocks 项目里,部分指的是游戏面板,防御线和 UFO。

游戏面板仅仅是为了控制游戏的,在游戏面板上有移动的块和已经被锁定的静止的块。而防御线仅仅是那10个立方体的静止的线。UFO 是一个可以移动到防御线上方的组合的网格。而抓住这些部分我就接近胜利了。

减少绘图调用次数

我在前面已经提到过,在这个游戏里我调用了太多次的绘图,我在我的 Android 机器上(a samsung galaxy s4)上测试我的游戏,随着功能的完善,我发现我的游戏运行的越来越慢,跟蜗牛一样。

为了让游戏运行的更好,减少绘图调用是一项重要的任务。我不得不在网上找答案。绘图调用消耗多少性能?是什么引起了绘图调用?怎样才能减少调用?

在性能的提升上,我设计不出一个好的实验方案,但是我找到了一个可以在 CPU 和 GPU 上都能运行的方案。虽然一些实验中性能上没有明显的区别,但是在我将游戏绑定到 FPS 上的大部分的实验会让游戏运行的缓慢一些

主要的原因是很容易发现的,是由于所有的立方体被分开使用素材渲染。

为了在游戏面板上减少绘图调用,我决定减少对象的数量和不同种素材的数量。

因此我试着实现了一个功能,这个功能在游戏面板上替换了以前可能分开的绘制200个立方体,而现在只需绘制一整块网格。然后我选择用顶点颜色替换了单色纹理。并且将素材着色器改变成我在网上找的无光源顶点颜色。现在我把游戏面板上多次的绘图调用变成仅仅一次。

对于防御线,我做了类似的事情,我把所有的素材修改成相同的无光源顶点颜色,但是我没有让它们作为一个网格来渲染,我沿用以前的每 10 个立方体一个防御线的策略,这是因为我已经把素材变成共享的了,这就可以把之前多次防御线的绘图调用变成一次调用。

不幸的是,由于我没对调整之前的游戏截屏,但是我又实在不想调整成以前的解决方案,因此不能向各位展示调整前后的区别。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/d00426951a2fe90b736e0a416a4f10a0.html