Box2D C++ tutorials - User data
Last edited: July 14 2013Chinese version -> 中文
User data
In the previous topic, we saw how useful it was to have a reference to a physics object from a game entity class. Sometimes it is also useful to have the opposite - a pointer from a physics object to an entity in your game. In Box2D this is called user data, and it is just a pointer which you can set to hold some information that may be useful for you. The following classes have this functionality:
- b2Body
- b2Fixture
- b2Joint
1 2 3 | //in b2Body, b2Fixture, b2Joint void SetUserData(void* data); void* GetUserData(); |
In order to access the user data for each physics body, we'll also need to try out a method for looping across all bodies in the scene. Instead of a loop in the proper sense, this is done by a linked list of bodies. We can use b2World::GetBodyList() to get the first element in the list to start iterating on.
So, start with the source code from the previous topic and modify it a bit. Firstly, take out all references to the m_body member variable of the Ball class, and alter its constructor to set the Ball class itself in the user data of the created physics body:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Ball(b2World* world, float radius) { m_radius = radius; //set up dynamic body b2BodyDef myBodyDef; myBodyDef.type = b2_dynamicBody; myBodyDef.position.Set(0, 20); b2Body* body = world->CreateBody(&myBodyDef); //set this Ball object in the body's user data body->SetUserData( this ); //add circle fixture b2CircleShape circleShape; circleShape.m_p.Set(0, 0); circleShape.m_radius = m_radius; b2FixtureDef myFixtureDef; myFixtureDef.shape = &circleShape; myFixtureDef.density = 1; body->CreateFixture(&myFixtureDef); } |
1 2 3 | b2Vec2 m_position; float m_angle; b2Vec2 m_linearVelocity; |
1 2 | glTranslatef( m_position.x, m_position.y, 0 ); glRotatef( m_angle * RADTODEG, 0, 0, 1 ); |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 | b2Body* b = m_world->GetBodyList();//get start of list while ( b != NULL ) { //obtain Ball pointer from user data Ball* ball = static_cast<Ball*>( b->GetUserData() ); if ( ball != NULL ) { ball->m_position = b->GetPosition(); ball->m_angle = b->GetAngle(); ball->m_linearVelocity = b->GetLinearVelocity(); } //continue to next body b = b->GetNext(); } |
So what kind of practical uses does this user data feature have then? The usefulness comes when we want to be informed about something happening in the physics engine that we can't easily predict, such as when fixtures collide, what they collided with and what the reaction forces will be, etc. Other useful things include ray-casting or AABB queries to find intersected fixtures (and get the related game entity from the user data in the fixture).
Setting complex user data
Since the user data accepts a void pointer, anything that can be cast to a void pointer can be set in the user data. This could be a single number, an existing object pointer (as above) or a pointer that you make specifically to hold some complex information relating to the physics object. Here are some examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //setting and retrieving an integer int myInt = 123; body->SetUserData( (void*)myInt ); ...later... int udInt = (int)body->GetUserData(); //setting and retrieving a complex structure struct bodyUserData { int entityType; float health; float stunnedTimeout; }; bodyUserData* myStruct = new bodyUserData; myStruct->health = 4;//set structure contents as necessary body->SetUserData(myStruct); ...later... bodyUserData* udStruct = (bodyUserData*)body->GetUserData(); |
For most applications it is very handy to set a structure with multiple members in the user data. Box2D does not delete any of your user data objects when you destroy a body/fixture/joint, so you must remember to clean these up yourself when they are no longer needed.
In the structure example above the members of the structure are fixed, which gives a limited set of attributes to use, and not much flexibility if you have different entity types in your game. See the section of the collision callbacks topic titled 'real scenarios' for an example of using class inheritance for a more practical approach for when you have many types of entities.