Another physics problem
A few weeks ago I noticed an odd physics bug in the game, where if part of a construction was rapidly rotating around one particular axis, that rotation would be massively slowed if the construction as a whole was also rotating about another, perpendicular axis. For example, a rapidly spinning axle (acting as a drive-shaft) running longitudinally in a car would be almost completely stopped if the car yawed or pitched (say when steering or coming off a jump).
There is a gyroscopic effect that applies to a rapidly spinning object, where if you try and rotate it about a second axis perpendicular to its spin axis, it will want to rotate about about a third axis perpendicular to both. Similarly, if you prevent it rotating about one perpendicular axis, it will resist rotation about the other. This happens in game physics, just as it does in the real world (it’s what keeps bicycles up!) In Unity’s physics (PhysX 2.83) when this resistance to rotation is counteracted by the hinge constraints holding the object’s rigidbody in place, it’s as if a large torque gets applied that dramatically reduces the rigidbody’s angular velocity about its spin axis. I’m no expert on the physics of gyros, it’s possible that this is a real world effect that is just exaggerated in PhysX – but regardless it didn’t feel correct to me and could completely screw up a construction’s behaviour in the game.
I did some tests using other physics engines – a later version of PhysX (3.3) and Bullet. I reproduced the same issue in both, so I’m assuming it’s a common behaviour among most, if not all, physics engines, and that porting over to a different one isn’t going to help me.
Hack and slash
I tried hacking around the problem by overriding the mass and inertia tensor of a rapidly spinning rigidbody, but to no avail. I tried adding an “artificial” torque to counteract the slowing down effect on the spinning rigidbody, but that just caused stability issues with the hinge constraints. It was as if all the forces were fighting each other, and something had to give!
I considered implementing a custom pseudo-physical solution specifically for drive-trains (i.e. motors, axles and gears), but this would have been a huge amount of work, it would have been very difficult to integrate nicely with the PhysX physics, and would have almost certainly limited the behaviour and physical realism of the constructions.
At this point I was really stuck. I contemplated ignoring the issue and simply living with it, but that just wasn’t acceptable to me. Another option would have been to completely remove all rapidly spinning stuff (like gears and axles) from the game, but after all the work I’ve done so far, I really didn’t want to do this. Besides, it would have hugely reduced the scope of what could be built in the game, and taken away from what I think will make it unique compared to other building / sandbox type games.
An error / performance trade-off
Fortunately I found a way out. I discovered that reducing the physics fixed update time-step minimised the problem to an acceptable level (albeit not eliminating it altogether). I believe the issue is due to mathematical error that occurs with a combination of very rapidly spinning rigidbodies and a fairly large time interval between physics updates. I can’t really lower the cap on how fast stuff can spin (not without placing undue limits on the constructions that can be built), so my only option was to update the physics more frequently with a smaller time-step. Of course this comes with a significant performance cost, but it looks like it’s a trade-off I’ll have to make.
So when you play the game now you may notice a performance slowdown (depending on the complexity of your constructions, and your computer spec). Next up, I plan to remove as much code as possible from my fixed update callbacks (these get executed at the same rate as the physics update), to try and mitigate this as much as I can!