Why do even simple movers lag when playing online?

Discussions about Coding and Scripting
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Why do even simple movers lag when playing online?

Post by Dizzy »

I've been reading up on movers and replication, and I think I understand the basics (correct me if I'm wrong): movers have their movement replicated from server to client with the frequency of the movement updates being determined by the server tick rate. However, to save bandwidth, UT compresses or otherwise limits the accuracy of (at least) some parts of the movers' positional data (especially the rotation data?) and this results in a mover looking laggy and choppy to the player.

However, why does this happen even if the mover is extremely simple, such as an elevator going from the ground floor to the first floor? Surely both the client and the server can both extrapolate the movement of such movers without the need to constantly update the player as they ride the elevator?

I'm researching this because certain BunnyTrack maps suffer horribly from laggy movers which make them very difficult to play, (examples: BT-SeGear (first elevator movers) and BT-Donnie (long horizontal mover)) and I would like to solve that problem.

I came across this thread on this forum about replicating movers' movement with a higher degree of accuracy, and it seems like a good idea to me (but I'm unable to get it working, as I say in the thread).

Can anyone explain the mechanics of this problem and help me understand how it might be fixed please?
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Why do even simple movers lag when playing online?

Post by Higor »

If you have XC_Engine version 21, replace XC_Engine.u with this one.
It's a hack fix to movers, what it does is change their interpolation time to the nearest 'net safe' value.
This may slightly affect the time it takes some movers to move, but there won't be any mismatch between clients and servers.
Script patcher:
- Added in XC_Engine.ini [GeneralConfig] option
-- bFixMoverTimeMP (default=True)
** Tweaks Movers' interpolation time so that mover position doesn't desync on net games.
You do not have the required permissions to view the files attached to this post.
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

I'm going to look at this. Because I'm curious about that Boat from CrystalMine3 - in default stage, the Boat from client is moving faster - route is long, if you jump outta boat too early you'll fall in water being attacked by some BiterFish-ies, it's annoying, I wanna see this fix.
Perhaps I'll port it into an external actor declared in ini like the DripGenerator solution.
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Re: Why do even simple movers lag when playing online?

Post by Dizzy »

@Higor I don't use XC Engine yet; we did test it on the server about a year ago but if I remember correctly, it was causing issues with some BT maps and obstacles. I might try it again and I can let you know of any issues, if you're interested?

@sektor That would be good, thanks. Did you see my post on the other thread? The code looks like it should work because it's just extending UT's default Mover object, right? But I don't know enough about native coding to even understand why it has to be a native class in the first place.

I compiled the code and made a test map with the mover. It works offline but not online.
Test map: http://ge.tt/6r4UgAs2
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

Nah, it's another code done by Higor, you can take a look at it. It's not about tick it's function InterpolateTo having some Time tweak probably usable in a mover child or in default mover if you know to conform another Engine.U file with original for not messing up players.

Take in account that XC_Engine 21 is better that its predecessors, I'm using it currently without collision tweaks because I have other stuff for teleporters which was good enough so far. Tests/Games have been operated on a lousy machine at home and in a service for game-servers rental, all is functional.

Edit: I checked in detail header of that "code". I draw probably two conclusions:
- that snipped could be other programming language :what: ;
- if that snippet wants to be some UScript, it could get a sort of Nobel prize for bullshitting. By looking at code for 10-20 seconds it looks as a no go for me. Class is declared as an abomination and a DLL file has to be sent at player, and here I don't know what can be done. I don't want to go Evil Mode today but that is not a help for community. If coders are writing such things, I'm not surprised to see web space filled with crap and GB of updates :omfg: .

As another hint even for me and from me, I think worth the time to see what is about that EXUMover or such - EXU has a lot of things that worth lecturing if Waffnuffly has nothing against this.
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Re: Why do even simple movers lag when playing online?

Post by Dizzy »

OK, so do you think I should just abandon that code completely?

I thought the discussion in the other thread made complete sense:
comoestas wrote:When I put your suggestion into the default properties, simulated proxy worked, but lagged as much as the DumbProxy. Good thing I was reading up much on replication. Apparently the rotation and location values are compressed when replicated, loosing accuracy, and so the collision lag, or more appropriately, approximation error. To fix it, I replicated the separate components of both location and rotation as floats, and updated them in a simulated Tick. No accuracy loss and absolutely no lag, even with 200+ ping.
So this person is saying that SimulatedProxy movers work, but they lose accuracy because of UT's netcode compressing the location/rotation values resuling in approximation errors. His solution was to create a custom mover which fully replicates the positional data for the mover to the client.
Feralidragon wrote:best thing to do in these cases where you need full precision is to put vectors in floats and rotators in ints (in the case of rotators int or float will have the same precision since the max precision of a rotator is an integer anyway), and then replicated them to the client, and let the client set them up on its own.
So that's what I'm trying to do.

