Facepunch / garrysmod-issues

Garry's Mod issue tracker
139 stars 56 forks source link

ENTITY:GetVelocity( ) is glitchy after server runs for over 30 minutes #774

Open Acecool opened 10 years ago

Acecool commented 10 years ago

Regardless of using sandbox, base, etc game-modes. When using GetVelocity, everything works fine. After about 30 minutes, it starts getting jittery and returns incorrect values client-side. Server-side reports properly.

The longer a server is open / running, the worse it gets, but 30 minutes seems to be around the exact moment it starts.

I had my dev-server run for 4 days, and it would report to the client: Correct speed, half correct speed, correct speed, half correct speed.

Possibly other incorrect values in-between, but I noticed it would deliver around half the correct value, and it would be too jittery to use as a hud-output for speed.

I could take an average, but even when taking an average, using a value half the correct value will have a big impact on calculations.

I'm working on a replacement for client-side GetVelocity called GetSpeed which takes the dT vs dPosition and calculates a "speed"; alternatively, it could be networked but the best way would be for this issue to be fixed.

I'll post some code when it's done; will post later today or tomorrow albeit we're having brown-outs so could be by Thursday.

Edit: Actually, this may have been fixed. I had this issue for the longest time, and it would show after 30 minutes. Had the server up for 4 hours after updating everything and it seems fine. If this has been fixed, please remove.

I'll keep the server up and post updates if it still exists.

Acecool commented 10 years ago

Update: It's no longer occurring within the first 30 minutes; seems to occur after 3- 4 hours.

Acecool commented 10 years ago

Update: I created a replacement which used pos1 - pos2 length, and also pos1 distance pos2. If I updated it every .15 seconds, it seemed ok; I'd return the old value until an update came out. If I went to 0.05 between updates, it would jitter. The jitter is in the opposite direction though. Anything under 0.25 seems to be weird...

GetVelocity jitters under what speed it should be at. the GetSpeed I created jitters above the speed I should be getting.

Tried many different things in here which is why it's commented out to hell. The issue still occurs when the server has been up long periods. Weapon sway / bob scales used to jitter after 30 minutes; the speedometer used to always take a little longer, I was incorrect thinking they occurred together, I believe...

So, because the values are so unpredictable, even using an average doesn't resolve the issue.

function ENTITY:GetSpeed( )
    // Set up vars
    if ( !self.__LastLocation ) then self.__LastLocation = self:GetPos( ); end
    if ( !self.__LastSpeed ) then self.__LastSpeed = 0; end
    if ( !self.__LastLocationTime ) then self.__LastLocationTime = CurTime( ); end

    // Below 0.25 it's irradic after server is up a long time; same as GetVelocity albeit this appears to show above instead of below
    // most of the time.
    if ( CurTime( ) - self.__LastLocationTime < 0.05 ) then return self.__LastSpeed; end

    // Tried both methods for getting distance.
    -- local _dist = self:GetPos( ):Distance( self.__LastLocation );
    local _dist = ( self:GetPos( ) - self.__LastLocation ):Length( );

    // Just makes sure that it's moving instead of just wobbling ( vehicle ), then does the conversion for speed
    _dist = ( _dist < 1 ) && 0 || ( _dist / ( CurTime( ) - self.__LastLocationTime ) );

    // Tried doing it separately instead of above, same
    -- _dist = _dist / ( RealTime( ) - self.__LastLocationTime )

    // Cache
    self.__LastSpeed = _dist

    // Tried doing it this way, without using the above calc, just set above to _dist instead of doing calc within, same result.
    //self.__LastSpeed = ( _dist * ( CurTime( ) - self.__LastLocationTime ) ) / CONVERSION_UNITS_TO_MILES;

    // Printing for testing purposes.
    -- print( ( _dist / ( CurTime( ) - self.__LastLocationTime ) ))

    // Update cache vals
    self.__LastLocation = self:GetPos( );
    self.__LastLocationTime = CurTime( );

    // Return, also tried different methods of output
    return _dist //self.__LastSpeed; // / CONVERSION_UNITS_TO_MILES;
end

As a final test; I tried networking the SERVER value to the client every 0.05 seconds. The speed shows absolutely smooth with no hiccups at all. Some value is losing precision after x time on the server; I wonder if this is related to previous loss of precision bugs.

Acecool commented 10 years ago

Changed link to Youtube... http://youtu.be/O-F59NvI6R0

Sorry about the image in the bottom right ( Most of the speedometer can be seen ); but all of it's using the same output speedometer. The GetVelocity is 100% of the time on the left of the screen as text output.

I switch between the above GetSpeed, GetVelocity and the new networked thing I tried.

The server was up for over 24 hours in this video. It usually starts around 3-10 hours of being up.

