我正在用C ++同时开发一个引擎和一个游戏,我正在使用box2D作为物理后端。我正在测试不同的Android设备和3个设备中的2个,游戏运行良好,物理也是如此。然而,在我的Galaxy tab 10.1上,我偶尔会得到一种“口吃”。这是一个YouTube视频演示:
http://www.youtube.com/watch?v=DSbd8vX9FC0
游戏运行的第一个设备是Xperia Play ......第二个设备是Galaxy Tab 10.1。毋庸置疑,Galaxy标签的硬件要比Xperia Play好得多,但Box2D在随机时间长度内随机间隔滞后。两台机器的代码完全相同。此外,引擎/游戏的其余部分实际上并不落后。整个时间,它以60 fps的速度运行。所以这种“口吃”似乎是从box2D实际读取值的某种延迟或故障。
您看到的精灵会在渲染时检查它们是否有附着的物体,并根据物理身体的世界位置设置它们的位置值。因此,似乎在这个特定的过程中,box2D似乎与应用程序的其余部分不同步。很奇怪。我意识到这是一个很长的镜头,但我想我会在这里发布它,看看是否有人有想法...因为我完全被难倒了。感谢您提前输入任何内容!
哦,P.S。我正在使用一个固定的时间步骤,因为这似乎是这类事情最常建议的解决方案。我在桌面上开发这个时移动到一个固定的时间步骤,我遇到了类似的问题,更严重,固定步骤是解决方案。也像我说的那样游戏稳定运行在60 fps,由低延迟计时器控制,所以我怀疑简单滞后是个问题。再次感谢!
答案 0 :(得分:2)
正如我在这里的评论中所提到的,这归结为计时器解决问题。我正在使用一个计时器类,它应该访问最高分辨率的系统计时器,跨平台。一切都运行得很好,除了它来到Android,一些版本工作,一些版本没有。星系标签10.1就是这样一种情况。
我最终重新编写了getSystemTime()
方法,以使用名为std::chrono::high_resolution_clock
的C ++ 11新增功能。这也很好(除了Android之外)......除了它还没有在任何NDK for android中实现。它应该在crystax NDK R7的第5版中实现,该文章在本文发布时已完成80%。
我对访问系统时间的各种方法进行了一些研究,或者我可以在NDK端建立可靠的计时器,但归结为所有平台都不支持这些不同的方法。我经历了从头开始编写自己的引擎的痛苦过程,因此我可以支持每个版本的android,所以投注不一致实现的方法是荒谬的。
在我看来,面对这个问题的任何人唯一明智的解决方案就是放弃在NDK方面实施此类代码的想法。我将在Java端执行此操作,因为到目前为止,在我的所有测试中,这已经在我测试过的所有设备上足够可靠。更多相关内容:
<强>更新强>
我现在已经实现了我提出的解决方案,在java方面进行计时并且它已经工作了。我还发现,在NDK方面处理任何相对较大的数字,无论数据类型(调用单调时钟的纳秒数)都会导致某些版本的android严重滞后。因此,我通过传递指向系统时间的指针尽可能地优化了这一点,以确保我们不是通过复制。
最后一件事,我的说法是从NDK方面调用单调时钟是不可靠的,但是看起来似乎是错误的。来自System.nanoTime()上的Android停靠栏,
...和System.nanoTime()。这个时钟保证是单调的, 并且是通用间隔时间的推荐基础 用户界面事件,性能测量和其他任何事情 这不需要测量设备睡眠期间的经过时间。
所以看起来,如果这可以信任,那么调用时钟是可靠的,但是正如所提到的那样还会出现其他问题,例如处理分配和转储大量的数据,结果这几乎将我的帧速率降低了一半使用Android 3.2在Galaxy Tab 10.1上。 最终结论: 同样支持所有Android设备无论是接近还是完全不可能,使用本机代码似乎会让情况变得更糟。
答案 1 :(得分:1)
我对游戏开发非常陌生,而且你似乎经验丰富,问题可能很愚蠢,但是你使用delta time
来更新你的世界吗?虽然你说你有60 fps的恒定帧速率,但是你的帧计数器可能计算出错误,你应该使用delta time
在FPS低时跳过一些帧,或者你的世界似乎“留下来”。我很确定你对此很熟悉,但我认为这是一个很好的例子:DeltaTimeExample尽管它是一个C实现。如果您需要,我可以从我的Android项目中粘贴我使用增量时间的一些代码,这是我在本书后面开发的:Beginning Android Games。