【译】在 Unity 开发 Android 游戏时如何追踪性能问题

发表于2016-01-06
评论2 1.3k浏览
原文地址:http://www.codeandux.com/tackling-performance-issues-in-unity-for-mobiles/
原文作者未做版权声明,视为共享知识产权进入公共领域,自动获得授权

前言

几个星期前我试着用 Unity Android 开发一个游戏:Sky Blocks。这个游戏已经放到了 Google Play 上,如果有时间的话你可以试着下一下。

在开发这个游戏的过程中我遇到的问题几乎都是关于性能的问题。我将先试着讲解一下这个游戏机制,在介绍是什么引起了性能的问题和我是怎么解决这个问题的。


Sky Blocks 游戏的机制

Sky Blocks 是一个颠倒的俄罗斯方块和太空大战混合的游戏。游戏的玩法是将方块放置成一条线,然后这些线会移动到游戏面板的顶端,但是不像在俄罗斯方块那样线会完全的消失。你有60秒的时间去创建尽可能多的线,当时间结束时,UFO 就开始入侵地球,先摧毁你创建所有的线,如果它们成功的穿过了你的防御,然后开始攻击地球,当地球的生命值为0时游戏结束。

是不是听起来很简单,然而开发起来却操碎了心。但是却很有趣,非常有趣。


不要忘记做设计

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

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

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

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

 

不要忘记做设计

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

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

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

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

 

不要忘记做设计

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

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

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


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

 

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

下面这张图片是优化后的截屏,但它也只能是张图,你可以通过这张图片了解我的游戏。
活动块调用了一次绘图指令,参考(Batches: 20 或者 SetPass calls)。就像我前面所说的,以前每个块包包含 4-5 个独立的立方体并且每个都含有素材引用。因此正如你看到的每个块本身都要通过至少四次才能创建出来。

 

而现在在顶端的两个被锁定的块,我们仅仅使用了一次额外的绘图调用。而这些块还是活动块时, 都是由原始的立方体组成并且每个立方体至少要经过一次处理才能创建出来。

防御线使用相同的模式,但是这里只有 10 个原始的使用顶点颜色和共享素材的四方体。实际上,在这里我们不需要在一个网格里绘制完整的防御线,Unity 帮我们自动的将完整的防御线添加到通过批处理保存

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引