Skip to content

Commit

Permalink
Improve smoothness in tickrate
Browse files Browse the repository at this point in the history
  • Loading branch information
adammitchelldev committed Jan 14, 2021
1 parent 804d292 commit fbf8204
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
12 changes: 9 additions & 3 deletions OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static class Game
public const int NewNetcodeNetTickScale = 1; // Net tick every world frame
public const int Timestep = 40;
public const int TimestepJankThreshold = 250; // Don't catch up for delays larger than 250ms
public const double NetCatchupFactor = 0.25;
public const double NetCatchupFactor = 0.1;
public static InstalledMods Mods { get; private set; }
public static ExternalMods ExternalMods { get; private set; }

Expand Down Expand Up @@ -600,6 +600,8 @@ static void InnerLogicTick(OrderManager orderManager)
worldTimestep = Timestep;
else if (world.IsLoadingGameSave)
worldTimestep = 1;
else if (orderManager.IsStalling)
worldTimestep = 1;
else if (orderManager.CatchUpFrames > 0)
worldTimestep = (int)Math.Floor(world.Timestep / (1.0 + NetCatchupFactor * orderManager.CatchUpFrames)); // Smooth catchup
else
Expand Down Expand Up @@ -805,8 +807,11 @@ static void Loop()
var maxFramerate = Settings.Graphics.CapFramerate ? Settings.Graphics.MaxFramerate.Clamp(1, 1000) : 1000;
var renderInterval = 1000 / maxFramerate;

if (OrderManager.IsStalling)
logicInterval = 1;

// TODO: limit rendering if we are taking too long to catch up
if (OrderManager.CatchUpFrames > 0)
else if (OrderManager.CatchUpFrames > 0)
logicInterval = (int)Math.Floor(logicInterval / (1.0 + NetCatchupFactor * OrderManager.CatchUpFrames));

// Tick as fast as possible while restoring game saves, capping rendering at 5 FPS
Expand Down Expand Up @@ -835,7 +840,8 @@ static void Loop()
LogicTick();

// Force at least one render per tick during regular gameplay
if (!(OrderManager.CatchUpFrames > 0) && OrderManager.World != null && !OrderManager.World.IsLoadingGameSave && !OrderManager.World.IsReplay)
// TODO: Have OrderManager tell us when we should force render
if (!OrderManager.IsStalling && !(OrderManager.CatchUpFrames > 2) && OrderManager.World != null && !OrderManager.World.IsLoadingGameSave && !OrderManager.World.IsReplay)
renderBeforeNextTick = true;
}

Expand Down
4 changes: 4 additions & 0 deletions OpenRA.Game/Network/OrderManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public sealed class OrderManager : IDisposable
public int OrderLatency; // Set during lobby by a "SyncInfo" packet, see UnitOrders
public int NextOrderFrame;
public int CatchUpFrames { get; private set; }
public bool IsStalling { get; private set; }

public long LastTickTime = Game.RunTime;

Expand Down Expand Up @@ -197,6 +198,7 @@ void CheckSync(byte[] packet)

void CompensateForLatency()
{
// NOTE: subtract 1 because we are only interested in *excess* frames
var catchUpNetFrames = frameData.BufferSizeForClient(Connection.LocalClientId) - 1;
if (catchUpNetFrames < 0)
catchUpNetFrames = 0;
Expand Down Expand Up @@ -309,6 +311,8 @@ public bool TryTick()
willTick = frameData.IsReadyForFrame();
if (willTick)
ProcessOrders();

IsStalling = !willTick;
}

if (willTick)
Expand Down

0 comments on commit fbf8204

Please sign in to comment.