Last month we’ve been busy working on multiplayer and rendering performance. This blog post is all about the challenges we encountered so far while writing Volo’s netcode.
Martijn has been busy finding and fixing what seemed like the most terrifying bug in the history of Volo. Right after we ported the Pilot code to support multiplayer a super annoying bug pops up that made the whole simulation unstable under low frame rates. And we just couldn’t find the source of this bug. So we went from blaming Unity, to blaming ourselves, to blaming Unity to almost settling on ‘Okay, we have to make the performance of the game better otherwise no one can play it’, to ‘Oh, it’s just this stupid little line in our code that breaks everything’.
Right now, we’re both working on the actual code that syncs the pilot between peers. Which means we have to try to make Unity behave like it should respect two separate physics worlds (one on the client and the other on the server) and try to reconcile them. Unfortunately, Unity doesn’t really have any tools for doing that. In fact the whole physics engine basically assumes there is only one physics world, like you’re building a singleplayer game. So, we have to work around that. And if the workarounds turn out not result in a satisfying playing experience we have to use another physics engine that does respect multiplayer environments.
This is definitely one of those “if only I could go back in time to warn my past self about this” scenarios.
Let me explain in more detail why Unity is ill-suited for fast-paced multiplayer physics-heavy games and why another physics-heavy game you might have heard of called Rocket League switched to Bullet physics for this exact reason.
The way Unity physics work is that time always moves forward and time only passes when real time passes. The consequence is that we cannot run the physics engine to predict anything. Prediction and correction are important parts of multiplayer code where we extrapolate where Player A is based on the time that it took to send the information from Player A to Player B. This latency (the time between sending and receiving) is the duration you need to use to extrapolate from to visualize on Player B’s screen where Player A is now. If we would just render Player A on the exact spot Player A told us that he was we would effectively be rendering him in the past, resulting in a poor multiplayer experience.
So, if extrapolation is at the heart of a good multiplayer experience how do we fix that? There’s two ways of doing this:
Create our own limited physics extrapolation engine that effectively tries to mimick what Unity’s physics do, but giving us the power to rewind time and simulate in non-realtime. The resulting code is usually hacky, and almost works in some circumstances but not in others. Flying straight forward works fine, but barrel rolling doesn’t for example. Collisions are also a nightmare. You can imagine that making our own Volo specific extrapolation engine is complex and time consuming especially since each new use-case for Volo’s physics model (barrel-rolling, parachutes, you name it) has to be modeled in this extrapolation engine as well. It’s certainly not impossible to do this but the result of this approach will definitely be that Volo multiplayer is not gonna be as awesome as Volo singleplayer simply because some things are just too hard or time-consuming to do. We would have to make the Pilot physics simpler, take out barrel-rolling, significantly reduce the complexity of the parachutes and probably limit the Pilot/Parachute user customization that we had in mind.
Another solution to this problem is to do the same as the Rocket League people did: switch to a physics engine you have more control over, like Bullet Physics. Once you use Bullet physics you get your extrapolation engine for free, simply because Bullet doesn’t have a notion of real time. It just runs whenever you want it to run, for example: you can simulate 5 seconds of physics as fast as your processor can crunch the numbers (say, 1 millisecond realtime).
The hard part of course is that we would need to port the entire Pilot and Parachute simulation to this new physics engine, and become responsible for maintaining this physics engine code during the game’s lifespan. You can imagine that this is a lot of work, especially for a 2-person team with quite enough on their plates already.
Whichever way it goes, there are still a few core battles to fight before Pilot is ready to fly together with friends.
Furthermore, this month we open sourced our master server solution called Padrone. It’s a unique master server solution that let’s people on different platforms (itch.io, Steam etc.) play games with each other. Normally, games would just require you to use Steam for multiplayer, or would limit their multiplayer experience to the platform that it runs on. We think we can do better, and help promote the awesome itch.io platform as well. We’ve been consistently impressed by the quality of this platform and their new desktop easily rivals Steam. We encourage you to check it out.
That’s it for this month! Watch out for next month’s blog post for more info on multiplayer and why the new Unity 5.4 release is crucial for improving Volo’s performance, both in VR and in general.