2D Physics: Unity3D vs Farseer

The problem: colliding large, concave, moving 2D objects using small quads or circles as colliders to define the overall object boundaries. The small colliders are dynamic: they can be added, removed, or their shapes and positions changed. This doesn’t appear to be a typical physics scenario, so I wrote two implementations for Unity3D: one using its own 3D physics and another integrating Farseer physics.

Unity3D

Pros

  • Built-in: It’s already designed to work with the transform system, and has gizmos for colliders.
  • Decent API: Unity has plenty of API oddities and gotchas, but the physics fit in sensibly with the rest of the system.

Cons

  • Black box: Not always clear what’s happening as a result of changes or calls I make. This has led to one instance where I ended up with odd “popping” effects upon adding or removing colliders when rotation was enabled on objects and I wanted to use my own moment of inertia value. I did not pursue the problem further.
  • 3D: This adds a slight inconvenience in regard to constraining dynamics. It may also mean reduced performance because of greater complexity compared with 2D, although for my purposes I have yet to see problems.
  • Overhead: Each collider requires its own GameObject, which worries me when it comes to performance at scale. It comes back to the black box issue; it may be performant enough, but it’s an unknown that could change.

Farseer

Farseer is a C# port of Box2D. It was originally developed for XNA, but written to work as a stand-alone library as well.

Pros

  • Open-source: It’s great that I can jump in and see exactly what the library is doing. This also makes it easier to test; I can run the simulation in a test environment, allowing me to build automated physics integration tests.
  • 2D: Potential for better performance compared with a 3D library.

Cons

  • Integration effort: This means synchronizing between Farseer bodies and Unity transforms. Gizmos needed to be implemented, but fortunately much of the work was done in Farseer’s debug view and in this port.
  • API: It felt like the functionality was all over the place and a lot of internal details exposed (possibly for good reasons). It’s probably difficult to make changes at a point where it’s so widely used, and I’m sure much of it is the result of performance tuning and its history.
  • Code changes needed: Dynamic fixtures did not work well out of the box: Farseer does not appear to be designed for rapid fixture/shape changes. I had to write my own methods to create/pool fixtures and update shapes which relied on internal details of the library. I also notice a number of places where fixtures are removed from array-based lists by shifting the following array elements, which could conceivably result in poor performance with a large number of objects.

For both, I’d like to have better control over when body properties are automatically recalculated. In my case, I don’t want them to ever be recalculated from the shapes composing them because I already maintain those calculations and because the shapes do not represent the entire object. I haven’t stress-tested them both for a performance comparison, but I’d have a hard time believing Farseer would fare worse.

Another option I’d like to consider is Chipmunk, a 2D C library which appears to have a fairly clean API. Unfortunately, I don’t see any C# ports maintained, and I’m not about to roll my own (and maintain it..) without a compelling reason.

Conclusion

At this point I’ve decided to go with Farseer. It appears to work, I’ve gotten past some of the messy details, and it allows me to test physics-dependent functionality independently from Unity. That last point is the most compelling, and probably won’t change even if Unity gets a 2D solution that otherwise fits my needs.

This comparison came with some side benefits to the codebase:

  • Isolating coordinate mapping: Unity has a left-handed coordinate system, and in the past I’ve had the camera looking in the -Y direction, with the X-Z plane containing the 2D world. I took this opportunity to instead map to X-Y with the camera looking in the +Z direction, defining a common set of methods to support either.
  • Decoupling physics: During the transition, I could swap back and forth between physics implementations to compare results. I’d like to maintain this ability to mock out or swap physics libraries in the future.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>