奇怪的“口吃”在不同 Android 设备上的 box2D 中

发布于 2025-01-05 11:50:35 字数 817 浏览 0 评论 0原文

我正在用 C++ 同时开发引擎和游戏,并使用 box2D 作为物理后端。我正在不同的 Android 设备上进行测试,在三分之二的设备上,游戏运行良好,物理效果也很好。然而,在我的 Galaxy Tab 10.1 上,我偶尔会遇到某种“口吃”的情况。以下是演示的 YouTube 视频:

http://www.youtube.com/watch?v=DSbd8vX9FC0

运行游戏的第一台设备是 Xperia Play...第二台设备是 Galaxy Tab 10.1。不用说,Galaxy Tab 的硬件比 Xperia Play 好得多,但 Box2D 会以随机间隔、随机时间长度出现滞后。两台机器的代码完全相同。此外,引擎/游戏的其余部分实际上并不滞后。自始至终,它都以稳定的 60 fps 运行。因此,这种“口吃”似乎是实际从 box2D 读取值时出现的某种延迟或故障。

您看到移动的精灵会在渲染时检查它们是否具有附加的物理主体,并根据物理主体的世界位置设置其位置值。因此,在这个特定过程中,box2D 似乎与应用程序的其余部分不同步。很奇怪。我意识到这是一个渺茫的机会,但我想无论如何我都会将其发布在这里,看看是否有人有想法......因为我完全被难住了。感谢您提前提供任何意见!

哦,PS 我使用固定时间步长,因为这似乎是此类问题最常建议的解决方案。当我在桌面上开发这个程序时,我转向了固定时间步骤,我遇到了类似的问题,只是更严重,固定步骤就是解决方案。也正如我所说,游戏稳定地以 60 fps 运行,这是由低延迟计时器控制的,所以我怀疑简单的延迟就是问题所在。再次感谢!

I'm developing an engine and a game at the same time in C++ and I'm using box2D for the physics back end. I'm testing on different android devices and on 2 out of 3 devices, the game runs fine and so do the physics. However, on my galaxy tab 10.1 I'm sporadically getting a sort of "stutter". Here is a youtube video demonstrating:

http://www.youtube.com/watch?v=DSbd8vX9FC0

The first device the game is running on is an Xperia Play... the second device is a Galaxy Tab 10.1. Needless to say the Galaxy tab has much better hardware than the Xperia Play, yet Box2D is lagging at random intervals for random lengths of time. The code for both machines is exactly the same. Also, the rest of the engine/game is not actually lagging. The entire time, it's running at solid 60 fps. So this "stuttering" seems to be some kind of delay or glitch in actually reading values from box2D.

The sprites you see moving check to see if they have an attached physical body at render time and set their positional values based on the world position of the physical body. So it seems to be in this specific process that box2D is seemingly out of sync with the rest of the application. Quite odd. I realize it's a long shot but I figured I'd post it here anyway to see if anyone had ideas... since I'm totally stumped. Thanks for any input in advance!

Oh, P.S. I am using a fixed time step since that seems to be the most commonly suggested solution for things like this. I moved to a fixed time step while developing this on my desktop, I ran into a similar issue just more severe and the fixed step was the solution. Also like I said the game is running steady at 60 fps, which is controlled by a low latency timer so I doubt simple lag is the issue. Thanks again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苦妄 2025-01-12 11:50:35

正如我在这里的评论中提到的,这归结为计时器分辨率问题。我正在使用一个计时器类,它应该访问跨平台的最高分辨率系统计时器。一切都运行良好,除了 Android 之外,有些版本可以运行,有些版本则不能。 Galaxy Tab 10.1 就是这样的例子。

我最终重写了 getSystemTime() 方法,以使用 C++11 中新增的一个名为 std::chrono::high_resolution_clock 的方法。这也很有效(除了 Android 之外的任何地方)...除了它尚未在任何 Android NDK 中实现。它应该在crystax NDK R7 的第5 版中实现,在本文发表时已完成80%。

我对访问系统时间的各种方法或可以在 NDK 端建立可靠计时器的方法进行了一些研究,但归根结底是并非所有平台都支持这些不同的方法。我经历了从头开始编写自己的引擎的痛苦过程,只是为了支持每个版本的android,所以把赌注押在实现不一致的方法上是没有意义的。

在我看来,对于任何面临此问题的人来说,唯一明智的解决方案就是放弃在 NDK 端实现此类代码的想法。我将在 Java 端执行此操作,因为到目前为止,在我的所有测试中,这在我测试过的所有设备上都足够可靠。有关更多信息,请访问:

http:// /www.codeproject.com/Articles/189515/Androng-a-Pong-clone-for-Android#Gettinghigh-sensitivetimingfromAndroid7

