[Multiplayer] How to get smooth character interpolation on moving platforms without jittering

Hi guys.

After fiddling around with experimental blueprints and modifiying character movement component, I’m now asking for some advice ._.

I want to get two things working:

Firstly,
I’m trying to get players replicated on moving objects without stuttering. The moving object hasn’t to accelerate or turn fast. A good example would be a boat or ship.

What I’ve done is setting up a basic actor, which position gets replicated over the network from server to client. The client will simultaneously accelerate with the server. If there’s too much offset, the client’s boat will interpolate to the server position. So really basic networking stuff. The clients boat also extrapolates the servers position, considering the network latency, so it doesn’t gets corrected to a position back in time. I even visualized the servers real position with the extrapolated ones, compared with mine, to get better visual feedback.

Almost everything is working fine. There are no problems if I just accelerate, no matter how fast it speed up or stops. There is only one thing, I couldn’t get a rid of.
That stuttering and jittering when the platform rotates on the yaw axis (left and right turning). I slowed down the turnspeed to a minimum of about 6 units per second (times deltatime).
I even slowly adding a value from 0-1, which gets multiplied by the turnrate. But after a second or so, it still jitters.

The strange thing what I’m wondering about is, why it doesn’t stutters when I’m accelerating, even at 500*deltatime per second, without slowly increasing speed. Everything is fine.
But turning at a constant slow speed, the player starts to stutter.

Secondly,
on top of that problem. If the player jumps on a moving platform, he gets shifted a few units, basically teleporting to the servers position. I investigated the character movement component, especially the “setbase” function, because I wanted to get a rid of the “teleport” what happens, if you jump on a moving platform in multiplayer at a given lag.
The server will jump [lag]ms later on the moving platform, causing the platform being a little further X units and will correct the players position not smoothly, but immediately.
To visualize the teleporting problem, I made up a graphic:

I could minimize this behavior by turning off the “setbase” function, if the player jumps. So as long he enters a boat/ship which doesn’t move, it should be fine. He can move around and even jump without being rebased twice, after the jump and right after landing.

Faking the objects movement is no option for me, as they can be more moveble platforms, on which other player can stand on.
I even bought an unreal engine c++ multiplayer course, which was really great to dive in, but at the end, same problems occure:

  • jittering / rotational offset by the player on a moving platform which is turning in one direction while accelerating forward
  • teleport / rebaseing if I jump on a moving platform

After some search for games made up in unreal, I find “sea of thieves” as a good working example.

  • player can walk smooth and free on a moving platform (ship)
  • player can even jump on, without being corrected/teleported immediately

The questions I had in mind when I saw the gameplay were:
Does they somehow edited the character movement component or
did they write up a whole new character movement component, which replicates its position relative to the platform origin, extrapolating the movement of the ship to the player?

I’m out of ideas. Do I overcomplicate this issue? Is there a good workaround, to get this two features working?

edit: one thing I forgot to add:

If the platform is rotating just a little faster, so the offset is greater than the “walls” thickness of the object, preventing the player walking off the ledge, there is another issue, caused by the same logic. I can move on the client, at certain positions, through the walls, off the platform, hover in the air, jittering around. On the server, I’m still on the platform, but the offset is causing the difference, letting the client move outside in his state of the game.

Here’s another graphic, which highlights a green area, which marks the offset, in which the clients is standing on, hovering in the air:

Try increasing the server tickrate and see if that helps. https://answers.unrealengine.com/que…tick-rate.html

It won’t get rid of stuttering completely but should smooth it noticeably.

Thanks for that hint, will try it out.

I also tried, setting Network Max Smooth Update Distance to a higher value, which is exactly that, what should help out to fix the stuttering. The description says:
“Maximum distances character is allowed to lag behind server location when interpolating between updates.” But even at 10x higher values, when I activate “p.NetShowCorrections=1”, I see the same corrections, sadly. It doesn’t do anything.

Also, that green area in the second pic, the offset area between server and client. That happens also, if I just accelerate forward. But I can’t go through any wall at the client, even at 800 units/seconds, which makes the area quite big at the rear part of the platform. It seems, the character movment component checks the correct relative position at any lag, as long as I’m not turning in any other direction but straight ahead while accelerating.

What you could do is force a net update on all characters standing on that platform as it is rotating. I don’t know if this will work though. Other than that maybe you could make the rotation happen locally on the client aswell. The client runs its own simulation of the platform, if it goes wrong it automatically gets corrected by the server.

Hm, I just disconnected all correction logic and just rotated the platform on both, the server and the client and do you know what? It jitters again o-0
But it’s smooth, if I run it at zero lag. And of course if I am the server, to make sure, the problem isn’t somewhere else.

I think it’s time to make a very simple demo, out of the third person example, to dismiss all other factors, that might come in to my problem. I will make a video about it.

Okay, Nvidia Experience isn’t working anymore since the last update, if unreal engine is open. So I uploaded the test project:
https://www.dropbox.com/s/scy1ysee3d…nTest.rar?dl=0

