复用,UIScrollView Item复用,避免频繁创建销毁对象
缓存,例如Transform
运算裁剪,例如碰撞检测裁剪
粗略碰撞检测(划分空间——二分/四叉树/八叉树/网格等,降低碰撞检测的数量)
精确碰撞检测(检查候选碰撞结果,进而确定对象是否真实发生碰撞)
休眠机制:避免模拟静止的球
逻辑帧与渲染帧分离
分帧处理
异步/多线程处理
6.3GPU:最佳原则减少渲染
纹理压缩
批处理减少DrawCall(unity-Static Batching和Dynamic Batching,cocos SpriteBatchNode)
减少无效/不必要绘制:屏幕外的裁剪,Flash脏矩阵算法,
LOD/特效分档
NGUI动静分离(UIPanel.LateUpdate的消耗)
控制角色骨骼数、模型面数/顶点数
降帧,并非所有场景都需要60帧(腾讯桌球游戏场景60帧,其他场景30帧;天天酷跑,在开始游戏前,FPS被限制为30,游戏开始之后FPS才为60。天天飞车的FPS为30,但是当用户一段时间不点击界面后,FPS自动降)
6.4内存:最佳原则减少内存分配/碎片、及时释放
纹理压缩-Android ETC1、iOS PVRTC 4bpp、windows DXT5
对象池-PoolManager
合并空闲图集
UI九宫格
删除不用的脚本(也会占用内存)
6.5IO:最佳原则减少/异步io
资源异步/多线程加载
预加载
文件压缩
合理规划资源合并打包,并非texturepacker打包成大图集一定好,会增加文件io时间
6.6网络:其实也是IO的一种
使用单线程——共用UI线程,通过事件/UI循环驱动;还是多线程——单独的网络线程?
单线程:由游戏循环(事件)驱动,单线程模式比使用多线程模式开发、维护简单很多,但是性能比多线程要差一些,所以在网络IO的时候,需要注意别阻塞到游戏循环。说明,如果网络IO不复杂的情况下,推荐使用该模式。
在UI线程中,别调用可能阻塞的网络函数,优先考虑非阻塞IO
这是网络开发者经常犯的错误之一。比如:做一个简单如 gethostbyname() 的调用,这个操作在小范围中不会存在任何问题,但是在有些情况中现实世界的玩家却会因此阻塞数分钟之久!如果你在 GUI 线程中调用这样一个函数,对于用户来说,在函数阻塞时,GUI 一直都处于 frozen 或者 hanged 状态,这从用户体验的角度是绝对不允许的。
多线程:单独的网络线程,使用独立的网络线程有一个非常明显的好处,主线程可以将脏活、累活交给网络线程做使得UI更流畅,例如消息的编解码、加解密工作,这些都是非常耗时的。但是使用多线程,给开发和维护带来一定成本,并且如果没有一定的经验写出来的网络库不那么稳定,容易出错,甚至导致游戏崩溃。下面是几点注意事项:
千万千万别在网络线程中,回调主线程(UI线程)的回调函数。而是网络线程将数据准备好,让主线程主动去取,亦或者说网络线程将网络数据作为一个事件驱动主线程去取。当年我在用Cocos2d-x + Lua做魔法花园的手机demo时,就采用的多线程模式,最初在网络线程直接调用主线程回调函数,经常会导致莫名其妙的Crash。因为网络线程中没有渲染所必须的opengl上下文,会导致渲染出问题而Crash。
6.6包大小
使用压缩格式的纹理/音频
尽量不要使用System.Xml而使用较小的Mono.Xml
启用Stripping来减小库的大小
Unity strip level(strip by byte code)
Unity3D输出APK,取消X86架构
iOS Xcode strip开启
6.7耗电
下面影响耗电的几个因素和影响度摘自公司内部的一篇文章。
7.异常与Crash
7.1防御式编程
非法的输入中保护你的程序
检查每一输入参数
检查来自外部的数据/资源
断言
错误处理
隔栏
防不胜防,不管如何防御总有失手的时候,这就需要异常捕获和上报。
7.2异常捕获
异常捕获已经有很多第三组件可供接入,这里不介绍组件的而接入,而是简单谈一下异常捕获的原理。