java - 2D 物理游戏性能问题(android 中的 libgdx box2d)

标签 java android performance libgdx box2d

我正在制作一个 2D 汽车游戏,比如赚到死 2。我几乎完成了它。唯一的问题是物理引擎性能。我正在使用 box2d 并且有 10 米长的边缘形状完全构建了 100 公里的地形。 1辆车,通常30-40箱。 Activity 动态体的数量约为 60-100,最大 120。游戏在桌面上流畅运行,但在 android 中,当 Activity 体超过 60 时,fps 下降到 30 以下。汽车与盒子和盒子之间以及盒子和汽车之间存在碰撞接地。

我使用 libgdx 框架 1.9.4 作为版本,java 是 1.7,使用 eclipse neon 编码,windows 7。

这就是我计算世界上活跃物体的方式

    int num=0;
    Array<Body> bodies=new Array<>();
    world.getBodies(bodies);
    for(Body b:bodies){
        if(b.isActive())num++;
    }

主动动态体通常在 100 个左右

这不是所有地形和地下网格的绘图问题,汽车和盒子的成本为 6-7 毫秒我在 box2d 调试渲染关闭时测量它们,当汽车有大约 30 个盒子时,世界步骤方法调用的成本约为 30 毫秒正在压入他们

我不加载所有游戏对象(现在是盒子)我将整个 map 分成 block map 大小为 100 公里,当汽车在接下来的 50 米(在 block 范围内)时 block 大小为 50 米我从准备好的池(这些对象的 box2d 世界表示也被池化,当盒子在池中时,我使用 setActive(false) 停用它们的 box2d 主体,并在 block 加载时返回 true)

我也将这个 block 系统应用于地形。我在游戏加载时加载所有地形,然后通过使用此方法 setActive(false) 设置来停用它们,如果 block 范围包括汽车的 x 轴坐标,则当汽车通过 map 时,我激活包含地形静态的下一个 block body 有大约 20 个大小为 10 米的固定装置,使 block 大小总计 200 米。

here an ss of the part of map to visualize my performance optimizing plan :)

绿线是 Activity 的地形形状,如您在一段距离被停用直到 map 结束后左右看到的那样,这部分来自大约 60 公里的 map ,位于 100 公里地形图的中间。

当车辆移动一点时,更多的新箱子将在前面装载,如果它们距离汽车 20 米,旧箱子将被汇集在一起​​。

我的问题是

1) 这个 fps (20 fps) 是否正常且符合预期?(android 7 这是手机规范 http://www.androidpolice.com/2016/02/23/the-general-mobile-gm-5-plus-is-the-most-powerful-android-one-device-yet/ )

2)100公里的地形会不会有问题,如果是我应该如何管理它?

->本地形体超出屏幕矩形时,我尝试激活/停用它们。

->我在一个主体上尝试了数百个固定装置,或者每个地形 block 都作为分离的主体,但我将 100 公里的地形分成 200 米的 block ,每个 block 都是一个主体,由大约 20 个固定装置组成。

3) 模拟 100 个具有巨大边缘形状地形的动态物体是完全不可能的? (但在赚到死时他们做到了)

4)我应该只为这种游戏(一个简单的特定游戏)编写自己的简单物理吗?

5)我应该使用子弹物理而不是 box2d 来实现 2D 目的吗?可能吗?我会面临性能问题吗?

如果您需要任何代码请评论,我会添加。

如果您建议更改 box2D ,是否有任何我在网上找不到的非常快速的物理引擎?

值得注意的是:

我正在模拟具有恒定时间步长的 box2d 我尝试了 1/60 1/45 1/30 和 8-3 , 6-
2 作为迭代步骤。

我对所有物体的线性和角度都使用高阻尼值,例如 0.9。

我也想把这些盒子分成几 block ,实际上我正在这样做,但是当汽车被压碎时没有分开下摆,我正在经历这个 fps 下降,所以我现在禁用它。

只有关节是车轮关节,用于汽车的车轮,在 map 的任何地方都没有关节。

这些盒子高 1.2 米,尺寸真实。

用于盒子和汽车的多边形形状用于地形边缘形状使用(链形状)

速度阈值在世界设置中默认为 1。