The code snippet looks like UScript to me but I agree the class declaration is strange and that's why I'm asking for help understanding what's going on there.
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

Dizzy wrote:The code snippet looks like UScript to me but I agree the class declaration is strange and that's why I'm asking for help understanding what's going on there.
Apparently is UScript except something...

Code: Select all

native function SetBrush(model m);
THIS, as term native from my poor knowledge it's about a NATIVE function located in a DLL file, probably written in C++. These things can be sent to player by doing ugly hacks as long as Player has to know what that Mover does else won't match anything like a replication. If that thing do works I want to see it, else I won't believe a word.

Aside. I'll inspect Higor's code for showing what is about
First is backup of an empty function - getting original mover code

Code: Select all

			ReplaceFunction( class'XC_Engine_Mover', class'Mover', 'InterpolateTo_Org', 'InterpolateTo'); //Backup the function
			ReplaceFunction( class'Mover', class'XC_Engine_Mover', 'InterpolateTo', 'InterpolateTo_MPFix'); //Apply the fix
This is happening in Server
And how do look these inside Abstract class used as main core

Code: Select all

//======== InterpolateTo Original backup - begin ==========//
//
// Stores Mover.InterpolateTo original code here
//
final function InterpolateTo_Org( byte NewKeyNum, float Seconds ) //This empty one is completed by Original
{
}
//======== InterpolateTo Original backup - end ==========//


//======== InterpolateTo hack - begin ==========//
//
// Hacked version of Mover.InterpolateTo
// Fixes the 'Seconds' parameter so that movers don't badly
// desync in net games
//
 
final function InterpolateTo_MPFix( byte NewKeyNum, float Seconds ) //Original then is turned into this one
{
	Seconds = int(100.0 * FMax(0.01, (1.0 / FMax(Seconds, 0.005))));
	Seconds = 1.0 / (Seconds * 0.01);
	InterpolateTo_Org( NewKeyNum, Seconds); //And then calling original execution previously thrown here as backup
}
//======== InterpolateTo hack - end ==========//
All it's inside Server and client is pulled here. I gotta admit I did not know ever how to set those "Seconds" variable and if they could help at tweaking. Higor is a living CPU unit, processing with 1024 thoughts/second :wink: .
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Re: Why do even simple movers lag when playing online?

Post by Dizzy »

Thank you for the explanation of Higor's solution. That makes sense.

My next question is: can we make this solution into a server actor which doesn't require XC_Engine to run?
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

Dizzy wrote:My next question is: can we make this solution into a server actor which doesn't require XC_Engine to run?
Umm... this is a function called in Mover and you have to hook execution, I don't have a clue if this is possible but... I did not try yet the second solution for NON XC servers by implementing this directly in default Mover class, it would be nice to have a server-actor but "push-code" I think it's not in account here.
The only thing so far is to try this add-on in original Engine.Mover class. This code it's not like you are pushing monster to attack a biterfish by changing State and Enemy variable and leaving original execution to take place, this is a different thing and it needs rewritten, it's execution itself.
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Why do even simple movers lag when playing online?

Post by Higor »

You can change ANY property in Movers... as long as the first tick hasn't been run yet.

So you load a SERVERACTOR, BECAUSE YOU DON'T NEED A MUTATOR (you'll end up checking every single actor being spawned like this otherwise, and ServerActor is loaded on servers not offline), have it run a

Code: Select all

event PreBeginPlay()
{
    ForEach AllActors( class'Mover', M)
    {
        M.MoveTime = FIXTIME(M.MoveTime);
        if ( M.IsA('GradualMover') )
            { } //Fix GradualMover times here as well
    }
    Destroy();
}
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

Good, I'll capture this code. As for a less number of actors and objects generally, I prefer a Mover defaulted with a hard-coded good code...
It looks operational so far even without XC_Engine - not a bad fix at all.
Speaking about On-Line experiments, I could fight with monsters on such a moving platform (Some fixed Tarmation2 as a sample) where usually was hard to figure where was the monster on the platform during movement to not forget the fight around those elevators with more than 3 key-frames where Pawn's Location looks much better replicated. I could perform even two Combo shocks on the Boat from CrystalMine3, harder but not impossible as long as action do looks more realistic. Worth this patch.
For the rest of stunts I think I will setup a builder and a mapping class/package that can be loaded and creating such a Mover ready for mapping. That one definitely will work everywhere...
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Re: Why do even simple movers lag when playing online?

