如何优化手机游戏,是一件很难说明的事。不论你从本文学到了什么,都是没有意义的,除非你遇到了相同的问题。很不幸,iOS和android设备都很脆弱, 所以你必须成为更强的开发者。从程序开发周期之初就要不停优化,参考下面的经验以免重蹈覆辙。
优化游戏一半是经验一半是艺术。你必须学会各操作的快捷键及可选方式,包括导入、unity行为、以及所写的每行代码。如果你发现游戏在老的iPhone或Android设备上运行太慢,本文能给出一些解决之道。我的切身例子是ROAR!。这是我第一次认真优化的游戏,原因是Vuforia AR插件占用了设备的大部分资源。:)
• 选择合适的开发设备
越慢越好,但是别过头。如果选的设备太慢,可能会降低你的效率,使你过早开始优化,可能那时还不需要优化。我相信适当折中,一定能找到最佳方案。
• 优化游戏包大小
有时你的游戏会无缘无故的占用很大空间。控制游戏大小很重要,这会直接影响到有多少用户来下载你的游戏。另外一定要注意的是,用户需要卸载游戏时,通常会从大的开始。这是生存法则:)
• 压缩纹理和音频文件
构建游戏,然后检查编辑器日志,找出那些占用太多空间的文件。大部分情况下,不是纹理就是音频文件。纹理应该是正方形的,并且大小是2的整数次幂(POT),这样便于压缩,大小在1024*1024左右,最好不要超过2048。音频文件应该总是压缩了的,除非声音特别短,而压缩会破坏它的音质(很少有这种情况)。
• 打包精灵(sprite)
尽可能打包UI和游戏中的所有精灵。在Unity 5中,Sprite Packer是免费的,也可使用其它工具如NGUI。就Sprite Packer而言,它可以将图片打包成图集,这是使精灵不受2的整数次幂(POT)限制的好方法。只要设置了Packing Tag,Unity会替你处理其他所有事,简单地节省大量空间。
• 启用mscorlib级别的剥离
要在项目(以及使用的插件)允许的情况下大胆启用剥离,从代码中剔除未使用的dll。很可能你的2D游戏并没使用太多Unity的特性,甚至没有使用物理模拟,但是它们占用了很大空间。
• 确保没有包含不必要的资源
如果你隐藏了场景中的游戏对象(GameObject),即使它从不显示,Unity构建工程时还是会将它引用的资源包含进来。清除层级面板中未使用的游戏对象,以及它们引用的资源。"Resources"文件夹的所有资源都会被引入游戏,所以务必要小心!
• 优化内存使用
随着操作系统的升级,它们使用的内存越来越多,而留给你的将会越来越少(没错,iOS,说的就是你)。明智的做法是,尽量减少加载到内存中的资源量。内存压力是你的应用被操作系统终结的最大原因。恩,随机崩溃也大多来源于内存崩溃。:)
• 巧妙地打包精灵
一旦游戏开始运行,文件都必须被解压,它们又会占用很大空间。但是,如果你前期工作做得好,精灵打包很合理,那还是能节省很多内存的。经验法则是,将同时出现的图打包在一起,尽量不要让图集留有大量空白。例如,应该将UI打包到一个独立的图集。在本例中,UI图集有大部分内容是不常见的,它应该被打包到另一个图集中去。差点忘了!使用九宫格精灵(9-sliced sprites),避免大背景图!(可以将它们设置为可拼贴模式,或者使用更简单的精灵)。禁用MIP maps。
• 降低图片和音频的质量
你确定你的角色需要1024的像素宽度?如果移动设备的分辨率是1024*768,我猜并不需要(除非它和整个场景一样大)。你的音乐循环有3分钟长?很可能它只有30秒。它很容易超过手机能够显示的最大品质。降低图像和音频质量,在手机上大部分人是感觉不到差别的。
• 小心应对场景引用
曾经有一次,我的应用使用了大量图片。根据选中的角色,我会从长列表中实例化一个预制(prefab)。让我惊讶的是,列表引用导致所有的预制(prefab)被加载到了内存,因而加载了所有的图片。这个故事告诉我们,性能分析从不说谎。
• 在必要时使用Resources文件夹
上一个例子的解决方法就是把所有的预制/资源(prefab/assets)放到Resources文件夹中,然后动态加载你需要的那一个。这种方法不如直接引用简便,因为你必须提供每个资源的路径,而且如果移动资源就会出错。但是我想你肯定能写一个编辑器脚本来处理这种小问题。:)
当你的应用被意外终止时,操作系统默默告诉你的就是这个。
• 优化CPU使用
游戏要么快,要么死。玩家通常能接受一定程度的平庸:糟糕的界面,糟糕的故事,糟糕的图片……任何事都能被原谅,除了糟糕的性能。你要知道你的极限,在这种情况下,通常要牺牲一切来保证像样的帧率。这是硬道理。
• 当心语法糖如:foreach循环
在Unity的CPU性能优化中,这是最常提到的建议。因为Unity使用的是旧版本的.NET框架,其中有很多东西并不那么高效。既然这不会马上改变,你就应该用“for”取代“foreach”循环,用“arrays”取代“lists”;)。更多官方的代码优化小贴士参考这里。还有面向对象(OOP)语言通用的代码实践,不要错过哦:)
• 隐藏调试日志
Unity处理字符串很慢,你应该尽量避免字符串操作。所以,在构建发布版本时,就不要开着那些"Debug.Log"。你会惊讶地发现,如此一件小事却能带来很大差异。
• 从底层到上层优化
优化游戏时应该用Profiler监控,这样就可以很清楚是哪些类导致运行缓慢。从游戏“底层”开始优化,因为会有其它类使用它们,例如人工智能(AI)或者寻路(Pathfinding)类。如果运气好的话,就不需要优化“顶层”了。
查找经典瓶颈,比如多层嵌套循环或者脚本多次实例化
假设你有一个脚本叫”PlayerController”,另一个叫"EnemyController”。如果在屏幕上同时有100个敌人,那为了更新不同的敌人,”PlayerContoller”可能会变慢100倍。所以,先优化"EnemyController”脚本。移除特别慢的调用如"FindObjectOfType”,它们是不能在Update中调用的。缓存变量,甚至单例类,可以提高性能。
可以通过深度性能分析跟踪那些很慢的方法,但是它本身也会影响性能! :/
祝你好运,记住,做个值得优化的好游戏!:D
这些并不是全部。需要时去看看Unity的小贴士和建议,那里还包括本文所忽略的内容。