It’s a 4.18.2 project, but it should be possible to convert it to 4.19, since it’s just the 3rd person example.
To simulate lag, I recommend clumsy(lag inbound outbound 120ms delay):
https://jagt.github.io/clumsy/index.html

If you hit play, make sure you’re running on a dedicated server, 1 player is enough.
You will see the platform moving towards to you, with a red wireframe, which is the actual server position. It should be shifted a little, if you set up the lag correctly.
I set the platform to replicated, but not replicated movement. So both platforms, on client and server, will move independent from each other. You can turn on movement replication, it’s just to better visualize the problem.

If you jump on the platform, you will be teleported. I never could get a rid of that behavior completely, even the smallest amount of lag will make it visible, explanation in picture 1 in my first post.
But everything else is working pretty good. You walk until the very last ledge of the platform without jittering or falling down, even if the server is 1-5m ahead of you. Your position is stored relative to the platform, you client and server are good.

Now, go into theplatform blueprint and reconnect the event tick to “addRelativeRotation”, hit compile and play. You should have “replicate movement” on the platform turned off now, to see what I mean. Just keep “replicates” checked =). Jump on the platform, you can only land, where the red wireframe model is. You can even float in the air, like in my 2nd picture of my first post in that green zone.

So why this doesn’t happen if I only accelerate without rotation? I mean, it’s basically the same thing. Server and client are shifted, due to a lag. The client can jump on the platform and beside that teleport, he can run from edge to edge, without being corrected by the position offset, because the relative location is mainained. But not if rotation comes into play, it jitters and there is no relative position maintaining, why is this? You can see the jittering if you look on the players feet on the ground.

Okay, clumsy somehow prevented shadowplay from recording. I’m uploading a video right now, for all, which don’t want to download the project. Gonna put the link in this post when it’s done.

here you go:

If I would have jumped on the red wireframe, while the platform was just moving forward, the player would be teleported to the correct relative position. That doesn’t happen with the rotation setup, he will float in the air.

It would be nice, if someone from epics networking programmers would confirm the differences and maybe can provide a workaround. If/how it’s possible in general, to avoid this behavior with the current character movement component with a bit of adapting the c++ files.

I’ve got an even better visualization of the different behaviors:

You can clearly see what happens, while the platform rotates. The player isn’t keeping the offset. And that’s causing the issues.

Alright, I further investigated the c++ code of the character positioning and replication and found the issue. I need to change, how the character gets based on platforms and add some rotational logic to some lines. But have no idea if I will success. Maybe I will reach someone of epics networking programmers with a detailed bug report.

Thanks anyways, for trying to help me out with that issue =)

Based movement should work with prediction already - you need to make sure the platforms themselves are synchronised. If they aren’t, then you’ll notice glitches - especially with rotations as the offsets will be that much larger.

I know what you mean. I already did extrapolate my clients platform to match up the servers. It runs okay.

But what I reckognized in an experiment was (only if rotation sticks to 0), no matter how far the platform on server and client are apart from each other, there is not the smallest amount of jitter.
Because the movment component does calculate the position relative to the platform. Of course, they are desynced, but that’s not my point. In the 2nd video, you see the red server player maintaining the offset to the client. So it doesn’t jitter, because relative positions are good. I want that for the rotation too. I switched in that video to rotation later on. Server and client were almost on the same location, which is a different behavior, compared to the non-rotational movement in the first part of the 2nd video. I can walk over the edge and hover around. Of course it’s because of the desync and it was just to demonstrate the different behaviors. It would be much better, if the rotational distance between client and server would be maintained, so no jittering occures if they don’t match up for a second.

It’s pretty hard to explain what I mean, but at the end, I will turn on again my movement replication and smoothing and everything, so the platforms are only a few cm apart from each other(not like in the example).
But then, everything will be smooth, no matter what. And no glitching through walls, which happens, if the server can runs a little further than the client, due to the wrong offsets.

Thanks for your input.
edit: And of course, if you can give a simple example of a rotating platform running smooth at a certain lag without those problems, I’m more than happy to try it out =)

I can confirm that Zhentouk is right. Unreal is location based, not rotational.

Having the same problem here; I need to get character to jump along a rotating column… and a small delay will cause players to miss the end of the columns. Our solution was similar to Zhentouk, We extrapolate the client into the future with the lag amount. Such then when player jump, the rotating column will match his landing both on client and server. (It was very tough… let me tell you that.)

The problem we have is after that though. Since unreal update player position with relative location with disregard the base rotation, lots and lots of thing go wrong afterward.

1 Like

Thanks for confirming this issue,
I alsmost implemented rotational relative platform walking. Replication is done, just the controls…I need to edit the “MoveForward” direction, which get sent to the server, to a relative one. But I still couldn’t figure out where the right place is. Because if I just change the direction vector, both, client and server will move together, as they both use this vector for movement. I’m really close to solve it.