GetVelocity can be up to 50% different; for example it will report the correct value some of the time, and some of the time it will report half of the actual value. That was on a test with the server up for around 4-5 days.

In the video, you'll see that GetVelocity reports around 25% less than what it is at times. GetSpeed seems to report slightly faster instead of slower, at times.

The main issue is that there is no problem with GetVelocity until a few hours have gone by. I'm not sure if you recall, but there was, or is, an issue with bob/sway scale for weapon view-models. That occurs after 30 minutes of up-time. I had to re-write the entire system to omit it. There were a few other bugs which seem to have been caused after the server was running for a few hours or longer which would cause loss of precision in other functions.

The other notable thing in the video is when I get out of the vehicle and noclip, GetVelocity is spot on, no errors and no jittering. I think this is because Player movement is shared, while Vehicle movement is server-side only.

While noclipping, GetSpeed emulates GetVelocity and jitters.

I believe GetSpeed works on FRESH server-start, but I haven't tested that yet; I'll test it in a few hours once I'm back from running an errand.

Acecool commented 10 years ago

Update: When the server is freshly started; no issue using either GetVelocity or the GetSpeed functions.

Acecool commented 10 years ago

Here's the video after the server has been running for 1 hour. No issues. I'll keep checking in each hour until it glitches out. http://youtu.be/epvx7a7sjjY

Acecool commented 10 years ago

After 2:30 uptime; GetVelocity starts to glitch out. IT's small, but considering after 5 days uptime the desync is up to 50% this seems to be where it starts. It may be with the time, or something else causing it.

http://youtu.be/s_FGm9-5zEM

Edit: Seems to be random; after 1 hour I'm getting similar minor glitching after restart.

robotboy655 commented 10 years ago

Can you like do the same, but without any of your crap, like only on vanilla with some simple GetVelocity on the HUD?

Acecool commented 10 years ago

Absolutely; If you notice, on the left hand side where it says "Speed ( MPH ): xxx" That's using math.round( vehicle:GetVelocity( ) / units_to_mph ) as said in most of the videos.

You can see the text jumping around a lot, it happens regardless of rendering the speedometer, and as shown using the networked method and also showing GetVelocity after a fresh-server start, it moves fine. The speedometer is a nice graphical representation of the text because it can be hard to read the text, that's how much it jumps around.

Also, after the server was up for 5 days it was up to 50% off, example I'd be at 100 and it would show the proper 100 value and then jump to 50 then back up.

If you want me to do the same on Sandbox, I'll start up a secondary test server right now and give it a few hours for it to do the thing.

robotboy655 commented 10 years ago

I mean, without any other serverside or clientside crap you might have in those 2000 files of yours.

Acecool commented 10 years ago

Most of the files are helper-functions, and a lot is rewritten from default stuff. Example, the notify window was rewritten so the think hook doesn't run by default, it gets started on first and removed on last. Most of my hooks are done that way except ones that need to run.

And yeah; I launched a sandbox server with just:

//
// Conversions - Josh 'Acecool' Moser
//
// 1 unit = 0.75 inches. 
// 4/3 units = 1 inch - from this we base our calculations.
CONVERSION_UNITS_TO_INCHES      = 4 / 3; // 4/3 units per 1 inch, 16 units per foot
CONVERSION_UNITS_TO_FEET        = CONVERSION_UNITS_TO_INCHES * 12; // == 16 in game units
CONVERSION_UNITS_TO_METERS      = CONVERSION_UNITS_TO_FEET * 0.3048;
CONVERSION_UNITS_TO_MILES       = CONVERSION_UNITS_TO_FEET * 5280;
CONVERSION_UNITS_TO_KILOMETERS  = CONVERSION_UNITS_TO_FEET * 3280.84;
CONVERSION_UNITS_TO_MPH         = CONVERSION_UNITS_TO_INCHES * 17.6;
CONVERSION_UNITS_TO_KPH         = CONVERSION_UNITS_TO_INCHES * 10.936133;

COLOR_WHITE         = Color( 255, 255, 255, 255 );

hook.Add( "HUDPaint", "VEHICLE:GetVelocity", function( )
    local _p = LocalPlayer( );
    local _v = _p:GetVehicle( );
    if ( !IsValid( _v ) ) then return; end

    local _speed = _v:GetVelocity( ):Length( ) / CONVERSION_UNITS_TO_MPH;

    draw.SimpleText( "Speed ( MPH ): ", "default", 10, ScrH( ) - 115, COLOR_WHITE )
    draw.SimpleText( math.Round( _speed, 0 ), "default", 120, ScrH( ) - 115, COLOR_WHITE )
end );
Acecool commented 10 years ago