Post by Dizzy »

sektor2111 wrote:It looks operational so far even without XC_Engine - not a bad fix at all.
Can you please share this operational mod so I can test it on my server too?
sektor2111 wrote:For the rest of stunts I think I will setup a builder and a mapping class/package that can be loaded and creating such a Mover ready for mapping. That one definitely will work everywhere...
And that sounds excellent; will you share this when it's done too?

Thank you both for your help so far.
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

If Higor said that an Actor doing changes to "MoveTime" as a great Server-Actor is a solution, then let's see something... but preventing a "zero" deal (there are such maps and they are very logic). I have a proposal for this Server-Actor if Higor wants to look at code - before doing changes in server if this idea is not a good one. Also there are more mover types with various Close Open Times, I have to take them in account too...
Editing...

Edit: So far - awaiting Higor's feed-back:

Code: Select all

class MovSync expands Actor config (MovSync);

var() config float MinTime;

event PreBeginPlay()
{
	local Mover M;

	log ("Mover Net Sync Tweaking Actor has been loaded.",'MoverSync');

	if ( MinTime == 0 ) // Generate ini or rewrite Moron type setup
	{
		MinTime = 0.2;
		SaveConfig();
	}
// Fast moving movers can be used as effects for something creative.
// We try to ignore movers moving under MinTime seconds.
// But GradualMover and other classes with multiple timers have another deal.
	foreach AllActors(class'Mover', M)
	{
		if ( M.NumKeys == 0 ) //Some maps uses these for various purposes - they won't move.
			continue;
		if ( M.Class == Class'Mover' || M.Class != Class'RotatingMover' || M.Class == Class'MixMover' || M.Class == Class'LoopMover'
		|| M.Class == Class'GradualMover' || M.Class == Class'ElevatorMover' || M.Class == Class'AttachMover'|| M.Class == Class'AssertMover')
			FixMover(M,M.MoveTime); 
	}
	if ( M == None )
	{
		log ("This Map does not have any mover...",'MoverSync');
	}
	else
		M = None;
	LifeSpan = 1.000000; //I don't think I will destroy this during Initialization
}

final function FixMover( Mover M, float Secs )
{
	local bool bInvalidMover;
	local int i;

	if ( M.bStatic || Secs >= 3600 || M == None || M.bDeleteMe ) //Not gonna be like in sh!t maps a la CryptRunners with Movers that can be deleted.
		bInvalidMover = True;

	if ( !bInvalidMover )
	{
		if ( i != 0 )
			i = 0;
		if ( M.MoveTime > MinTime ) //Not sure if GradualMover will use these but let's solve it too, never dealing with 0, it's pointless.
			M.MoveTime = ComputeTime(Secs);
		for ( i = 0 ; i < 6 ; i++ )
		{
			if ( GradualMover(M) != None )
			{
				if ( GradualMover(M).OpenTimes[i] > MinTime )
					GradualMover(M).OpenTimes[i] = ComputeTime(GradualMover(M).OpenTimes[i]);
				if ( GradualMover(M).CloseTimes[i] > MinTime )
					GradualMover(M).CloseTimes[i] = ComputeTime(GradualMover(M).CloseTimes[i]);
			}
			else if ( AssertMover(M) != None )
			{
				if ( AssertMover(M).OpenTimes[i] > MinTime )
					AssertMover(M).OpenTimes[i] = ComputeTime(AssertMover(M).OpenTimes[i]);
				if ( AssertMover(M).CloseTimes[i] > MinTime )
					AssertMover(M).CloseTimes[i] = ComputeTime(AssertMover(M).CloseTimes[i]);
			}
			else if ( MixMover(M) != None )
			{
				if ( MixMover(M).OpenTimes[i] > MinTime )
					MixMover(M).OpenTimes[i] = ComputeTime(MixMover(M).OpenTimes[i]);
				if ( MixMover(M).CloseTimes[i] > MinTime )
					MixMover(M).CloseTimes[i] = ComputeTime(MixMover(M).CloseTimes[i]);
			}
		}
		if ( i != 0 )
			i = 0;
	}
}

final function float ComputeTime(float OldMove)
{
	local float Seconds;

	Seconds = OldMOve;
	Seconds = int(100.0 * FMax(0.01, (1.0 / FMax(Seconds, 0.005))));
	Seconds = 1.0 / (Seconds * 0.01);

	return Seconds;
}

