SSS#3: Removing Zigzagging for Settlers: The Efforts Invested and Yet to Come(Part 2)
In our last blog, we discussed the zigzagging issue and how it inspired us to create a physics-based simulation to enhance the visuals and gameplay in our colony simulation game. We showcased a video that demonstrated how we implemented entity steering. There were many difficulties we had to overcome to reach the point where we are now, with creating physics shapes for our blocks being the most important one.
The first problem we encountered was that our options in Unity were quite limited for creating physics shapes for blocks at that time. We had a mesh for a 16 x 16 x 16 chunk that was generated dynamically. However, to utilize Unity's physics engine, it took a long time to build a physics shape for a given mesh, and it had to be rebuilt every time a block was added or removed. We first faced this problem when we simply tried to implement raycast, the ability to pick the block where the mouse is pointing. At that time, we were not considering something as big as utilizing a different, more customizable physics engine, but to solve the problem at hand, I implemented an incomplete physics engine in Rust to store the geometrical data and perform raycast on demand. This was before we migrated to Rust, but it was one of the reasons. The idea of having a more customizable, powerful, and performant engine at our disposal had its roots during that time. Fortunately, we later found a better option than my half-baked raycast engine: rapier3d, an open-source rigid-body physics engine written in Rust.
One of the benefits of using an open-source physics engine is customizability. It was great to implement our own solution for the blocks' physics shape, and it becames the next problem. We started with a triangle mesh to represent a chunk of blocks, which the rapier engine has good support for. However, from a physics simulation's prespective, this triangle mesh for the terrain blocks have some characteristics that is hard to deal with:
1. They consist of numerous blocks but with a limited variety
2. They get updated frequently
Thus, we have to carefully craft our physics shape instead of using the default implemetation from rapier engine.
In our previous blog, we talked about how we used some optimization techniques for the rendering of the blocks. These optimizations were designed to overcome these characteristics. In essence, we basically reused the compressed mesh data generated by the rendering step to construct our physics shape. All the triangles in the physics shape are stored as indices in a dictionary, which contains the triangles for all types of blocks, helping to save memory space. Since the meshes are also updated incrementally, we built the update of the physics shape on top of that, ensuring that they are updated consistently.physics shape could be updated realtime as well.
With all the effort, we now have a dynamically updated terrain that interact with other entities interactively. Our custom solution, combined with the rapier3d physics engine, has allowed us to overcome the limitations we previously faced in our development.