更新

我现在已经实现了我提出的解决方案,在java端进行计时并且它已经起作用了。我还发现,在 NDK 端处理任何相对较大的数字,无论数据类型如何(例如调用单调时钟的纳秒数),也会导致某些版本的 android 上出现严重滞后。因此,我通过传递指向系统时间的指针来尽可能地优化它,以确保我们不会传递副本。

最后一件事是,我关于从 NDK 端调用单调时钟不可靠的说法似乎是错误的。从 System.nanoTime() 上的 Android 底座,

...和 ​​System.nanoTime()。这个时钟保证是单调的,
是通用间隔计时的推荐基础
用户界面事件、性能测量和其他任何内容
不需要测量设备睡眠期间经过的时间。

因此,如果这是可信的,那么调用时钟是可靠的,但正如前面提到的,还会出现其他问题,例如处理分配和转储导致的大量数字,仅此一项就几乎将我在 Galaxy 上的帧率降低了一半Android 3.2 的选项卡 10.1。 最终结论: 平等地支持所有 Android 设备要么几乎是不可能的,要么根本不可能,而使用本机代码似乎会让情况变得更糟

As I mentioned in the comments here, this came down to being a timer resolution issue. I was using a timer class which was supposed to access the highest resolution system timer, cross platform. Everything worked great, except when it came to Android, some versions worked and some versions it did not. The galaxy tab 10.1 was one such case.

I ended up re-writing my getSystemTime() method to use a new addition to C++11 called std::chrono::high_resolution_clock. This also worked great (everywhere but Android)... except it has yet to be implemented in any NDK for android. It is supposed to be implemented in version 5 of the crystax NDK R7, which at the time of this post is 80% complete.

I did some research into various methods of accessing the system time or something by which I could base a reliable timer on the NDK side, but what it comes down to is that these various methods are not supported on all platforms. I've went through the painful process of writing my own engine from scratch simply so that I could support every version of android, so betting on methods that are inconsistently implemented is nonsensical.

The only sensible solution for anyone facing this problem, in my opinion, is to simply abandon the idea of implementing such code on the NDK side. I'm going to do this on the Java end instead, since thus far in all my tests this has been sufficiently reliable across all devices that I've tested on. More on that here:

http://www.codeproject.com/Articles/189515/Androng-a-Pong-clone-for-Android#Gettinghigh-resolutiontimingfromAndroid7

Update

I have now implemented my proposed solution, to do timing on the java side and it has worked. I also discovered that handling any relatively large number, regardless of data type (a number such as the nano seconds from calling the monotonic clock) in the NDK side also results in serious lagging on some versions of android. As such I've optimized this as much as possible by passing around a pointer to the system time, to ensure we're not passing-by-copy.

One last thing too, my statement that calling the monotonic clock from the NDK side is unreliable is however, it would seem, false. From the Android docks on System.nanoTime(),

...and System.nanoTime(). This clock is guaranteed to be monotonic,
and is the recommended basis for the general purpose interval timing
of user interface events, performance measurements, and anything else
that does not need to measure elapsed time during device sleep.

So it would seem, if this can be trusted, that calling the clock is reliable, but as mentioned there are other issues that then arise, like handling allocating and dumping the massive number that results which alone nearly cut my framerate in half on the Galaxy Tab 10.1 with Android 3.2. Ultimate conclusion: supporting all android devices equally is either damn near or flat out impossible and using native code seems to make it worse.

二智少女 2025-01-12 11:50:35

我对游戏开发非常陌生,而您似乎更有经验,这样问可能很愚蠢,但是您是否使用增量时间来更新您的世界?尽管你说你的帧速率恒定为 60 fps,但也许你的帧计数器计算出了错误,当 FPS 较低时,你应该使用增量时间跳过一些帧,或者你的世界似乎“留在后面”。我很确定您对此很熟悉,但我认为这里有一个很好的例子: DeltaTimeExample 虽然它是一个 C 实现。如果您需要,我可以粘贴我的 Android 项目中的一些代码,说明我如何使用增量时间,这些代码是我按照本书开发的: 开始 Android 游戏

I am very new to game development, and you seem a lot more experienced and it may be silly to ask, but are you using delta time to update your world? Altough you say you have a constant frame rate of 60 fps, maybe your frame counter calculates something wrong, and you should use delta time to skip some frames when the FPS is low, or your world seem to "stay behind". I am pretty sure that you are familiar with this, but I think a good example is here : DeltaTimeExample altough it is a C implementation. If you need I can paste some code from my Android Projects of how I use delta time, that I've developed following this book : Beginning Android Games.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文