The 2nd Problem with the “jump on a platform” is there on both cases, with or without rotation. If you would jump on the straight moving platform, and the servers platform is a little in advance, you could miss it, if you jump on the last end of the platform. The Server client will land Xms later and miss it. (Doesn’t unreal has some integrated lag compensation integrated? Maybe worth using this…)
This and the “teleport” which happens, if you land on a moving platform are hard to solve. What I don’t understand is, the “snapping”. Maybe I can smooth this behavior. Together with extrapolating the correct destination, it will be almost not recognizable anymore (I hope). But for now, my platforms will wait until the player is on top, then accelerate.

edit: By the way, do you use the authoritative client predicted characterMovementComponent for your game? And does it jitter while moving on rotating platforms?

edit2: Relative movment is working now. Just have to adapt the jump. In certain cases (random 1:5), the position gets recorrected. I might have overlooked something.

anotherEdit: Disabled impart base velocity. Seems pretty stable right now.

Question: If you enable “NetShowCorrections 1” via command. The green debug capsule has to match the servers position, right? Because it isn’t in my test project, so I need to apply the relative rotation somewhere on the correction logic too.

Offsetting the time based on latency isn’t enough to keep the platforms synchronized. Based Movement is sent as a relative position/rotation, not absolute. The Server and Client will ultimately be simulating the rotation of the platform at different delta times (less obvious when you’re testing on the same machine), so when the Server receives an RPC for the Character Movement, it is 99% likely that the platform will still be at a slightly different rotation there than on the client.

Character Movement would suffer the same issue - but doesn’t because the Server actually doesn’t run any simulation on the client between packets. When it receives a packet from the client, delta time is computed from the time the last packet was received and that’s when it updates movement. This ensures that Client and Server simulate movement with the same delta time over the course of multiple frames. It also does some complex timestamp synchronization which prevents the client from artificially sending huge deltas for speed-hacking.

You’re right.
And what I’m trying to accomplish right now is, (if dynamicBase) not only set the clients position relative to the platforms position, but also to the platforms rotation. The only thing, what I can’t implement 100% right now, it sending relative accelerationInput data to the server, and (on the server) read them back to absolute values, based on the platforms rotation. Everything works until the server sent a small correction. I can see, the correction tries to fit the player into a wrong direction(acceleration) and it jitters(corrects) the player, until I stand still for one or two seconds. After that, I can walk around smoothly on the rotating platform. I guess, I need to edit the correction logic somewhere. But it’s really hard to find :confused:
The wrong direction the player is facing, when he is jittering around due to the corrections sent from the server, is infact the inverseTransform of the direction in world space of the platform I’m standing on. So I just need to convert a direction vector (direction input or acceleration) somewhere from local to world space. But it’s really tricky. It’s the very last step, everything else works perfect.

edit: I think I found the last issue. The correction sends the velocity from the server, which should be wrong. I also changed the inputDirectionRotation to another position in code to a more direct one, which made the last issue more subtle and almost gone. I’ll check, if I can rotate the velocity or send relative velocity vectors. I hope this will fix it.

Everything works now as intended. As long as I interpolate the rotation fast enough, there are only very few and short corrections, which the player won’t recognize. And this is only, if the character moves. If he stands still, there is no error, no correction.

I made a final video.
First, I show the relative offsets, by letting the platform interpolate to the servers position slowly.
You see now, server and client remain at correct offsets. But there are some corrections while I keep moving.
Then, I just turn up my rotational interpolation to show, what the player movement is look like, at 240ms rtt lag (120 in/out).
I didn’t touch replication settings like “MAXPOSITIONERRORSQUARED=3”. So you see, most of the time, even at higher lags, it maintains the (locDiff | locDiff) under 3, as long as I RInterp fast enough. The only jittering you see, is the replicated red wireframe server position, but that’s just debug information. Now I can use this for a commercial project, which involves trains and ships moving in multiplayer environments =)

This time only 720p. Upload times are crazy at 1080p^^

In another test, I set the addRelativeLocation to 12kdeltatime, which should be about 432 km/h | (((12.000 / 100) / 1000) * 3600) .
At rotationSpeed 12
deltatime, there was the same experience as shown in the 2nd part of the video. Occational and short corrections, but nothing which the player will recognize.
Phew, now I know a lot better how CharacterMovementComponent works under the hood. The only last issue now would be the teleport, if you jump on a moving object. But I will change this teleport to a smooth correction, if I find out how.

2 Likes

Do you know if anyone ever achieved a solution to the problem? I’m working on exactly the same thing; replicating rotation for a vehicle players can stand on. The user Zhentouk seems to be gone so I could really use some help, can’t find anyone else that’s working on it.

I don’t sorry. It’s a really complex problem so without attempting to implement it myself I couldn’t propose a solution.

My hope is that the upcoming Chaos/Network Prediction implementation will be more tightly coupled with the replacement character movement system to make this sort of thing easier.

I am working on the same thing currently, do you want to join a discord or something like that so we can share our ideas/help each other?

Is this going to be in 4.26? Would appreciate any info on the Chaos/Network Prediction and replacement character movement system so I can keep learning. Can transform location for a ship and the characters can walk around on the surface at max velocity, but as soon as any rotation is added the character locations become out of sync and jittery. Have tried many solutions but found nothing promising as of yet.

Yeah that’d be good, I can start a Discord channel. Will send you the invite.