Offset in position during replication of fast-moving actors

Hi,

I’m replicating fast projectiles (speed: 8000) that uses Projectile Movement Component.The thing that on client side I see significant offset from initial spawning location (Replication of fast-moving objects - YouTube)

But if I spawn projectile with zero initial speed and set velocity OnBeginPlay after any small Delay (0.0001 just for sake of delay), spawn position behave as expected (fast projectiles - no delay - YouTube)

I understand that due to replication stuff, bullet’s position on client side will slightly shift. But I’m observing too big shift, right?

Although delay fixing the problem, I personally feel it too hacky to be good solution :confused: I would like to know the better way to process such situations.

P.S. replication update frequency set by default (100 per second) and I’m running on 60 FPS.

Thanks.

I have a similar problem and it causes projectiles to spawn behind the character sometimes when the character is moving forward, and then the projectiles collide with the character!

What is your projectile Tick Group? Pre Physics, During Physics or Post Physics? Does messing around with these makes any difference?

What part of the projectile (Events and Variables) are you replicating?

(It is pointless to replicate projectile position for such fast moving deterministic objects so please assure me that you don’t.)

Tick group is Pre Physics. Anyway it does not change anything in my situation.
For the projectile I’m using simple Actor with Projectile Movement Component. And I’m replicating actor itself.
Blue trails - particle system and orange glowing object - Static Mesh Component.
It maybe pointless to replicate it, but I don’t see any problem (except one I mentioned). My question is why it behave as I described. If it’s intended, how should I solve my problem.

Physics and rendering are not synchronized. They run on separate threads. (I assume) While rendering runs on variable frame rate (FPS) physics runs best with high, fixed frame rate. (which allows the use of interval arithmetic) For this reason the Unreal Physics Engine uses sub-stepping. (source)

  1. When you fire your gun the projectile actor is spawned in its initial position
  2. Next a request is send to the physics system with a timestamp and a speed vector.
  3. The moment the physics system replies the position of your projectile is set based on this timestamp.
  4. The other client receives the initial conditions but it is way behind in respect to time so the projectile is created a few meters away from the gun because that is the correct position based on the velocity and the timestamp.
  5. All particles and graphics are then attached in the tick but they don’t have any prior position so they look like they start from that point (a few meters away)

If you delay the setting of the speed the engine has enough time to replicate the starting position in the first frame on the other client and the the particles are attached.

When the physics system starts to move the object the particles were already created in their initial position and you get the proper result.

Now the important bit:

Physics engines are not deterministic (contrary to what you might think) because they cut a lot of corners and are prone to all kinds errors.This means that the same simulation can have different outcome every time you run it and may differ significantly on different clients.

This is the reason most games do not simulate meaningful physics in multiplayer environment. Battlefield games for example, replicate the destruction of a wall but every client simulates the physics (smoke and rubble) on their own and the physical objects have no gameplay significance - you can run and shoot through the rubble.

If you need a physical simulation in your multiplayer game it is either not simulated by the physics engine (like the gravity affecting the ACharacter) or run entirely on the server (which often leads to glitches)

To fix your problem:

  1. You might create your particle in it’s initial position and then hand it out to the physics system (which you in fact do with the delay). BTW delay with value of 0.0f will delay a single frame which might be useful to you.
  2. You might mask the glitch with big enough muzzle flash. (which is often used in production)
  3. You might just send the initial conditions (position rotation and time) to the server, calculate the hit result (location and time) on the server and send it back to the clients. Then every client will draw whatever particles it wants between the two points oblivious to the underlying logic but the resulting hit will be consistent across all clients.
  4. Fighter jet pilots have average reaction time of about 250msec. (don’t quote me on that) No one can dodge your projectile moving at 288km/h. This makes this weapon, in essence, a scan-line hit so you just might treat it like that.
  5. Limit your frame rate and sub-step values. This might work to negate the lag/frame drop problems.

Bonus:

Here is a nice blog post by Giuseppe Portelli which explores the Unreal physics system much better than I could.

Sorry for the long read.

I understand all that things, I’m not new in game development.

The other client receives the initial conditions but it is way behind in respect to time so the projectile is created a few meters away from the gun because that is the correct position based on the velocity and the timestamp.

I’m afraid, you wrong here. UE4 have no build in lag compensation. And it’s easily to check:

  1. I’m testing on single machine so there is near zero latency.
  2. If I add some fake latency via console command, projectiles (and other replicated actors) positions on client will be delayed. They wont be in sync anymore.

I feel there is something with spawning projectile with initial speed. But it makes no sense for me. Only one frame skip (Delay 0) solves the problem. That means replication work very precise (if only one frame-skip is enough to establish correct initial spawn position), so there should not be any problem at all :confused:

So, still waiting if someone can explain what is going on :slight_smile:

I understand all that things, I’m not new in game development.

Ah! Then you have no excuse for replicating the position of fast moving physical objects :wink:

Seriously: I am sorry if I somehow hurt your pride. I try to explain things in length as I don’t know you and I have no idea which part eludes you.

UE4 have no build in lag compensation.

You are entirely missing the point. It is not about network latency but the inherited order of operations and the discrepancy between render and physics delta time. (and the underlying predictions) If you start a dedicated server - chances are that all clients will see the offset result regardless of ping. The use of a listening server gives you the illusion that somehow one of the clients behaves differently. (assuming the projectile spawn executes on the server)

  1. ListeningServer tick1:
    Spawn a projectile and set its position and velocity. Add particle effect.
  2. ListeningServer physics sub-step:
    The projectile is moved to position based on velocity and timestamp.
  3. Client tick2:
    Get replicated actor position. Create replicated actor with position and velocity. Add particle effects.

As you obviously understand, the client will always get the first position already modified by the physics sub-step of the server. Not only that you can’t reliably pinpoint when the physics sub-step is executed but you have no way of ensuring when the replication will happen.

Here is another interesting read on the subject: Networked Physics (2004) | Gaffer On Games

I honestly don’t want discuss “to replicate or not to replicate” here :slight_smile: Let’s say I must replicate fast moving projectile for some insane reason. Return to the topic, I guess now I understand what’s going on. So if I want without any RPC out of nowhere just replicate fast-moving actor’s location, I need to delay speed application post spawn a bit to “settle” things in place.

Thanks for your patience and explanations.

Yep. In practice you should start moving the object after you are sure the initial position has been replicated already.

Glad I could help.

P.S. Check the links. There is much more than I can explain.