NTRCustomSendInterval - formatting

This commit is contained in:
MrGadget1024 2023-02-25 21:30:02 -05:00
parent 40d8e0268d
commit b0b039f468

View File

@ -6,19 +6,21 @@
public class NTRCustomSendInterval : NetworkTransformBase public class NTRCustomSendInterval : NetworkTransformBase
{ {
uint sendIntervalCounter = 0;
double lastSendIntervalTime = double.MinValue;
float onlySyncOnChangeInterval => onlySyncOnChangeCorrectionMultiplier * sendIntervalMultiplier;
[Header("Sync Only If Changed")] [Header("Sync Only If Changed")]
[Tooltip("When true, changes are not sent unless greater than sensitivity values below.")] [Tooltip("When true, changes are not sent unless greater than sensitivity values below.")]
public bool onlySyncOnChange = true; public bool onlySyncOnChange = true;
[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.")] [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; public float onlySyncOnChangeCorrectionMultiplier = 2;
private float onlySyncOnChangeInterval => onlySyncOnChangeCorrectionMultiplier * sendIntervalMultiplier;
// uint so non negative. // uint so non negative.
[Header("Send Interval Multiplier")] [Header("Send Interval Multiplier")]
[Tooltip("Send every multiple of Network Manager send interval (= 1 / NM Send Rate).")] [Tooltip("Send every multiple of Network Manager send interval (= 1 / NM Send Rate).")]
public uint sendIntervalMultiplier = 3; public uint sendIntervalMultiplier = 3;
private uint sendIntervalCounter = 0;
private double lastSendIntervalTime = double.MinValue;
[Header("Rotation")] [Header("Rotation")]
[Tooltip("Sensitivity of changes needed before an updated state is sent over the network")] [Tooltip("Sensitivity of changes needed before an updated state is sent over the network")]
@ -39,6 +41,12 @@ public class NTRCustomSendInterval : NetworkTransformBase
[Range(0.00_01f, 1f)] // disallow 0 division. 1mm to 1m precision is enough range. [Range(0.00_01f, 1f)] // disallow 0 division. 1mm to 1m precision is enough range.
public float scalePrecision = 0.01f; // 1 cm public float scalePrecision = 0.01f; // 1 cm
public Action<Vector3, Vector3> VelRotChangedAction;
[Header("Debug Velocity")]
public Vector3 velocity;
public Vector3 angVelocity;
// delta compression needs to remember 'last' to compress against // delta compression needs to remember 'last' to compress against
protected Vector3Long lastSerializedPosition = Vector3Long.zero; protected Vector3Long lastSerializedPosition = Vector3Long.zero;
protected Vector3Long lastDeserializedPosition = Vector3Long.zero; protected Vector3Long lastDeserializedPosition = Vector3Long.zero;
@ -51,11 +59,6 @@ public class NTRCustomSendInterval : NetworkTransformBase
protected int lastClientCount = 1; protected int lastClientCount = 1;
protected override void Awake()
{
base.Awake();
}
// update ////////////////////////////////////////////////////////////// // update //////////////////////////////////////////////////////////////
void Update() void Update()
{ {
@ -75,8 +78,7 @@ void LateUpdate()
// instead. // instead.
if (isServer || (IsClientWithAuthority && NetworkClient.ready)) // is NetworkClient.ready even needed? if (isServer || (IsClientWithAuthority && NetworkClient.ready)) // is NetworkClient.ready even needed?
{ {
if (sendIntervalCounter == sendIntervalMultiplier && if (sendIntervalCounter == sendIntervalMultiplier && (!onlySyncOnChange || Changed(Construct())))
(!onlySyncOnChange || Changed(Construct())))
SetDirty(); SetDirty();
CheckLastSendTime(); CheckLastSendTime();
@ -105,9 +107,7 @@ protected virtual void UpdateServer()
// then we don't need to do anything. // then we don't need to do anything.
// -> connectionToClient is briefly null after scene changes: // -> connectionToClient is briefly null after scene changes:
// https://github.com/MirrorNetworking/Mirror/issues/3329 // https://github.com/MirrorNetworking/Mirror/issues/3329
if (syncDirection == SyncDirection.ClientToServer && if (syncDirection == SyncDirection.ClientToServer && connectionToClient != null && !isOwned)
connectionToClient != null &&
!isOwned)
{ {
if (serverSnapshots.Count > 0) if (serverSnapshots.Count > 0)
{ {
@ -130,9 +130,6 @@ protected virtual void UpdateServer()
protected virtual void UpdateClient() protected virtual void UpdateClient()
{ {
//if (!inFocus) Console.WriteLine($"Update Frame Time = {Time.time - lastUpdateTime}");
//lastUpdateTime = Time.time;
// client authority, and local player (= allowed to move myself)? // client authority, and local player (= allowed to move myself)?
if (!IsClientWithAuthority) if (!IsClientWithAuthority)
{ {
@ -170,18 +167,23 @@ protected virtual void UpdateClient()
protected virtual void CheckLastSendTime() protected virtual void CheckLastSendTime()
{ {
if ( // timeAsDouble not available in older Unity versions.
#if !UNITY_2020_3_OR_NEWER #if !UNITY_2020_3_OR_NEWER
AccurateInterval.Elapsed(NetworkTime.localTime, NetworkServer.sendInterval, ref lastSendIntervalTime)) if (AccurateInterval.Elapsed(NetworkTime.localTime, NetworkServer.sendInterval, ref lastSendIntervalTime))
{
if (sendIntervalCounter == sendIntervalMultiplier)
sendIntervalCounter = 0;
sendIntervalCounter++;
}
#else #else
AccurateInterval.Elapsed(Time.timeAsDouble, NetworkServer.sendInterval, ref lastSendIntervalTime)) if (AccurateInterval.Elapsed(Time.timeAsDouble, NetworkServer.sendInterval, ref lastSendIntervalTime))
#endif
{ {
if (sendIntervalCounter == sendIntervalMultiplier) if (sendIntervalCounter == sendIntervalMultiplier)
sendIntervalCounter = 0; sendIntervalCounter = 0;
sendIntervalCounter++; sendIntervalCounter++;
} }
} }
#endif
// check if position / rotation / scale changed since last sync // check if position / rotation / scale changed since last sync
protected virtual bool Changed(TransformSnapshot current) => protected virtual bool Changed(TransformSnapshot current) =>
@ -236,9 +238,12 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
// of the function, last = snapshot which is the initial state's snapshot // of the 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 // 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. // snapshot constructed would have been the same as the last anyway.
if (last.remoteTime > 0) snapshot = last; if (last.remoteTime > 0)
snapshot = last;
if (syncPosition)
writer.WriteVector3(snapshot.position);
if (syncPosition) writer.WriteVector3(snapshot.position);
if (syncRotation) if (syncRotation)
{ {
// (optional) smallest three compression for now. no delta. // (optional) smallest three compression for now. no delta.
@ -247,7 +252,9 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
else else
writer.WriteQuaternion(snapshot.rotation); writer.WriteQuaternion(snapshot.rotation);
} }
if (syncScale) writer.WriteVector3(snapshot.scale);
if (syncScale)
writer.WriteVector3(snapshot.scale);
} }
// delta // delta
else else
@ -260,6 +267,7 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
Compression.ScaleToLong(snapshot.position, positionPrecision, out Vector3Long quantized); Compression.ScaleToLong(snapshot.position, positionPrecision, out Vector3Long quantized);
DeltaCompression.Compress(writer, lastSerializedPosition, quantized); DeltaCompression.Compress(writer, lastSerializedPosition, quantized);
} }
if (syncRotation) if (syncRotation)
{ {
// (optional) smallest three compression for now. no delta. // (optional) smallest three compression for now. no delta.
@ -268,20 +276,20 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
else else
writer.WriteQuaternion(snapshot.rotation); writer.WriteQuaternion(snapshot.rotation);
} }
if (syncScale) if (syncScale)
{ {
// quantize -> delta -> varint // quantize -> delta -> varint
Compression.ScaleToLong(snapshot.scale, scalePrecision, out Vector3Long quantized); Compression.ScaleToLong(snapshot.scale, scalePrecision, out Vector3Long quantized);
DeltaCompression.Compress(writer, lastSerializedScale, quantized); DeltaCompression.Compress(writer, lastSerializedScale, quantized);
} }
// int written = writer.Position - before;
// Console.WriteLine($"{name} compressed to {written} bytes");
} }
// save serialized as 'last' for next delta compression // save serialized as 'last' for next delta compression
if (syncPosition) Compression.ScaleToLong(snapshot.position, positionPrecision, out lastSerializedPosition); if (syncPosition)
if (syncScale) Compression.ScaleToLong(snapshot.scale, scalePrecision, out lastSerializedScale); Compression.ScaleToLong(snapshot.position, positionPrecision, out lastSerializedPosition);
if (syncScale)
Compression.ScaleToLong(snapshot.scale, scalePrecision, out lastSerializedScale);
// set 'last' // set 'last'
last = snapshot; last = snapshot;
@ -296,7 +304,9 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
// initial // initial
if (initialState) if (initialState)
{ {
if (syncPosition) position = reader.ReadVector3(); if (syncPosition)
position = reader.ReadVector3();
if (syncRotation) if (syncRotation)
{ {
// (optional) smallest three compression for now. no delta. // (optional) smallest three compression for now. no delta.
@ -305,7 +315,9 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
else else
rotation = reader.ReadQuaternion(); rotation = reader.ReadQuaternion();
} }
if (syncScale) scale = reader.ReadVector3();
if (syncScale)
scale = reader.ReadVector3();
} }
// delta // delta
else else
@ -316,6 +328,7 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedPosition); Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedPosition);
position = Compression.ScaleToFloat(quantized, positionPrecision); position = Compression.ScaleToFloat(quantized, positionPrecision);
} }
if (syncRotation) if (syncRotation)
{ {
// (optional) smallest three compression for now. no delta. // (optional) smallest three compression for now. no delta.
@ -324,6 +337,7 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
else else
rotation = reader.ReadQuaternion(); rotation = reader.ReadQuaternion();
} }
if (syncScale) if (syncScale)
{ {
Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedScale); Vector3Long quantized = DeltaCompression.Decompress(reader, lastDeserializedScale);
@ -333,12 +347,29 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
// handle depending on server / client / host. // handle depending on server / client / host.
// server has priority for host mode. // server has priority for host mode.
if (isServer) OnClientToServerSync(position, rotation, scale); if (isServer)
else if (isClient) OnServerToClientSync(position, rotation, scale); OnClientToServerSync(position, rotation, scale);
else if (isClient)
OnServerToClientSync(position, rotation, scale);
// save deserialized as 'last' for next delta compression // save deserialized as 'last' for next delta compression
if (syncPosition) Compression.ScaleToLong(position.Value, positionPrecision, out lastDeserializedPosition); if (syncPosition)
if (syncScale) Compression.ScaleToLong(scale.Value, scalePrecision, out lastDeserializedScale); Compression.ScaleToLong(position.Value, positionPrecision, out lastDeserializedPosition);
if (syncScale)
Compression.ScaleToLong(scale.Value, scalePrecision, out lastDeserializedScale);
}
protected override void Apply(TransformSnapshot interpolated, TransformSnapshot endGoal)
{
if (!isOwned)
{
velocity = (transform.position - interpolated.position) / Time.deltaTime;
angVelocity = (transform.rotation.eulerAngles - interpolated.rotation.eulerAngles) / Time.deltaTime;
VelRotChangedAction?.Invoke(velocity, angVelocity);
}
// must call base after, or we'll get zeros
base.Apply(interpolated, endGoal);
} }
// sync //////////////////////////////////////////////////////////////// // sync ////////////////////////////////////////////////////////////////
@ -353,18 +384,16 @@ protected virtual void OnClientToServerSync(Vector3? position, Quaternion? rotat
if (serverSnapshots.Count >= connectionToClient.snapshotBufferSizeLimit) return; if (serverSnapshots.Count >= connectionToClient.snapshotBufferSizeLimit) return;
// 'only sync on change' needs a correction on every new move sequence. // 'only sync on change' needs a correction on every new move sequence.
if (onlySyncOnChange && if (onlySyncOnChange && NeedsCorrection(serverSnapshots, connectionToClient.remoteTimeStamp, NetworkServer.sendInterval, onlySyncOnChangeInterval))
NeedsCorrection(serverSnapshots, connectionToClient.remoteTimeStamp, NetworkServer.sendInterval, onlySyncOnChangeInterval))
{ {
RewriteHistory( RewriteHistory(
serverSnapshots, serverSnapshots,
connectionToClient.remoteTimeStamp, connectionToClient.remoteTimeStamp,
NetworkTime.localTime, // arrival remote timestamp. NOT remote timeline. NetworkTime.localTime, // arrival remote timestamp. NOT remote timeline.
NetworkServer.sendInterval * sendIntervalMultiplier, // Unity 2019 doesn't have timeAsDouble yet NetworkServer.sendInterval * sendIntervalMultiplier, // Unity 2019 doesn't have timeAsDouble yet
target.localPosition, target.localPosition,
target.localRotation, target.localRotation,
target.localScale); target.localScale);
// Console.WriteLine($"{name}: corrected history on server to fix initial stutter after not sending for a while.");
} }
AddSnapshot(serverSnapshots, connectionToClient.remoteTimeStamp + NetworkServer.sendInterval * sendIntervalMultiplier, position, rotation, scale); AddSnapshot(serverSnapshots, connectionToClient.remoteTimeStamp + NetworkServer.sendInterval * sendIntervalMultiplier, position, rotation, scale);
@ -382,13 +411,12 @@ protected virtual void OnServerToClientSync(Vector3? position, Quaternion? rotat
{ {
RewriteHistory( RewriteHistory(
clientSnapshots, clientSnapshots,
NetworkClient.connection.remoteTimeStamp, // arrival remote timestamp. NOT remote timeline. NetworkClient.connection.remoteTimeStamp, // arrival remote timestamp. NOT remote timeline.
NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet NetworkTime.localTime, // Unity 2019 doesn't have timeAsDouble yet
NetworkClient.sendInterval * sendIntervalMultiplier, NetworkClient.sendInterval * sendIntervalMultiplier,
target.localPosition, target.localPosition,
target.localRotation, target.localRotation,
target.localScale); target.localScale);
// Console.WriteLine($"{name}: corrected history on client to fix initial stutter after not sending for a while.");
} }
AddSnapshot(clientSnapshots, NetworkClient.connection.remoteTimeStamp + NetworkClient.sendInterval * sendIntervalMultiplier, position, rotation, scale); AddSnapshot(clientSnapshots, NetworkClient.connection.remoteTimeStamp + NetworkClient.sendInterval * sendIntervalMultiplier, position, rotation, scale);