如果有任何笔记我忘记了,请发表评论,我会分享。

谢谢你。

最佳答案

免责声明:我无法回答您的所有问题,以下只是我的猜测。

几年前,我用Java + box2d + plain Opengl (LWJGL) 开发了一个游戏原型(prototype)和游戏库。

我想你正面临着我遇到的一些问题。

但是,以我的经验不足,我可能是错的。
如果专家(读者)认为我的帖子有任何错误,请在下方评论,我会修复。

我猜

Java 很慢/不太适合游戏。

免责声明:关于这一点有很多争论。
我不是专家,无法在这里发表一个可靠的声明,但我发现我的很多游戏原型(prototype)在 C++ 中的运行速度比 Java 快 3 到 10 倍。 (使用不太不同的算法)

内存 fragment

您可能已经知道,即使您使用 pool,它与 C++ 相比仍然很差。
你把盒子放在一起,但你不能把所有东西都放在一起,例如游戏逻辑数据结构、vector2D、普通数组(通常是 new[])、您使用的某些库中的一些恐怖算法。

停用的物体仍然会消耗内存(间接加剧内存 fragment )。

你有很多静态物体/静态物体的高度复杂性。

你没有提到你有多少静态体,它们是什么。
您是否为地形使用大量顶点形状?
流行的物理引擎,如 Box2D 和 Bullet,在凸形状方面很酷,在原始形状方面很熟练,但在凹形状方面往往效果不佳(例如,你的 terrian)

你的形状不断地相互碰撞。

例如,一堆 100 个盒子比散布在场景周围的 100 个盒子要花费更多的计算量。

世界太大

据我所知,box2d 将一个场景(世界)划分为一个网格。如果你的世界很大,但是很多 body 聚集在同一个网格单元格中,Box2D 的效果会相对较差。

它不仅限于 Box2D。
Bullet 和 Ogre3D - 在某些配置中 - 也会遇到这个问题。

答案(再次猜测)

1) is this fps (20 fps) normal and expected?



我不知道 moblie,但是您的代码仍然可以在某些方面进行优化。 (见下文)

2) can the 100 km terrain be problem if so how should I manage it?



未聚焦的 block -> 移除主体(不仅仅是停用它)。

是的,说起来容易做起来难,你可以只关闭附近的 block ,但删除(删除)远处的 block 中的所有主体(> 3 block 距离,可能是)。

如果删除的 block 可以回到场景中,您可能必须找到一种方法将其保存在某个地方。 (例如只保存 body 的位置、大小、重量)

3) simulating 100 dynamic bodies with huge edge shape terrain is tottaly impossible ? ( but in the earn to die they did it)



他们做到了,或者你只是认为他们做到了?
在某些方面,编程是一门艺术。
你看到的东西可能与它们的实际实现方式有很大不同。
您的瓶颈可能只是地形 - 降低其详细程度也可能有所帮助。

4) should I write my own simple physics for only this kind of game (a simple specific one) ?



不,除非你想学习 && 有很多时间 && 真的很喜欢数学。

5) should I use bullet physics instead of box2d for 2D purposes ? is it possible? and will I face with performance problems ?



我想你还是会在某种程度上面对。
约束是昂贵的对于 Box2D 和 Bullet。
你确定你真的需要约束吗?
在某些情况下,可以通过复合形状/稍微修改游戏设计来避免这种情况。

我认为如果你改用 C++ 和 Bullet,你将获得至少 3 倍的性能,但是 我完全不确定 .

关于java - 2D 物理游戏性能问题(android 中的 libgdx box2d),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42346463/

相关文章:

c# - 更改冲突的程序集引用

c# - View 会降低 LINQ 查询性能吗?

java - 调整 CloudBees 应用程序的 JVM 参数

java - 解决 Hibernate 在多线程应用程序中的错误

java - 获取包 org.assertj.core.api 不存在,即使我在我的 pom 中指定版本 3.6.2 同时使用 JDK 1.8

java-如何确定不同类型服务器中特定类型处理的最佳线程数

java - 需要创建tql查询

java - 使用微调器操作 URL

android - 如何替换 Facebook Android SDK 替换 Session.OpenRequest

ruby-on-rails - rails 测试和开发数据库处于不同的模式中