Just how many physics updates per second should your game have?
I'm not shy about the fact that I always thought 60 was completely ridiculous number. Building something that I hope to actually be finished one day, WITH multiplayer capabilities, I thought 50 would be a better number, as it's much more scalable (every 20 milliseconds as opposed to every 16.666667, Or 17, 17, 16, 17, 17, 16 etc depending if you use floats or ints).
But looking at commercial game developers, they think even that is too high. I've sort of got raycast projectiles working (I say sort of, because I can't see them breaking at present), and of course for "moving projectiles", the length of the ray (which translates to how fast it travels) is affected by the number of physics steps per second:
- 100 steps per second, ray is one unit long
- 50 steps per second, ray is two units long
- 30 steps per second, ray is 3.333333 units long
- etc
But what about player movement? There's no raycasts involved here. Players are represented using ellipsoids that are stretched tall. They are actual physics bodies that are kept upright using Newton's custom 6DOF joint (which there is no access to in LE2, but I've made them more or less the same as upvectors, which are very similar to LE2's raycast player controllers). All rotation is restricted by the joint, which prevents them from toppling over but they also can't "look to the side" for example (your camera can as its rotation is not physics based at all, it just has its position locked to your player body).
I set about updating the physics update section of the main loop, which is rather small. Once every (1000 / tick rate) milliseconds (based upon the time of the first ever tick, not the time of the previous tick), the world is updates by (1 / tick rate) seconds. So if tick rate is 50, then once every 20 milliseconds, the world updates by 0.02 seconds.
I swapped the tick rate number out for 40 instead of 50. It's still divisible by 1000, but now the world will advance by 0.025 seconds once every 25 milliseconds rather than the old 0.02 seconds every 20 milliseconds. That sounds right doesn't it?
The first problem to arise from this, I'd already expected. I hadn't updated the amount of force that each player moved by. This was deliberate. If the force value was a number per second, than the code wouldn't need updating. But it wasn't - it's just an arbitrary number. So the next step would be to calculate the force required, such that were it was 1 before, it would now be 1.2. I preferred a calculation over the fixed number version because once I had got the same distance per second working at 40 ticks per second, I would then change it again to see if it still worked.
There is however, a complication. A force of 1.2, 40 times per second, does not give the same results as 1.0, 50 times per second. The most logical reason I can think of because once the next physics step arrives, I add a new 1.2 to whatever force was still acting on the body from the previous update. This in theory should be fine if there was no cap on the maximum speed a player is allowed to travel at. If you add forces on the bodies for however many ticks 2 exact seconds works out as, and then let them slow down naturally, they should stop at the same position. But I've imposed a maximum running speed cap to prevent players from speeding up like motorbikes and reaching silly speeds.
I played around for a few hours trying to come up with some exponential formula to allow deceleration to occur at the same rate, regardless of the update rate, but without removing the speed cap, it just wasn't going to work (and with the speed cap removed, the complex formula shouldn't be necessary at all). Eventually I tried a different idea.
Instead of trying to change how many times per second the physics are updated, why didn't I keep that constant along with the forces, and instead only change how often the forces were calculated? To make this idea work I'd have to remove the current system and replace it with a new one - one that ticked much, much faster - insane speeds by comparison. Well that's exactly what I did. There were 1000 physics updates performed per second. (you read that right, but I'll write it out in words just to make it absolutely clear, one thousand times per second). I know what you're thinking: "you think you can make a game playable over the Internet when it's updating 1000 times per second... You're mad!"
I believe Einstein went mad too, but this isn't mad. I'm thinking along the idea of 1000 little steps per second. For a case of 50 ticks per second, we calculate "movement" forces, and then for the next 20 ticks we keep giving the objects the same movement forces. If our force is equivalent to 0.1 units per physics mini-step, then after 1 second we will have moved 100 units if we kept the movement key held down for the entire time. The same is visible if we calculate the forces 40 times per second instead - there's still 1000 mini-steps occurring each second, it's just that the forces are being calculated less regularly, but if you don't alter your movement vector, the result is identical.
It means that now, the I can set the world's apparent tick rate based on how the game is being played.
Over the Internet, 25 seems like a good number here, and for local network play, 40 is probably plenty fast enough (For reference, Unreal Tournament uses 20 and 35 respectively, but I thought 35 wasn't very scalable). For single player games, it depends on the style of game here, but for a FPS, I don't 50 (or even 100) would be excessive, however I feel multiplayer co-op story based games should probably stick 40. There's a lot of information to keep synchronised there, and it gets worse when there are more than 2 players involved.
However, things to consider if using the mini-steps idea. "external" forces, such as being sent flying by a rocket explosion should only be applied for 1 tick. The explosion only happens once - it's not a persistent force like walking would be. Keep your internal and external forces separate - add them both during a mini-step, but afterwards, clear the external forces, but keep applying the same (not recalculated) internal forces until your next "major" step.
It makes no difference if (for example at 40 ticks per second), you really do update the world once per millisecond, or if you simply call the update function 25 times in a loop, and then not perform any more mini-steps for another 25 milliseconds. Using the latter method may help to remove the temptation to recalculate forces before the next major step, and closer resembles the layout of our 40 ticks per second behaviour. It also means your main game thread can sleep, thus leaving your client threads with more CPU time to accept your clients' (or AI bots) inputs.
In a very large world with many bodies, 100 mini-steps per second may be more preferable than 1000, but there will be some loss of accuracy here, or you'll need a system to know when to add an extra step. After all, now each major step will occur after 2.5 mini-steps (in case of 40 per second), so you'll need to keep track of when to add one extra. It's easy for 40, all major steps have two mini steps, but every second major step will need one extra - but if you want 17 (just as a deliberately awkward example) major steps per second, that will be a little trickier, although not impossible.
0 Comments
Recommended Comments
There are no comments to display.