这里主要说的是opengles用于2D时的优化,但优化的方法也适用于3D
1. 基本的优化和注意点
http://www.linuxgraphics.cn/android/write_real_time_for_android.html 这篇文章是google员工写的,其中提到一些基本的java游戏编写的影响效率的因素,总结起来就是 1) 不要在游戏交互过程中分配内存,尽量预先分配好. 像写C一样写java(其实没那么严重) 2) 少点函数调用(java的关系不是很大), gl.gl**这类的函数会调到jni,会比较耗时.
2. 单线程, 双线程?
内置的GLSurfaceView会创建一个新的线程来更新场景及编制场景(同时还要处理主线程响应的一些事件). 很多开源的引擎用的是双线程(除主线程之外), 一个用来算场景及物理模型(物理线程), 一个用来绘制. 你就要问了,这样有道理吗? 一般手机只有一个CPU, 实际多线程是分时的, 分多个线程还有线程之间的context switch 上的消耗. 嗯,这主要是因为opengl的绘制是异步的, 当调用glDraw*及其它gles函数,它们会比较快的返回,但真正的绘制发生在 eglSwapBuffer()时, 所以在eglSwapBuffers时绘制线程会花很多时间等待gles的渲染结束. 所以,正解是用两个线程会快, 而且用得好的话,会快很多很多.
3. glDrawTexfOES? 不
glDrawTexfOES 这个看上去很方便的函数是一切邪恶的根源. 当你要画50个贴图时,这个是方便的选择. 但是当时要画200个时, 这个函数就恶梦. 正解是什么? glDrawElements. 这个函数好处是可以减少对gl**函数的调用,极大的提高渲染效率. 当然,为此,你需要做好多事啦. 像贴图要做成Atlas,尽量把多个贴图放在一个texture中, 像把各个图形放在一个数组中. 这些工作多是一劳永逸, 在写引擎时要多考虑一些,之后这些细节都 被封装起来.
4. 屏幕mouse事件造成系统lag
这是我无法解决的问题,google groups 上很多人讨论,基本上认为是系统的一个不好的实现. 这个问题没法解决,但是双线程游戏引擎的框架却很好的绕过一部分的问题. 处理touch 事件 主要影响绘制线程和物理线程. 在双线程模型中,点绘制线程调用eglSwapBuffer时,物理线程利用这段"漫长的时间"进行计算,如果有很多mouse事件,会造成物理线程计算耗时多. 但一般来说,算物理及场景会比较快,即使受到mouse事件景响,也不会太慢. 这样,只要在eglSwapBuffer完成之前完成物理及场景, mouse事件对物理线程的影响就是0. 那么物理事件只能对绘制线程产生影响了,这样整体来说mouse事件的影响变小了. 在G2上不停产生touch 事件, 300三角面 45 fps以上是没有问题的.
5. 好多游戏引擎,我用哪个
这是与优化无关的问题,但有很多开源的游戏引擎可选,用哪个呢. 多数开源游戏引擎看上去很美, 用起来有这样那样的问题和bug. 我不赞成重造车轮,但这个问题上,我赞成参考别人的引擎来完成自己的引擎(主要参考设计,效率方面还是要自己实践). 我实际运行过的引擎是Rokon感觉效率一般, 离商业差得有点远(设计的还靠谱,好像是一个外国的博士生写的). 看过一些AndEngine及libgdx,感觉libgdx是有积累的,代码的效率比较高,还有很多jni直接可以参考, 非常不错. 另一个引擎是coco2d_android,没太深入了解.
总之, java是能写出很快的游戏啦.