DefaultProperties
{
	RemoteRole=ROLE_None
	NetUpdateFrequency=0.01
	CollisionHeight=1
	CollisionRadius=1
	bHidden=True
	DrawType=DT_None
	MinTime=0.2
}
Explanations:
- wants a configuration for minimal movement time attacked by tweaker actor - fast movers or "no-time" moving movers should not be tweaked - What for ?;
- wants only default stock classes letting people to be creative/doing BETTER Movers - never touch custom things if not needed;
- GradualMover MixMover AssertMover are known types with up to 6 OpenTimes CloseTimes used but we want ONLY Stock debated as said before;
- Rotating Mover has another way of working with rotation stuff;
- a little "SpeedUp" for such cases would be good by excepting "IsA" when is not a must-have;
- configurable a MaxMovingTime fix rather than a hard-coded 3600 value (3600 seconds = 1 hour - Expecting retarded movers ?) ?;
- according to paranoia stuff, perhaps actor class being bMovable by default we can set bMovable = False in PrebeginPlay - after spawning actor, just because won't hurt anything.
Next stage is doing some Testing... I believe you can compile previous code :| .
User avatar
Dizzy
Experienced
Posts: 109
Joined: Tue May 21, 2013 3:57 pm
Personal rank: Oaf

Re: Why do even simple movers lag when playing online?

Post by Dizzy »

@sektor Amazing code; you're a legend. I'll give this a try later today.

One thing: should the following not be AND instead of OR?
if ( M.Class == Class'Mover' || M.Class != Class'RotatingMover' ...etc

A few random questions:

1. When would you use a Mover with NumKeys = 0?
2. When would you make a Mover bStatic = True?
3. Why did you give the Actor a CollisionRadius and CollisionHeight of 1?

For RotatingMovers, Drunklove offers a possible solution to keep them working properly online:
http://www.i4games.eu/forum/p120807-%5B ... ggy-movers
Spoiler
Another option for rotating movers is to use the custom script PropertyChanger.u to toggle SimulatedProxy to DumbProxy then back to SimulatedProxy in a fraction of a second. There's a small jitter every minute or so but the mover doesn't stop rotating, it just updates it online.

https://www.mediafire.com/?j8u6ryscnca8kij

Notes:
-Still needs tested with multiple people, not sure what happens if a player joins a server half way through.
-The higher the TimedTrigger is set the bigger the jitter, the lower it's set the more jitters you see but not as noticeable.
-Only works for movers that rotate, AFAIK.
Join the BunnyTrack.net Discord chat server: https://www.bunnytrack.net/discord
User avatar
sektor2111
Godlike
Posts: 6435
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Why do even simple movers lag when playing online?

Post by sektor2111 »

Answering in order of asking >>
By looking at RotatingMover this one has probably nothing with MoveTime because it's ROTATING not Translating - this is not LIFT - if this is wrong, change condition, it's just a code that can be compiled. Else RotatingMover types might have another deal, it's about Pitch Roll Yaw, not about Moving from Location1 to Location2.

NumKeys = 0 is used in some map (probably more) with some cars-decorations. In order to have a more realistic collision mapper has added some movers almost similar to cars format inside them simulating car's collision and reducing polygons (not sure if was Kvartal map or other). Else... by using this way I've covered other decoration in MH-Sk_BattlingLottery in order to have a proper collision rather than default stupid cylinder and that mover makes noise when is being bumped by something but it is not supposed to move. Also I ruined some movers allowing to cheat a MH map with GRAB command - not only removing cheat but slapping down NumKeys for not being open EVER ("nasty" compiled code passing constants) - they could be some damn default walls not movers.

bStatic for mover could be used by other "mapper" for previous said "deco" reason, if such a mover won't move, being for masking cylinder type collision, definitely tweaking MoveTime makes no sense.

Collision of this actor - let's say that is my choice 1×1 - this actor actually doesn't even a need default collision because it might die in next second. Processing collision for it takes a fewer time if actor is small probably no processing for this case - I'm talking about VisibleCollidingActors iterator. Walk in forums and see why some maps are lagging - those having triggers with big collisions -> I like small actors: Small size, small collision, small code, small living time, small tweaking (but important), etc.

I read that linked thread but now I have to go, when I'll be back to home I'll save it... Perhaps if I'll take a break during day-time I'll use my phone to save that thread as PDF... Thanks for the link.

Edit> That RotatingMover - written RED can be removed - AND won't help here Class'Mover' definitely is not class 'RotatingMover' AND is pointless, else code will simply except it if you don't use it - was my over-thinking.

Code: Select all

      if ( M.Class == Class'Mover' || M.Class == Class'MixMover' || M.Class == Class'LoopMover'
      || M.Class == Class'GradualMover' || M.Class == Class'ElevatorMover' || M.Class == Class'AttachMover'|| M.Class == Class'AssertMover') //Completely excepting any RotatingMover