Pawn replicated movement 'jittery' for clients

I’ve always noticed that replicated pawns seem somewhat ‘jittery’ when viewed from clients. I’ve run some tests and can see that the pawn’s location vector is being rounded to the nearest integer. Hence, as the xyx values move between round integers, the pawn appears to jerk to the new location (at least i believe this is what’s causing it).

Here is a quick video of what I mean:

I’m not seeing much handling for this in any of the example UDK code, which is kinda surprising.

Has anyone dealt with this that would like to share their experience? Thanks

I see some params in UDKPawn:

/** Whether to smoothly interpolate pawn position corrections on clients based on received location updates */
var bool bSmoothNetUpdates;

/** Maximum location correction distance for which other pawn positions on a client will be smoothly updated */
var float MaxSmoothNetUpdateDist;

/** If the updated location is more than NoSmoothNetUpdateDist from the current pawn position on the client, pop it to the updated location.
If it is between MaxSmoothNetUpdateDist and NoSmoothNetUpdateDist, pop to MaxSmoothNetUpdateDist away from the updated location */
var float NoSmoothNetUpdateDist;

/** How long to take to smoothly interpolate from the old pawn position on the client to the corrected one sent by the server.  Must be > 0.0 */
var float SmoothNetUpdateTime;

However they seem to have no affect at all. I also don’t see them actually used anywhere in the US engine code.

Does anyone actually know where in the code clients receive the location sent by the server? Or is this hidden away in native code?

I have the same problem, games like chivalry medieval warfare don-t have such problems I wonder how they did, did it.

I have an idea that i think i think what is used in chivalry mediaval warfare cold scooter, With advanced foot placement the mesh gets attached to the floor so it never jitters just stays on the landscape…lFootPlacement here we have a hacky solution. Advanced foot placement it’s what we are looking for.

Chivalry doesn’t even use foot placement, and movement seems jittery across the net (proof)
foot placement might help, but getting foot placement to work over jittery movements is a pain in the first place (even in single player), especially as anything you do from code will be one frame behind. you don’t just “attach the mesh to the floor” because the mesh is a child of the Pawn, and therefore everything you do to the mesh is an offset in relation to the Pawn itsef.
as the Pawn gets authoritative movements from the network you’ll be just fighting a more complex problem.
unless you use absolute translation in your Pawn and pass it manually every frame. but then your Pawn would be one frame behind at all times. it might just work

Coldscooter: unfortunately those params are from UDKPawn so I can’t tell you anything about them native-wise

the only lead I could give is to try in vanilla UTGame, fake some net lag and packet loss (there’s console commands for this) and check if it’s the case (I’d be surprised if UT has this issue)

I’ve attempted my own pawn smoothing logic for clients, which works pretty well:

//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
// Pawns tick event
//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
simulated event Tick(float DeltaTime)
    local vector newLoc;


    //My attempt to smooth pawn location on network games.
    if (Role < Role_Authority && !IsLocallyControlled() && !bPlayedDeath) {
        if (PrevTickLocation != vect(0,0,0) && Physics != PHYS_FALLING) {
            newLoc = VInterpTo(PrevTickLocation, Location, DeltaTime, 10);
            newLoc.x = Location.x;//We only want to interp the z axis.
            newLoc.y = Location.y;
        PrevTickLocation = Location;

Seems very odd that there isn’t something in the default engine for this though…

thanks a LOT for sharing cold scoota

I know you solved it but I’m curious if just smoothing against the previous frame/update location is enough. don’t you still have some jitter or at least a bit of inconsistency?

some small extra info:

  • the native UDKPawn variables (bSmoothNetUpdates etc) work by modifying the mesh translation. if you’re modifying the mesh translation yourself elsewhere it might be the cause for it not to work
  • you’re right that vectors get rounded to integer values as described here
    That same page suggests that “If you need more than integer precision, you should multiply the vector by a scalar value before assigning it to the replicated variable.”