This commit is contained in:
vis2k 2022-10-03 10:37:34 +02:00
parent 9b5145a7f7
commit f3cb8f973f
3 changed files with 77 additions and 0 deletions

View File

@ -93,6 +93,9 @@ public struct NetworkClientConfig
// call this from Unity's OnValidate
public void OnValidate()
{
// snapshot interpolation thresholds need to be <0 and >0
catchupNegativeThreshold = Math.Min(catchupNegativeThreshold, 0);
catchupPositiveThreshold = Math.Max(catchupPositiveThreshold, 0);
}
}
@ -245,6 +248,7 @@ public static void Connect(string address)
// Debug.Log($"Client Connect: {address}");
Debug.Assert(Transport.active != null, "There was no active transport when calling NetworkClient.Connect, If you are calling Connect manually then make sure to set 'Transport.active' first");
InitTimeInterpolation();
RegisterSystemHandlers(false);
Transport.active.enabled = true;
AddTransportHandlers();
@ -261,6 +265,7 @@ public static void Connect(Uri uri)
// Debug.Log($"Client Connect: {uri}");
Debug.Assert(Transport.active != null, "There was no active transport when calling NetworkClient.Connect, If you are calling Connect manually then make sure to set 'Transport.active' first");
InitTimeInterpolation();
RegisterSystemHandlers(false);
Transport.active.enabled = true;
AddTransportHandlers();
@ -1485,6 +1490,9 @@ internal static void NetworkEarlyUpdate()
// process all incoming messages first before updating the world
if (Transport.active != null)
Transport.active.ClientEarlyUpdate();
// time snapshot interpolation
UpdateTimeInterpolation();
}
// NetworkLateUpdate called after any Update/FixedUpdate/LateUpdate

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using UnityEngine;
namespace Mirror
{
@ -45,5 +46,72 @@ public static partial class NetworkClient
// average delivery time (standard deviation gives average jitter)
static ExponentialMovingAverage deliveryTimeEma;
// OnValidate: see NetworkClient.cs
// add snapshot & initialize client interpolation time if needed
// initialization called from Awake
static void InitTimeInterpolation()
{
// initialize EMA with 'emaDuration' seconds worth of history.
// 1 second holds 'sendRate' worth of values.
// multiplied by emaDuration gives n-seconds.
driftEma = new ExponentialMovingAverage(NetworkServer.config.sendRate * config.driftEmaDuration);
deliveryTimeEma = new ExponentialMovingAverage(NetworkServer.config.sendRate * config.deliveryTimeEmaDuration);
}
// see comments at the top of this file
public static void OnTimeSnapshot(TimeSnapshot snap)
{
// set local timestamp (= when it was received on our end)
snap.localTime = Time.timeAsDouble;
// (optional) dynamic adjustment
if (config.dynamicAdjustment)
{
// set bufferTime on the fly.
// shows in inspector for easier debugging :)
config.bufferTimeMultiplier = SnapshotInterpolation.DynamicAdjustment(
NetworkServer.config.sendInterval,
deliveryTimeEma.StandardDeviation,
config.dynamicAdjustmentTolerance
);
}
// insert into the buffer & initialize / adjust / catchup
SnapshotInterpolation.InsertAndAdjust(
snapshots,
snap,
ref localTimeline,
ref localTimescale,
NetworkServer.config.sendInterval,
config.bufferTime,
config.catchupSpeed,
config.slowdownSpeed,
ref driftEma,
config.catchupNegativeThreshold,
config.catchupPositiveThreshold,
ref deliveryTimeEma);
// Debug.Log($"inserted TimeSnapshot remote={snap.remoteTime:F2} local={snap.localTime:F2} total={snapshots.Count}");
}
// call this from early update, so the timeline is safe to use in update
static void UpdateTimeInterpolation()
{
// only while we have snapshots.
// timeline starts when the first snapshot arrives.
if (snapshots.Count > 0)
{
// progress local timeline.
SnapshotInterpolation.StepTime(Time.unscaledDeltaTime, ref localTimeline, localTimescale);
// progress local interpolation.
// TimeSnapshot doesn't interpolate anything.
// this is merely to keep removing older snapshots.
SnapshotInterpolation.StepInterpolation(snapshots, localTimeline, out _, out _, out double t);
// Debug.Log($"NetworkClient SnapshotInterpolation @ {localTimeline:F2} t={t:F2}");
}
}
}
}

View File

@ -24,6 +24,7 @@ public struct NetworkServerConfig
tickRate < int.MaxValue ? 1f / tickRate : 0; // for 30 Hz, that's 33ms
// Mirror currently sends every tick
public int sendRate => tickRate;
public float sendInterval => tickInterval;
// default settings in one place. used by both NetworkServer & Manager.