0

Hi I'm having some fun with Box2D. And I'm working on a network game that requires full sync with all bodies. (There wont be many bodies).

So the plan is that i start up a server with some bodies in it. The server does the world simulation steps. Then after a while a client connects. When it does the server sends all state data for all bodies in the world to the client and the client will create them as NEW bodies. And then the client will have an exact fully synchronized copy of the game on the client side. Any small change on the server is copied and sent as message to the client. And because Box2D is deterministic any change on the server side will behave exactly the same on the client.

This works great if all bodies are awake. However when i one of them are asleep the simulations becomes unsynced. The positions, angles and velocitys for sleeping bodies differ with just a few decimals. actually it looks like they just need to be resting to screw up the sync.

So what i noticed was that even if i EXPLICITLY set a NEW body to be asleep, after the next world step it will become awake again. I'm guessing that is because Box2D needs to run a check on new bodies of some sort.

Is there anyway to fix this? And keep the sync?

currently im resyncing all bodies every 120th frame if offsync is detected by my checksum check. and keeps doing that until they are insync again. this causes some snapping of the game objects but still works surprisingly well, but id rather the game would not get offsync in the first place.

the server will send the float and int values to the client who will create the bodies using the following code. the server uses pretty much the same code when creating bodies on the server side:

//------------create world---------------
b2Vec2 gravity(0.0f, -10.0f);
b2World world(gravity);
world.SetAllowSleeping(true);

//---------------create bodies from values sent by server----------------------
//body def
b2BodyDef bodyDef;

if(bodyType == static_body)
bodyDef.type = b2_staticBody;
else if(bodyType == dynamic_body)
bodyDef.type = b2_dynamicBody;
else
throw "error invalid body def types";

bodyDef.angle = angle;
bodyDef.angularDamping = angularDamping;
bodyDef.angularVelocity = angularVelocity;
bodyDef.gravityScale = gravityScale;

bodyDef.linearDamping = linearDamping;
bodyDef.linearVelocity.x = linearVelocityX;
bodyDef.linearVelocity.y = linearVelocityY;
bodyDef.position.x = positionX;
bodyDef.position.y = positionY;

bodyDef.active = isActive;
bodyDef.awake = isAwake;
bodyDef.bullet = isBullet;
bodyDef.fixedRotation = isFixedRotation;
bodyDef.allowSleep = isSleepingAllowed;

//body
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
body = world.CreateBody(&bodyDef);

//fixture def
b2PolygonShape polygonShape;
polygonShape.SetAsBox(shapeWidth, shapeHeight);

b2FixtureDef fixtureDef;
fixtureDef.shape = &polygonShape;
fixtureDef.restitution = 0.5f;  // air resistance / fluid resistance
fixtureDef.density = 1.0f;
fixtureDef.friction = 1.0f;

//fixture
body->CreateFixture(&fixtureDef);

//set mass inertia and center
b2MassData md;
md.center = b2Vec2_zero;
md.I = intertia;
md.mass = mass;
body->SetMassData(&md);

//these cannot be predefined for some reason, seems like a bug in box2d
body->SetFixedRotation(isFixedRotation);

//----------run game simulations-----------
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;

world.Step(timeStep, velocityIterations, positionIterations);
4

1 回答 1

0

我在 box2d 论坛上问过,如果模拟在不同的时间步长开始,box2d 的内部状态似乎可能会有所不同。所以唯一的解决方案是解决它。

http://www.box2d.org/forum/viewtopic.php?f=3&t=8462&p=36115#p36115

于 2012-05-16T15:05:10.407 回答