4
votes

I am making a 2D car game like earn to die 2. I ve almost completed it. Only problem is the physics engine performance. I am using box2d and there are 10 meters length edge shapes totally building a 100 km terrain. 1 car and usually 30-40 boxes. Number of active dynamic bodies is around 60-100, max 120. Game fluently working in desktop but in android fps drops below 30 when actives bodies are more than 60. There are collisions between car and boxes and boxes each other and both box and car to ground.

I am using libgdx framework 1.9.4 as version, java is 1.7, coding with eclipse neon, windows 7.

this is how I am counting active bodies in world

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

active dynamic bodies are usually around 100

it is not a drawing issue with all terrain and underground meshes and car and boxes cost 6-7 mili seconds I measured them when box2d debug rendered is off and world step method call costs about 30 mili seconds when there are about 30 boxes while the car is crushing into them

I don't load all game objects (boxes for now) I splitted entire map into chunks map size is 100 km and chunk size is 50 meters when the car is in the next 50 meters ( in the chunk range) I load the boxes from a ready pool ( box2d world representations of the those objects are also pooled and when the boxes are in pool I deactivate their box2d body with setActive(false) and back to true while the chunk is loading)

I applied this chunk system for terrain too. I load all the terrain when the game is loading then deactivate them by setting with this method setActive(false) and when the car goes on trough the map if the chunk range includes car's x axis coordinate I activate the next chunk which contains the terrain static bodies having around 20 fixtures with size of 10 meters, makes the chunk size 200 meters at total.

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

the green lines are active terrain shapes as you see left and right after a distance are deactivated till the end of the map this part is from around 60 km of the map in middle of 100 km terrain map.

when vehicle moved little more new boxes will load there ahead and old ones will be pooled if they are 20 meters back from the car.

My questions are

1) is this fps (20 fps) normal and expected?(android 7 this is phone specifications http://www.androidpolice.com/2016/02/23/the-general-mobile-gm-5-plus-is-the-most-powerful-android-one-device-yet/)

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

->I tried activating/deactivating terrain bodies when they out of the screen rectangle.

->I tried hundreds of fixtures on a single body or every terrain piece is as separated body but best performance with I splited 100 km terrain into 200 meters chunks and each chunk is a body and consist of about 20 fixtures.

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 ?

if you need any code pls comment, I will add.

are there any really fast physics engines I couldn't find on the net if there are do you suggest to change box2D ?

good to note:

I am simulating box2d with constant time step I tried 1/60 1/45 1/30 and 8-3 , 6- 2 as iteration steps.

I use high damping values like .9 for both linear and angular for all bodies.

I also would like to split those boxes into pieces actually I am doing it but without splitting hem when car crushed I am experiencing this fps drop so I disabled it for now.

Only joints are wheel joints and used for wheel of car no more joints in anywhere in map.

Sizes are realistic those boxes are 1.2 meters high.

for boxes and cars polygon shapes used for terrain edge shapes used (chain shape)

velocity threshold is 1 as default in world settings.

if there are any notes I forgot pls comment and I will share.

thank you.

1

1 Answers

0
votes

Disclaimer: I can't answer all of your question, and below are just a guess from me.

A few years ago, I developed a game prototype and game library with Java + box2d + plain Opengl (LWJGL).

I think you are facing some issues that occurred to me.

However, with my low experience, I could be wrong.
If experts (readers) think that there are any mistake in my post, please comment below, I will fix it.

My guess

Java is slow / not quite suitable for game.

Disclaimer: There is a lot of argument about this.
I am not an expert enough to put a solid statement here, but I see a lot of my game-prototype run 3x-10x faster in C++ than Java. (with not-so-different algorithm)

Memory fragmentation

As you may already know, even you use pool, it is still very poor compared to C++.
You pool the boxes, but you can't pool everything, e.g. game logic data-structure, vector2D, plain array (new[] often), some horror algorithm in some libraries that you use.

Deactivated bodies still cost memory (intensify memory fragmentation indirectly).

You have a lot of static bodies / high complexity of static body.

You didn't mention how many static body you have, and what are them.
Are you using a high-amount-of-vertices shape for the terrain?
Popular physic engines like Box2D and Bullet are cool at convex shape, and expert at primitive shape, but tend to work poorly with concave shape (e.g. your terrian)

Your shapes are continuously colliding each other.

For example, a stack of 100 boxes cost a lot more computation than 100 boxes scattering around the scene.

Too large world

As far as I know, box2d divide a scene (world) into a grid. If your world is very large, but a lot of body cluster into the same cell of the grid, Box2D will work relatively worse.

It is not limited to Box2D.
Bullet and Ogre3D - in certain configuration - also suffer from this issue.

Answer (guess again)

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

I don't know about moblie, but your code can still be optimized in some ways. (see below)

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

Unfocused chunk -> remove the body (not just deactivated it).

Yes, it is easier said than done, you may just deactivate near chunk, but remove (delete) all bodies in chunk that is far away (> 3 chunk-distance, may be).

If the deleted chunk can come back to the scene, you may have to find a way to save it somewhere. (e.g. save only position of body, size, weight)

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

They did, or you just think they did?
In some aspect, programming is an art.
Thing you see can be very different from how they are actually implemented.
You bottleneck may be only the terrain - reduce its level-of-detail may also help.

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

No, except you want to learn && have a lot of time && really love Math.

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

I think you will still face in some degree.
Constraint is expensive for both Box2D and Bullet.
Are you sure you really need constraint?
In some cases, it can be avoided with compound shape / modify design of the game a bit.

I think if you change to C++ and Bullet, you will gain about at least 3x performance, but I am not sure about it at all.