无法解决的奇怪卡顿问题(包含完整源代码)

9
我基于月球着陆器的例子制作了我的游戏,自从开始制作以来就一直存在卡顿问题。我尝试过的所有方法都没有解决这个问题,所以我花了几个小时创建了一个简化版的月球着陆器示例,并放置了一个简单的滚动图片来展示卡顿情况。注意:这与垃圾回收器无关。如果你认为是这个原因,请查看日志,垃圾回收器运行的次数远不及卡顿出现的频率。
在我的手机上(摩托罗拉Milestone,2.2),屏幕上滚动的图片每秒会卡顿大约1/10秒。这种卡顿并不能完全破坏游戏体验,但它非常令人分心和沮丧。我的游戏还涉及大量快速滚动和快速移动,因此通常更容易察觉到卡顿。
如果你们中有人有时间,能否快速查看这个Eclipse项目并看看:
1. 在你的手机上是否会卡顿(仔细观察滚动时,每半秒到一秒半就会有一个小卡顿); 2. 是否可以找到任何解决卡顿的方法。
我希望只是我的某行代码导致了整个问题,而我却没有意识到。我只是不敢相信,即使剥离了这么多内容,它仍然与我的完整游戏中的1000个对象具有完全相同数量的卡顿,特别是因为它在我的手机上以稳定的60fps运行。
编辑:已在Traceview上对我的游戏进行了分析,看起来没问题。
源代码下载链接:http://dl.dropbox.com/u/4972001/LunarLander.rar

2
你尝试使用Traceview对游戏进行分析了吗?http://developer.android.com/guide/developing/tools/traceview.html - bigstones
1
是的,我有看过,看起来没问题——甚至在每个“updatePhysics”调用之间都有间隔,我也看不到任何没有调用的异常间隔。 - Smills
1
我不确定是不是我的问题,但我认为在LG Optimus One 2.2上有一个几乎不可察觉的口吃。 - bigstones
1
感谢您测试它,bigstones。我在测试每个手机时都会遇到几乎不可察觉的口吃问题(我刚刚自己在另一部手机上测试了一下)。有人知道如何消除这个问题吗? - Smills
我偶然发现了这个,不确定它是否相关:https://dev59.com/mVTTa4cB1Zd3GeqPq0nq - bigstones
4个回答

1

我在我的手机上(nexus one)尝试了一下,对我来说也是一样的。

我做了一些改变,让它对我来说更好:

  1. 在循环期间,不要每次声明新变量,而是将其声明为类的属性

    Canvas c = null; // 变成

    private Canvas c;

    // 现在只需在循环中使用

    c = null

对于您在doDraw和updatePhysics函数中反复声明的所有变量都要这样做。

  1. 不要一直增加viewY的值,只需添加一个简单的if语句

    如果(viewY > mCanvasHeight){

      viewY -= mCanvasHeight;   
    

    }

我不确定它现在是否百分之百有效,但对我来说看起来要好得多。


啊,我已经尝试过了,似乎确实使其更加流畅,但是遗憾的是在我的手机上仍然会卡顿。我设法在朋友的Desire HD上尝试了一下,他的手机运行非常流畅。这只影响某些设备,有点奇怪。 - Smills
这个改变对任何事情产生影响的可能性有多大?我怀疑这个代码改变会带来任何真正的差异,我认为你认为它现在更加流畅只是心理作用。@Smills:Desire HD比Milestone强大得多。Milestone在游戏方面似乎比大多数新手机慢得多。我注意到我的卡顿Milestone应用程序在新手机上非常流畅。 - rbcc

0

你每帧都在绘制三个巨大的背景位图...这比你需要做的工作还要多。使用BitmapShader并将TileMode设置为repeat可能会更好。然后只需调用一次本地层。

在某个地方添加一个Paint paint;成员,并将setSurfaceSize()更改为包括以下行:

BitmapShader shader = new BitmapShader(mBackgroundImage, 
    TileMode.CLAMP, TileMode.REPEAT);
paint = new Paint();
paint.setShader(shader);

那么doDraw()只需要这样:

//translate to viewY position
canvas.translate(0,(float)(-viewY));

//draw backgrounds
canvas.drawPaint(paint);

我实际上没有测量过这个来证明它更快,但从我对图形API的了解来看,它肯定应该更快。

(当然,如果你真的想要飞行,你应该使用OpenGL ES...)


0

听起来你的滚动生成了很多需要频繁回收的垃圾。如果你创建了许多短期小对象,请考虑管理自己的对象池。只要不让对象池无限增长,这可以大大减少GC占用你的时间。


1
开始时有这部分内容:“注意:它与垃圾回收器无关。如果您认为它是,请查看日志,垃圾收集器运行的频率远不如口吃出现的频率。” 不过这是个好建议,我实际上在原始问题中也假设了同样的问题,并提出了同样的解决方案。http://stackoverflow.com/questions/4867732/traceview-shows-some-methods-arent-being-called-for-200ms-or-more/ - Roy T.
1
是的,不幸的是它似乎不是垃圾收集器,如果是的话那就很好解决了。如果你看一下我的例子,我已经消除了所有在运行时生成垃圾的调用(或者至少几乎所有)。 - Smills

0
我在Verizon DroidX(2.2.1)上进行了测试,似乎每3-6秒就会出现非常短暂的卡顿。关闭活动壁纸并停止其他运行的应用程序后,情况似乎稍微好一些。也许是图形子系统跟不上?您是否尝试过使用像素更少、颜色更少的图像来减轻图形负担,以查看其效果?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接