Projectiles

Projectiles are split into two parts; the Projectile State and a Projectile Actor. The Projectile State is a lightweight struct which stores the information about the projectile (such as position and velocity) which can then be easily simulated forward every frame. Keeping this light also means that it is very easy and cheap to roll back to a previous state if required. The Projectile State can be overridden to create custom Projectile logic but must be deterministic and match on both client and server.

The Projectile Actor is a physical representation of what is happening in the projectile state. It binds to the relevant events within the state and then updates in the render tick rather than in the network tick to ensure the visuals of the projectile are smooth. This is not spawned on a dedicated server as there is no need for visuals.

Replication

Each projectile is given a unique ID so that they can be identified and matched between server and client. However, they are not replicated so they expect to be set up correctly initially so they can be simulated the same on all clients. Both the client and the server create each projectile independently. The ID should match on client and server so if authoritative RPCs need to be called, the correct projectile can still be found.

Projectiles have different Replication Modes that determine which timeline the projectile should be in:

  • Owner Predicted: The projectile will be spawned in the owners timeline. When the server spawns the projectile, the world state will be rolled back to the same state that the owner saw when it created the projectile. The server projectile is then stepped through each world tick until it hits a target or it catches up to the current server frame.

  • Simulated Predicted: The projectile is spawned in the servers timeline and will be simulated along with each world tick. Once the projectile is replicated to a Simulated Proxy, the projectile is stepped forwards so that the Simulated Proxy can see the projectile in their own timeline. This allows the Simulated Proxy to avoid the projectile. It is recommended to only use this for slow moving projectiles as the projectile will teleport on simulated clients and is more noticeable the further the distance. Simulated Proxies will also lose the advantage of being able to dodge the projectile if it is too fast.

Spawning Projectiles At Partial Frames

When using Interpolated SimulatedProxyNetworkLOD in NPP, the world state will be shown at a state that is earlier than your own predicted actors state. As this state is interpolated between two frames, the actual location of world actors may not match the server when using full frames.

To fix this, the client can send the spawn frame override (including the interpolation percentage) to the server via SendEmitterSpawnFrameOverride which will be validated with ValidateClientEmitterData to ensure the data has not been tampered. If valid, the server will then continue the rest of the projectile functionality with the updated frame index.

Visual Offset

As the player usually shoots at the location in the center of the reticle and the projectile must be shot from the end of the gun, these two lines need to meet somehow. The picture below shows how the projectile actors path can be blended into the authoritative state path over time to make this look as natural as possible. The data to change this blend can be found in the Projectile Data Asset under Predicted Visual Blend and Simulated Visual Blend. It may take some tweaking to find the value that looks the best.

Gunsmith.Debug.DisplayProjectileVisualBlendDebug 1 Can be used to visualise this blend, along with Gunsmith.Debug.DisplayProjectileDebug 1 to trace the projectiles path.

Redirection

While using Owner Predicted Replication Mode, any projectile created is being created in a timeline that matches what the owning player sees which means that all other targets are in a state that is in the past. However, other players will also be predicting their own pawns location which means that any projectiles created in the Simulated Proxies world will miss as they’re shooting at a target in the past.

The solution to this issue is Projectile Redirection. If a projectile hits a target on the server, an RPC will be sent to all Simulated Proxies to notify them of this hit. If this notification exists when the Simulated Proxy is setting up the projectile in their own world, the projectile can be oriented to ensure that it hits the predicted pawn in the same place on their own mesh.

This should only be used with very fast projectiles as the server needs to report the hit before the Simulated Proxy gets the chance to set it in their own world. This can be disabled per projectile in the Projectile Data Asset.

Gunsmith.Debug.DisplayProjectileRedirectionDebug 1 Use this debug command to visualise projectile redirection.