How to prevent projectile jitter/warping on client?

Here is a video of what I’d like the final solution to act like. Currently, it is my game running in standalone mode: Standalone Example - YouTube

Here is a video of my game running as a client: Client Example - YouTube

The difference should be clear - there is substantial jitter in the second, client based, video. Any moderate distance away from the projectile and it is jittering so bad that it blurs. My question is, how do I get rid of the jitter? I believe it’s a networking and replication issue. Below is an explanation of how things are wired up - I’ll show blueprints for the relevant parts.

The shot is initially fired by the client, which calculates the spawn location and forward vector and then makes a call to a server-only event. The server spawns the actor, which then calls an interface function on the spawned actor, Set Forward Direction. Here’s a picture.

Set Forward Direction is implemented no the projectile actor and really doesn’t do much aside from set a “RepNotify” variable called forwardVector. Here’s a picture.

The forwardVector variable’s replication condition is set to “Skip Owner”; however, since I don’t set the owner of the actor all clients and the server have their OnRep function get called. The OnRep function for the forwardVector variable sets the velocity for the projectile - here’s a picture.

The projectile actor, the one that is spawned, has the following components: ProjectileMovement, and a collision sphere that has the following 3 child components: the mesh, smoke, and an explosion effect. The actor’s replication settings can be seen here.

The ProjectileMovement component on the projectile actor has the following configuration:

  • Under Component Replication, the Component Replicates box IS NOT checked.
  • The initial velocity is set to (0,0,0)
  • Projectile Gravity Scale is set to 0.0
  • In Projectile Interpolation, Interp Movement is checked, but everything else is left default. See here.

Another critical piece to this puzzle (I think…) is how I set the interpolated component and the updated component. I do this in the Construction Script for the projectile actor. See here.

I have tried tinkering with the interp parameters in the Projectile Interpolation section, but I haven’t really seen that much of a noticeable difference. I was looking at the documentation for the Projectile Interpolation settings (Projectile Movement | Unreal Engine Documentation and Interpolation | Unreal Engine Documentation) and my only thought is that my extending the Actor class and overwriting the PostNetReceiveLocationAndRotation function to call MoveInterpolationTarget, but I was hoping that how I had things setup in the Construction Script on my projectile actor that this was happening already. Is this not the case?

I realize I do have alternatives… For example, I could uncheck the Replicate Movement field on my projectile actor. The client would then essentially be responsible for doing their own thing, but this might be ok since the projectile is created and velocity is applied at roughly the same time on both the client and the server. Regardless, this will not work for all edge cases… For example, consider close quarters combat where a client is receiving slightly lagged updates on his opponents location… Since the server is the responsible authority for detecting the collision, the projectile on the client side could hit and then stick to the opponent even though it barely missed in the server’s calculation. Without location replication to correct for this, the projectile on the client’s view is incorrectly stuck/stopped.

Link to all BP screenshots: Server Spawns Actor - Album on Imgur

Any thoughts, help, or guidance is much appreciated :slight_smile:

1 Like

Nevermind, I got it :slight_smile: The UE4 documentation for the ProjectileMovement component lead me to believe that interp’ing, using the interpolation settings on the component, is not possible without calling MoveInterpolationTarget from the PostNetReceiveLocationAndRotation callback on an Actor… Turns out that is correct.

The fix is simple. Extend the Actor class and override PostNetReceiveLocationAndRotation to call MoveInterpolationTarget. The necessary parameters for MoveInterpolationTarget can be retrieved the same way they are in the base Actor class that you are extending.

I feel like this is a major, major flaw in the UE4 Blueprinting system. Without diving into C++ code, you simply cannot make this “look” right while keeping the actor’s movement replicated. Furthermore, I found that all of the code necessary to make this work on the ProjectileMovement component is exposed to Blueprints. The only thing not exposed is the Actor’s PostNetReceiveLocationAndRotation function.

2 Likes