Even Freeman uses Lerp to "correct" GetVelocity, spoke with him earlier. Anyway, server has been up a few hours and am having same issue; not as bad just yet, but since I'm already seeing a minor glitch after 2 ish hours, waiting to see how bad it gets.

Acecool commented 10 years ago

Here it is on Vanilla Code Sandbox except for the code below in cl_init.lua at the bottom:

http://youtu.be/IgkbdUS4pWo

//
// Conversions - Josh 'Acecool' Moser
//
// 1 unit = 0.75 inches. 
// 4/3 units = 1 inch - from this we base our calculations.
CONVERSION_UNITS_TO_INCHES      = 4 / 3; // 4/3 units per 1 inch, 16 units per foot
CONVERSION_UNITS_TO_FEET        = CONVERSION_UNITS_TO_INCHES * 12; // == 16 in game units
CONVERSION_UNITS_TO_METERS      = CONVERSION_UNITS_TO_FEET * 0.3048;
CONVERSION_UNITS_TO_MILES       = CONVERSION_UNITS_TO_FEET * 5280;
CONVERSION_UNITS_TO_KILOMETERS  = CONVERSION_UNITS_TO_FEET * 3280.84;
CONVERSION_UNITS_TO_MPH         = CONVERSION_UNITS_TO_INCHES * 17.6;
CONVERSION_UNITS_TO_KPH         = CONVERSION_UNITS_TO_INCHES * 10.936133;

COLOR_WHITE         = Color( 255, 255, 255, 255 );

hook.Add( "HUDPaint", "VEHICLE:GetVelocity", function( )
    local _p = LocalPlayer( );
    local _v = _p:GetVehicle( );
    if ( !IsValid( _v ) ) then return; end

    local _speed = _v:GetVelocity( ):Length( ) / CONVERSION_UNITS_TO_MPH;

    draw.SimpleText( "Speed ( MPH ): ", "default", 10, ScrH( ) - 115, COLOR_WHITE )
    draw.SimpleText( math.Round( _speed, 0 ), "default", 120, ScrH( ) - 115, COLOR_WHITE )
end );

The server was up for 4-5 hours. It does have TDM cars and other things like some of your tools. If you want to to run it on a 100% vanilla sandbox without addons, I can do that too. In fact, I'll let that run over-night.

But it's an issue even Freeman had to deal with using a Lerp method ( Lerping didn't work for me the same way as it did for him; I use an average and then lerp 5% to the current velocity from the average ) which reduces jittering somewhat; but I want to leave the server up for a few days to see if I can stop the jittering when it gets to the 50% jittering issue.

Acecool commented 10 years ago

Uploading a new video.

Using GetVelocity, showing how 50% is lost, here's the odd part. While traveling 40 mph, it would drop down to 20 quite frequently, but at some points in the video it doesn't up to 80mph....

Using a fully client-side system to obtain speed by getting the change in distance in relation to time ( FrameTime / RealFrameTime was used ) where time was then turned into an hourly rate and miles per hour was obtained; it would hang around the lower 20mph value while traveling 40.

Networking the value, no issues other than having to sync it in real-time..... I think either GetPos loses precision or something else loses precision over time. This is a real bug affecting many users.

http://youtu.be/zisJKXoLgwY

Here's the client-side GetSpeed:

//
// Test replacement for GetVelocity - Josh 'Acecool' Moser
//
function ENTITY:GetSpeed( )
    local MAX_CACHED_VELOCITIES = 10;

    // INIT
    if ( !self.__CachedGetVelocity ) then self.__CachedGetVelocity = { }; end
    if ( !self.__CachedGetVelocityKey ) then self.__CachedGetVelocityKey = 0; end

    // Logic
    local _vel = self:GetCurrentSpeed( );
    self.__CachedGetVelocityKey = ( self.__CachedGetVelocityKey + 1 ) % MAX_CACHED_VELOCITIES;

    local _average = 0;
    local _count = 0;
    for k, v in pairs( self.__CachedGetVelocity ) do
        _average = _average + v;
        _count = _count + 1;
    end
    _average = _average / _count;
    self.__CachedGetVelocity[ self.__CachedGetVelocityKey ] = _vel;
    _vel = Lerp( 0.05, _average, _vel );

    return _vel;
end
Acecool commented 10 years ago

I've already done it on a vanilla sandbox except for tdm cars and some of robot tools; although I unsubbed to his tools.

Fine, I'll remove the addons and launch a sandbox server and let it run for hours / days and we'll see what happens. It'll run completely stock code except what I showed with server and client output; as I have done in the past with just client code.

You're saying addon vehicles can cause this issue? Are you saying Robots tools cause this? I don't know what you're trying to prove by saying this.

Acecool commented 10 years ago

