Tuesday, January 20, 2009

Update on Pickling

As of this post, the latest svn revision, r148, has pickling support which is working great on the testbed. I'm rather excited about it, as it's somewhat of a powerful and unique feature.

For those who can compile the library, check out the testbed. It works like your regular quicksave (F5)/quickload (F7) system. There's an additional test, test_pickle.py, that shows how easy it is to load a pickled world. As far as the code itself goes, there's still some commenting to be done, but it should be readable.


  1. Going to play with this tonight.

    Does this preserve everything? Forces? Worldstate?

    If so, simply amazing.

    Is it possible to pickle selectivly, i.e., only the static objects, or only certain statics? (for level loading/editing)

  2. The results of forces -- changes in linear/angular velocity -- are all stored. The forces that you apply in your Step() loop still need to be applied after loading.

    The world state appears to be mostly equivalent. In the testing I've done, I saved the string representations of the world and all of the objects when saving and after loading. After loading, except for the occasional minor floating point error and a lesser pair count, the output was just about the same. If you notice any inconsistencies, please let me know.

    I was considering doing selective pickling, but my main goal was saving the whole world *cough* initially. There are some problems with selective pickling that I'll have to think over, if the interest is there for it.

    Any thoughts on how you'd like to see selective pickling implemented?

  3. After reviewing how you're doing pickling, I begin to see why selective pickling is a difficult task.

    Would it be possible to flag bodies/shapes/joints in such a way that the pickler knows to skip over them?

  4. You know, keeping the world arguement and then optionally taking in a list of box2d things (bodies/shapes/joints) to pickle would work too.

    You could then leave it to the user to ensure that what they pickle is unpickable.

    If there is some implict unpickling order, you might need to take in a list for each type (pickle these bodies, shapes, joints) so if you need to unpickle bodies first, you will know which thing to unpickle when

  5. I guess if I supported a custom bodyList/jointList passed in by the user, it would be rather easy to selectively pickle.

    I'm thinking of just overwriting the GetBodyList/GetJointList methods in b2World before calling the pickle to return a custom set of lists. That might be enough to take care of it, then reset them once done.

    The only problem would be if the user didn't pass in all of the necessary bodies to recreate the joints.

    I don't think I could very easily do shapes the same way.

  6. Okay, I've successfully done selective pickling with saving only bodies or saving only statics.

    It was as simple as I thought it'd be, simply modifying the b2World's body/jointLists.

    It's absolutely necessary to have all required bodies to make it such that joints/controllers can be saved. That isn't shown with the example, but it is possible.

    I can't see how these examples would be integrated into the library itself, however. Maybe just some supporting functions that will selectively get the body or joint list, and then leave it up to the user to properly execute the save/load.