Hacker News new | ask | show | jobs
by yodon 2589 days ago
Fond(?) memories of the Tribes 2 engine discussed in that paper, which became the GarageGames engine, which was so poorly architected that every function of interest ran inside the network serialization function. Why did all the code run inside the network serializer? Because the engine was such a mess that no one could figure out why their values were getting stomped on and eventually someone realized "hey! The last bit of code that runs each frame is the network serializer! If I put my player bone animation code in the network serializer nothing can stomp on my animations" and a new arms race was born as every developer rushed to put their code into the network serializer.
1 comments

Disclaimer: I spent five years working at GarageGames doing core Torque development (the Tribes 2 engine derivative we sold).

The core code was pretty clean but there was a LOT of cruft on top of this part which tended to obscure the really good bits. IMHO the library that handled the animation was genius - it was incredibly light, it supported a broad featureset, and it could load any old asset from v1 up to v30. It even did a bunch of crazy data layout stuff to allow extremely fast endian conversion for PPC vs Intel (back when that mattered).

Good efficient networking for that era meant you had to be miserly with your resources. Tribes 2/Torque was very much aligned with these requirements and your example is actually a good example of those strengths.

The engine had three update cycles, all in service of the networking.

First, it would process fixed timestep logic - ticks guaranteed at 32 per second (this also aligned with packet send rate). Client and server both ran this. This is physics, user input, health management, etc.

Second, it would run "time" based logic. This would be things like particle systems which don't care a lot about whether you advance them 100ms at a time or 1ms at a time, and don't need to match precisely for gameplay anyway. Only client ran this.

Third, it would interpolate tick state. This would smoothly interpolate between the last and current game state based on how far you were between the two states. It introduced a small amount of lag but since it did not predict it never caused visual glitches. This is gave a smooth appearance for any of the stuff that happened in the first step. Only client ran this.

The result of all this machinery is that you paid exactly what you needed to for each type of thing in your simulation and no more.

Later versions of the engine added lag compensation. This meant that client would snapshot game state and re-run the fixed timestep logic for compensated objects based on latency. You could configure it to only consider objects that might have interacted with the player (and thus were mispredicted) to save on CPU.

What happened in the case of authoritative skeletal animation?

1. Gameplay relevant parts of the skeleton would be simulated in the fixed ticks. For instance, the current orientation of a player's weapon which might need to take their animation pose into account. So you might see the spine and one arm updated here, while legs wouldn't be touched.

2. In the time based logic, you would run the full skeletal animation update so that the player could see smooth animation.

3. In the interpolation phase, you would interpolate the position of the player between the two states to give a smooth appearance (in conjunction with the animation work in phase 2).

I would submit the above is actually a pretty elegant solution to the above. Unfortunately the surface level code was all cut down versions of Tribes code which was written with shipping, not long term reuse, in mind.

Most of the community developers never really got their hands wrapped around this architectural stuff. A big fault of our core engine product was that it was oriented towards AAA projects and we never really made it both user friendly AND powerful. So we went with powerful but that didn't serve our indie customer base well.

It took Unity around a decade and $500M to add "really powerful" to "easy to use" so I don't feel too bad about this.