I've already reproduced it on a vanilla sandbox server except for that code to output the glitch on the hud, as requested. I had TDM cars there so I'd have a vehicle that drives faster than 20... It can be reproduced, and has been reproduced, and is affecting a lot of people other than me.

I'll make one more video showing fully vanilla sandbox with NO addons, except the hud code added to cl_init.

You need to drop your personal vendetta against me, Robot and Matt. It serves no purpose when trying to make the game better for everyone when I post a legitimate bug-report. Robot has been spamming reports, some of which CAN'T be reproduced, or are the cause of his faulty code. Yet, he marks them as bugs because he believes he is some god of coding, just like you do.

Acecool commented 10 years ago

Here's the second video on sandbox, except this time it's 100% vanilla sandbox server aside from

//
// Conversions - Josh 'Acecool' Moser
//
// 1 unit = 0.75 inches. 
// 4/3 units = 1 inch - from this we base our calculations.
CONVERSION_UNITS_TO_INCHES      = 4 / 3; // 4/3 units per 1 inch, 16 units per foot
CONVERSION_UNITS_TO_FEET        = CONVERSION_UNITS_TO_INCHES * 12; // == 16 in game units
CONVERSION_UNITS_TO_METERS      = CONVERSION_UNITS_TO_FEET * 0.3048;
CONVERSION_UNITS_TO_MILES       = CONVERSION_UNITS_TO_FEET * 5280;
CONVERSION_UNITS_TO_KILOMETERS  = CONVERSION_UNITS_TO_FEET * 3280.84;
CONVERSION_UNITS_TO_MPH         = CONVERSION_UNITS_TO_INCHES * 17.6;
CONVERSION_UNITS_TO_KPH         = CONVERSION_UNITS_TO_INCHES * 10.936133;

COLOR_WHITE         = Color( 255, 255, 255, 255 );

hook.Add( "HUDPaint", "VEHICLE:GetVelocity", function( )
    local _p = LocalPlayer( );
    local _v = _p:GetVehicle( );
    if ( !IsValid( _v ) ) then return; end

    local _speed = _v:GetVelocity( ):Length( ) / CONVERSION_UNITS_TO_MPH;

    draw.SimpleText( "Speed ( MPH ): ", "default", 10, ScrH( ) - 115, COLOR_WHITE )
    draw.SimpleText( math.Round( _speed, 0 ), "default", 120, ScrH( ) - 115, COLOR_WHITE )
end );

running in cl_init to show speed.

As you can see, it is glitching after only a few hours of running. The number should be perfectly smooth, and it was after I just started the server. There are no addons at all; it's plain jane sandbox.

I'll leave this server up for a few days, and I'll post another video in a few days showing what it looks like. I don't have any other SRCDS servers running while this one is running, and even if I close Garry's Mod, and rejoin, it still happens. This is in the server-code. GetVelocity does work fine when used on players because player movement is predicted and shared. Vehicle movement is done 100% via server-side.

This can be proven easily; take a half-life model which is common in maps which has no physics compiled in it, which can normally be walked through. Recompile it with physics and upload it to the server. Try walking through it, you'll notice rubber banding when walking through because the client predicts that you can while the server says no. Try driving through it, there is no rubber banding. This is where the problem is coming from.

http://youtu.be/vdix_NU9OLw

I do have an idea of how I can improve on my GetSpeed function; if the GetPos function is tainted for vehicles, I wonder if it would work if I used _v:GetDriver( ):GetPos( ) instead of just _v:GetPos( ) in the current client-side calculation for getting the speed. I'll try it when the few days are up and I've proven my point... again.

freemmaann commented 10 years ago

Have this issue aswel, Gmod reinstalled so nothing could interfere.

For it me it happens instantly, dont have to wait for abit for it to show.

Tiny fluctuations, nothing big, but still not precise.

freemmaann commented 10 years ago

Not that tiny. I expect the server sending the most recent value, then the client receiving that.

Problem is that the client gets not the most recently known velocity of the server.

freemmaann commented 10 years ago

Exactly. There are sulotions, like Lerping the number or averaging the velocity. Seems kinda hacky tho.

Acecool commented 10 years ago

After about a day: http://youtu.be/MZCGlms-99A

It's jumping between 37-40. Faster cars would show more but it's completely vanilla. If you compare to the first video I did on sandbox / when it first started, it was perfectly smooth. As the server stays up longer it starts jittering.

JamesMinoucha commented 2 months ago

freemmaann

What a coincidence that I see you here 😂.

JamesMinoucha commented 2 months ago

After about a day: http://youtu.be/MZCGlms-99A

It's jumping between 37-40. Faster cars would show more but it's completely vanilla. If you compare to the first video I did on sandbox / when it first started, it was perfectly smooth. As the server stays up longer it starts jittering.

Was this bug fixed? It seems that the issue is still open, yeah there is research to do.