I’m working on a multiplayer vehicle game with projectiles. Networked vehicles are extremely smooth. Replicated projectile movement components are not so smooth. How do I make my networked projectiles just as smooth?
Here’s a video comparing multiplayer and single player side by side. It also includes screenshots of my replication settings and projectile component.
When in single player mode, both vehicle physics and projectile movement are very smooth
When networked, replicated vehicle movement is perfect (the vehicle replication in the engine is fantastic). The projectile movement components are choppy when replicated.
Physics substepping is on
I’m wondering what I can do to smooth out my replicated projectiles. I’m happy to implement some kind of client-side interpolation or explore other techniques, but I’m just looking for suggestions with authority! Any help would be appreciated. Thanks!
My workaround is a poor man’s client-side prediction implementation. It doesn’t include rewind/replay, but because the ProjectileMovement components are so predictable it’s fairly reliable. I suspect there will still be issues if the ProjectileMovement components interact with physics components, the latter of which could potentially be in different places at the same time on the server and client (depending on their replication behavior). This could result in the client’s projectile deviating from the server’s. However, I can’t say for sure since I haven’t tested this case nor have I dug into the engine code. That is on my long list of things I don’t know that I would like to know.
The client-side implementation for Projectiles looks like this, in short:
Replicate ProjectileMovement components, but set Replicates Movement to false
Instantiate, fire, and perform projectile collision detection on the Server with authority
Simultaneously instantiate, fire, and perform projectile collision detection with a replicated multicast. This will create a projectiles on client machines and launch them when the server launches its instance.
Here are a couple of screenshots detailing my implementation.
Projectile replication settings
Initial fire event (I have a ProjectileInterface so this is an event called by the launching mechanism on whatever Projectile it’s holding, typically it would just be a function call)
Execute server and multicast launches simultaneously (if using client-side prediction)
Server and multicast events
This isn’t really client-side prediction as much as it is client-side do-its-own-thing-but-depend-on-the-server-for-hits, but it certainly smooths out the illusion, and thanks to the predictability of the ProjectileMovement component I haven’t noticed any deviation yet.
I’m marking this “correct” for now, but it’s really just “better than nothing” until I can show that the projectiles will stay in sync regardless of environment, or someone less lazy than I shows up with a rewind/replay implementation.
I haven’t checked your images yet, but it sounds exactly like the initial solution I’m going with. I’d really love to see a blog post on improvements to this. It’d go a long way in my learning.