Projectiles

Projectiles which move over time can have lag hidden by accelerating the projectiles for the server and spectators, while allowing the firing client to show the projectile immediately.

Another bonus to this approach is you are not networking the projectile movement each tick, which saves tremendously on bandwidth and performance.

Here is an example of what this guide will cover. Notice how even though the client has a 220ms ping the projectile is still aligned on the server. Other clients would align the projectile as well with the same guide code.

First the local client, or owning client, fires the projectile. The projectile is spawned locally, then the client tells the server to also fire the projectile. The MAX_PASSED_TIME constant is covered in the next code snippet.

When the server receives the fire request it will calculate how long it took the client to send the fire message using the provided tick. Later on the projectile will be accelerated based on this time passed.

After the passedTime is calculated, spawn the projectile on the server, then tell spectators to also spawn the projectile; spectators being other clients.

Observers use the same technique to calculate the passed time and spawn the projectile. There are a few small things to note.

First, this RPC is sent to everyone but the owner. The owner does not need to receive the RPC because it already spawned the projectile locally.

Second, the passed time calculation is not limited by half. This is to support the maximum possible passed time. This is not a requirement, but is recommended.

With the projectile spawned all that's left is showing how to use the calculated passed time. You likely noticed the SpawnProjectile method was initializing the projectile with some values. Here's what that looks like:

After initializing with the specified passed time and direction all that's left to accelerate the projectile is a move method. The provided example is a very basic implementation of a move method, while also applying the acceleration.

If there is passed time to apply then additional delta is added using the passedTimeDelta variable.

The percentage applied when assigning the step variable decides how fast your projectile will catch up to the predicted value. In this code I am using 8% of the passed time per Move call. Higher values will result in the projectile catching up faster.

Very last, keep in mind these projectiles are fired locally and are not networked. Because of this you may want to perform different actions based on if client or server. The code below demonstrates what a collision event might look like.

Last updated