mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
delta: only sync on change
This commit is contained in:
parent
b5b02217ff
commit
114cbf0498
@ -22,6 +22,7 @@
|
||||
// buffer for bufferTime but end up closer to the original time
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mirror
|
||||
@ -83,13 +84,8 @@ public class NetworkTransformHybrid2022 : NetworkBehaviour
|
||||
[Tooltip("When true, changes are not sent unless greater than sensitivity values below.")]
|
||||
public bool onlySyncOnChange = true;
|
||||
|
||||
[Header("Sensitivity"), Tooltip("Sensitivity of changes needed before an updated state is sent over the network")]
|
||||
public float positionSensitivity = 0.01f;
|
||||
public float rotationSensitivity = 0.01f;
|
||||
public float scaleSensitivity = 0.01f;
|
||||
|
||||
// Used to store last sent snapshots
|
||||
protected TransformSnapshot lastSnapshot;
|
||||
protected TransformSnapshot last;
|
||||
|
||||
[Header("Compression")]
|
||||
[Tooltip("Position is rounded in order to drastically minimize bandwidth.\n\nFor example, a precision of 0.01 rounds to a centimeter. In other words, sub-centimeter movements aren't synced until they eventually exceeded an actual centimeter.\n\nDepending on how important the object is, a precision of 0.01-0.10 (1-10 cm) is recommended.\n\nFor example, even a 1cm precision combined with delta compression cuts the Benchmark demo's bandwidth in half, compared to sending every tiny change.")]
|
||||
@ -184,6 +180,29 @@ protected virtual void ApplySnapshot(TransformSnapshot interpolated)
|
||||
if (syncScale) target.localScale = interpolated.scale;
|
||||
}
|
||||
|
||||
// check if position / rotation / scale changed since last _full reliable_ sync.
|
||||
protected virtual bool Changed(TransformSnapshot current) =>
|
||||
// position is quantized and delta compressed.
|
||||
// only consider it changed if the quantized representation is changed.
|
||||
// careful: don't use 'serialized / deserialized last'. as it depends on sync mode etc.
|
||||
QuantizedChanged(last.position, current.position, positionPrecision) ||
|
||||
// rotation isn't quantized / delta compressed.
|
||||
// check with sensitivity.
|
||||
Quaternion.Angle(last.rotation, current.rotation) > rotationPrecision ||
|
||||
// scale is quantized and delta compressed.
|
||||
// only consider it changed if the quantized representation is changed.
|
||||
// careful: don't use 'serialized / deserialized last'. as it depends on sync mode etc.
|
||||
QuantizedChanged(last.scale, current.scale, scalePrecision);
|
||||
|
||||
// helper function to compare quantized representations of a Vector3
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected bool QuantizedChanged(Vector3 u, Vector3 v, float precision)
|
||||
{
|
||||
Compression.ScaleToLong(u, precision, out Vector3Long uQuantized);
|
||||
Compression.ScaleToLong(v, precision, out Vector3Long vQuantized);
|
||||
return uQuantized != vQuantized;
|
||||
}
|
||||
|
||||
// serialization ///////////////////////////////////////////////////////
|
||||
// serialize server->client baseline into a NetworkWriter.
|
||||
// for use in RpcSync and OnSerialize for spawn message.
|
||||
@ -219,6 +238,9 @@ void SerializeServerBaseline(NetworkWriter writer, Vector3 position, Quaternion
|
||||
// included in deltas to ensure they are on top of the correct baseline
|
||||
lastSerializedBaselineTick = (byte)Time.frameCount;
|
||||
lastServerBaselineTime = NetworkTime.localTime;
|
||||
|
||||
// set 'last'
|
||||
last = new TransformSnapshot(0, 0, position, rotation, scale);
|
||||
}
|
||||
|
||||
void DeserializeServerBaseline(NetworkReader reader)
|
||||
@ -452,6 +474,7 @@ protected virtual void OnServerToClientDeltaSync(byte baselineTick, Vector3? pos
|
||||
}
|
||||
|
||||
// update //////////////////////////////////////////////////////////////
|
||||
bool baselineDirty = true;
|
||||
void UpdateServerBaseline()
|
||||
{
|
||||
// send a reliable baseline every 1 Hz
|
||||
@ -460,13 +483,24 @@ void UpdateServerBaseline()
|
||||
// only send a new reliable baseline if changed since last time
|
||||
TransformSnapshot snapshot = ConstructSnapshot();
|
||||
|
||||
// send snapshot without timestamp.
|
||||
// receiver gets it from batch timestamp to save bandwidth.
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
// check if changed (unless that feature is disabled).
|
||||
// baseline is guaranteed to be delivered over reliable.
|
||||
// here is the only place where we can check for changes.
|
||||
if (!onlySyncOnChange || Changed(snapshot))
|
||||
{
|
||||
SerializeServerBaseline(writer, snapshot.position, snapshot.rotation, snapshot.scale);
|
||||
RpcServerToClientBaselineSync(writer);
|
||||
// reliable just changed. keep sending deltas until it's unchanged again.
|
||||
baselineDirty = true;
|
||||
|
||||
// send snapshot without timestamp.
|
||||
// receiver gets it from batch timestamp to save bandwidth.
|
||||
using (NetworkWriterPooled writer = NetworkWriterPool.Get())
|
||||
{
|
||||
SerializeServerBaseline(writer, snapshot.position, snapshot.rotation, snapshot.scale);
|
||||
RpcServerToClientBaselineSync(writer);
|
||||
}
|
||||
}
|
||||
// indicate that we should stop sending deltas now
|
||||
else baselineDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,6 +536,12 @@ void UpdateServerDelta()
|
||||
// authoritative movement done by the host will have to be broadcasted
|
||||
// here by checking IsClientWithAuthority.
|
||||
// TODO send same time that NetworkServer sends time snapshot?
|
||||
|
||||
// only sync on change:
|
||||
// unreliable isn't guaranteed to be delivered so this depends on reliable baseline.
|
||||
// if baseline is dirty, send unreliables every sendInterval until baseline is not dirty anymore.
|
||||
if (onlySyncOnChange && !baselineDirty) return;
|
||||
|
||||
if (NetworkTime.localTime >= lastServerSendTime + sendInterval) // CUSTOM CHANGE: allow custom sendRate + sendInterval again
|
||||
{
|
||||
// send snapshot without timestamp.
|
||||
@ -523,7 +563,6 @@ void UpdateServerDelta()
|
||||
}
|
||||
|
||||
lastServerSendTime = NetworkTime.localTime;
|
||||
lastSnapshot = snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,7 +653,6 @@ void UpdateClient()
|
||||
);
|
||||
|
||||
lastClientSendTime = NetworkTime.localTime;
|
||||
lastSnapshot = snapshot;
|
||||
}
|
||||
}
|
||||
// for all other clients (and for local player if !authority),
|
||||
@ -789,6 +827,9 @@ public virtual void Reset()
|
||||
lastSerializedScale = Vector3Long.zero;
|
||||
lastDeserializedScale = Vector3Long.zero;
|
||||
|
||||
// reset 'last' for delta too
|
||||
last = new TransformSnapshot(0, 0, Vector3.zero, Quaternion.identity, Vector3.zero);
|
||||
|
||||
Debug.Log($"[{name}] Reset to baselineTick=0");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user