mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
feat(NetworkTransformReliable): Added SendIntervalMultiplier to optionally reduce bandwidth (#3424)
* NetworkTransformReliable - formatting for consistancy / legibility * feat(NetworkTransformReliable): Added SendIntervalMultiplier * fixed conflict * formatting * formatting * formatting * formatting * formatting * indention * syntax * syntax * formatting * syntax * syntax * Restored formatting changes * one more formatting revert * Update NetworkTransformReliable.cs --------- Co-authored-by: mischa <16416509+vis2k@users.noreply.github.com>
This commit is contained in:
parent
50a8ce6e4f
commit
41ae4833b8
@ -11,9 +11,18 @@ public class NetworkTransformReliable : NetworkTransformBase
|
||||
[Header("Sync Only If Changed")]
|
||||
[Tooltip("When true, changes are not sent unless greater than sensitivity values below.")]
|
||||
public bool onlySyncOnChange = true;
|
||||
float onlySyncOnChangeInterval => onlySyncOnChangeCorrectionMultiplier * sendIntervalMultiplier;
|
||||
uint sendIntervalCounter = 0;
|
||||
double lastSendIntervalTime = double.MinValue;
|
||||
|
||||
[Tooltip("If we only sync on change, then we need to correct old snapshots if more time than sendInterval * multiplier has elapsed.\n\nOtherwise the first move will always start interpolating from the last move sequence's time, which will make it stutter when starting every time.")]
|
||||
public float onlySyncOnChangeCorrectionMultiplier = 2;
|
||||
|
||||
[Header("Send Interval Multiplier")]
|
||||
[Tooltip("Check/Sync every multiple of Network Manager send interval (= 1 / NM Send Rate), instead of every send interval.")]
|
||||
[Range(1, 120)]
|
||||
public uint sendIntervalMultiplier = 3;
|
||||
|
||||
[Header("Rotation")]
|
||||
[Tooltip("Sensitivity of changes needed before an updated state is sent over the network")]
|
||||
public float rotationSensitivity = 0.01f;
|
||||
@ -47,8 +56,9 @@ public class NetworkTransformReliable : NetworkTransformBase
|
||||
// Used to store last sent snapshots
|
||||
protected TransformSnapshot last;
|
||||
|
||||
protected int lastClientCount = 1;
|
||||
|
||||
// update //////////////////////////////////////////////////////////////
|
||||
// Update applies interpolation.
|
||||
void Update()
|
||||
{
|
||||
// if server then always sync to others.
|
||||
@ -58,18 +68,19 @@ void Update()
|
||||
else if (isClient) UpdateClient();
|
||||
}
|
||||
|
||||
// LateUpdate sets dirty.
|
||||
// movement scripts may change positions in Update.
|
||||
// use LateUpdate to ensure changes are detected in the same frame.
|
||||
// otherwise this may run before user update, delaying detection until next frame.
|
||||
// this would cause visible jitter.
|
||||
void LateUpdate()
|
||||
{
|
||||
// set dirty to trigger OnSerialize. either always, or only if changed.
|
||||
if (isServer || (IsClientWithAuthority && NetworkClient.ready)) // is NetworkClient.ready even needed?
|
||||
// It has to be checked in LateUpdate() for onlySyncOnChange to avoid
|
||||
// the possibility of Update() running first before the object's movement
|
||||
// script's Update(), which then causes NT to send every alternate frame
|
||||
// instead.
|
||||
if (isServer || (IsClientWithAuthority && NetworkClient.ready))
|
||||
{
|
||||
if (!onlySyncOnChange || Changed(Construct()))
|
||||
if (sendIntervalCounter == sendIntervalMultiplier && (!onlySyncOnChange || Changed(Construct())))
|
||||
SetDirty();
|
||||
|
||||
CheckLastSendTime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,6 +137,19 @@ protected virtual void UpdateClient()
|
||||
TransformSnapshot computed = TransformSnapshot.Interpolate(from, to, t);
|
||||
Apply(computed, to);
|
||||
}
|
||||
|
||||
lastClientCount = clientSnapshots.Count;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckLastSendTime()
|
||||
{
|
||||
// timeAsDouble not available in older Unity versions.
|
||||
if (AccurateInterval.Elapsed(NetworkTime.localTime, NetworkServer.sendInterval, ref lastSendIntervalTime))
|
||||
{
|
||||
if (sendIntervalCounter == sendIntervalMultiplier)
|
||||
sendIntervalCounter = 0;
|
||||
sendIntervalCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,6 +197,16 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
|
||||
// initial
|
||||
if (initialState)
|
||||
{
|
||||
// If there is a last serialized snapshot, we use it.
|
||||
// This prevents the new client getting a snapshot that is different
|
||||
// from what the older clients last got. If this happens, and on the next
|
||||
// regular serialisation the delta compression will get wrong values.
|
||||
// Notes:
|
||||
// 1. Interestingly only the older clients have it wrong, because at the end
|
||||
// of this function, last = snapshot which is the initial state's snapshot
|
||||
// 2. Regular NTR gets by this bug because it sends every frame anyway so initialstate
|
||||
// snapshot constructed would have been the same as the last anyway.
|
||||
if (last.remoteTime > 0) snapshot = last;
|
||||
if (syncPosition) writer.WriteVector3(snapshot.position);
|
||||
if (syncRotation)
|
||||
{
|
||||
@ -209,9 +243,6 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
|
||||
Compression.ScaleToLong(snapshot.scale, scalePrecision, out Vector3Long quantized);
|
||||
DeltaCompression.Compress(writer, lastSerializedScale, quantized);
|
||||
}
|
||||
|
||||
// int written = writer.Position - before;
|
||||
// Debug.Log($"{name} compressed to {written} bytes");
|
||||
}
|
||||
|
||||
// save serialized as 'last' for next delta compression
|
||||
@ -294,12 +325,11 @@ protected virtual void OnClientToServerSync(Vector3? position, Quaternion? rotat
|
||||
RewriteHistory(
|
||||
serverSnapshots,
|
||||
connectionToClient.remoteTimeStamp,
|
||||
NetworkTime.localTime, // arrival remote timestamp. NOT remote timeline.
|
||||
NetworkServer.sendInterval, // Unity 2019 doesn't have timeAsDouble yet
|
||||
NetworkTime.localTime, // arrival remote timestamp. NOT remote timeline.
|
||||
NetworkServer.sendInterval * sendIntervalMultiplier, // Unity 2019 doesn't have timeAsDouble yet
|
||||
target.localPosition,
|
||||
target.localRotation,
|
||||
target.localScale);
|
||||
// Debug.Log($"{name}: corrected history on server to fix initial stutter after not sending for a while.");
|
||||
}
|
||||
|
||||
// add a small timeline offset to account for decoupled arrival of
|
||||
@ -319,17 +349,16 @@ protected virtual void OnServerToClientSync(Vector3? position, Quaternion? rotat
|
||||
|
||||
// 'only sync on change' needs a correction on every new move sequence.
|
||||
if (onlySyncOnChange &&
|
||||
NeedsCorrection(clientSnapshots, NetworkClient.connection.remoteTimeStamp, NetworkClient.sendInterval, onlySyncOnChangeCorrectionMultiplier))
|
||||
NeedsCorrection(clientSnapshots, NetworkClient.connection.remoteTimeStamp, NetworkClient.sendInterval * sendIntervalMultiplier, onlySyncOnChangeInterval))
|
||||
{
|
||||
RewriteHistory(
|
||||
clientSnapshots,
|
||||
NetworkClient.connection.remoteTimeStamp, // arrival remote timestamp. NOT remote timeline.
|
||||
NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet
|
||||
NetworkClient.sendInterval,
|
||||
NetworkClient.connection.remoteTimeStamp, // arrival remote timestamp. NOT remote timeline.
|
||||
NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet
|
||||
NetworkClient.sendInterval * sendIntervalMultiplier,
|
||||
target.localPosition,
|
||||
target.localRotation,
|
||||
target.localScale);
|
||||
// Debug.Log($"{name}: corrected history on client to fix initial stutter after not sending for a while.");
|
||||
}
|
||||
|
||||
// add a small timeline offset to account for decoupled arrival of
|
||||
|
Loading…
Reference in New Issue
Block a user