Fixed V2 where full sync data is quantized first before considering delta

This causes premature rounding error (seen in tank turret bobbing) because full sync data has a rotation less than rotationSensitivity but non 0. but new snapshot derived from delta + quantized full sync data will produce a rotation of 0.

WIP - Need to fix this in V1
This commit is contained in:
ninjakickja 2024-01-20 21:58:12 +08:00
parent 65280a8f17
commit 04f247d43e

View File

@ -48,9 +48,9 @@ public class HybridNetworkTransformV2 : NetworkBehaviour
double lastFullSendIntervalTime = double.MinValue;
private byte lastSentFullSyncIndex = 0;
private SyncDataFull lastSentFullSyncData;
private QuantizedSnapshot lastSentFullQuantized;
//private QuantizedSnapshot lastSentFullQuantized;
private SyncDataFull lastReceivedFullSyncData;
private QuantizedSnapshot lastReceivedFullQuantized;
//private QuantizedSnapshot lastReceivedFullQuantized;
/*[Header("Delta Send Interval Multiplier")]
[Tooltip("Check/Sync every multiple of Network Manager send interval (= 1 / NM Send Rate), instead of every send interval.\n(30 NM send rate, and 3 interval, is a send every 0.1 seconds)\nA larger interval means less network sends, which has a variety of upsides. The drawbacks are delays and lower accuracy, you should find a nice balance between not sending too much, but the results looking good for your particular scenario.")]
@ -271,7 +271,7 @@ public override void OnSerialize(NetworkWriter writer, bool initialState)
if (syncRotation) writer.WriteQuaternion(lastSentFullSyncData.rotation);
if (syncScale) writer.WriteVector3(lastSentFullSyncData.scale);
lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
//lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
}
}
@ -400,7 +400,7 @@ protected virtual void ServerBroadcastFull()
{
lastSentFullSyncData = ConstructFullSyncData(true);
lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
//lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
SyncDataFullMsg msg = new SyncDataFullMsg(netId, ComponentIndex, lastSentFullSyncData);
SendToReadyObservers(netIdentity, msg, false, Channels.Reliable); // will exclude owner be problematic?
@ -442,7 +442,7 @@ public virtual void OnServerToClientSyncFull(SyncDataFull syncData)
// use current non-synced axis instead of giving it a 0.
lastReceivedFullSyncData = syncData;
CleanUpFullSyncDataPositionSync(ref lastReceivedFullSyncData);
lastReceivedFullQuantized = ConstructQuantizedSnapshot(lastReceivedFullSyncData.position, lastReceivedFullSyncData.rotation, lastReceivedFullSyncData.scale);
//lastReceivedFullQuantized = ConstructQuantizedSnapshot(lastReceivedFullSyncData.position, lastReceivedFullSyncData.rotation, lastReceivedFullSyncData.scale);
// We don't care if we are adding 'default' to any field because
// syncing is checked again in Apply before applying the changes.
@ -458,9 +458,9 @@ protected virtual void ServerBroadcastDelta()
if (lastSentFullSyncIndex == 0) return;
SyncDataFull currentFull = ConstructFullSyncData(false);
QuantizedSnapshot currentQuantized = ConstructQuantizedSnapshot(currentFull.position, currentFull.rotation, currentFull.scale);
//QuantizedSnapshot currentQuantized = ConstructQuantizedSnapshot(currentFull.position, currentFull.rotation, currentFull.scale);
SyncDataDelta syncDataDelta = DeriveDelta(currentQuantized);
SyncDataDelta syncDataDelta = DeriveDelta(currentFull);
SyncDataDeltaMsg msg = new SyncDataDeltaMsg(netId, ComponentIndex, syncDataDelta);
SendToReadyObservers(netIdentity, msg, false, Channels.Unreliable); // will exclude owner be problematic?
@ -509,8 +509,13 @@ protected virtual void ClientBroadcastFull()
{
lastSentFullSyncData = ConstructFullSyncData(true);
lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
//lastSentFullQuantized = ConstructQuantizedSnapshot(lastSentFullSyncData.position, lastSentFullSyncData.rotation, lastSentFullSyncData.scale);
/*if (gameObject.name.Contains("Turret"))
{
Debug.Log($"Pos Y = {lastSentFullSyncData.position.y.ToString("F10")}");
Debug.Log($"Pos Y Quantized = {lastSentFullQuantized.position.y}");
}*/
SyncDataFullMsg msg = new SyncDataFullMsg(netId, ComponentIndex, lastSentFullSyncData);
NetworkClient.Send(msg, Channels.Reliable);
}
@ -549,8 +554,9 @@ protected virtual void OnClientToServerSyncFull(SyncDataFull syncData)
// See Server's issue
lastReceivedFullSyncData = syncData;
if (gameObject.name.Contains("Turret")) Debug.Log($"Pos Y Received = {lastReceivedFullSyncData.position.y.ToString("F10")}");
CleanUpFullSyncDataPositionSync(ref lastReceivedFullSyncData);
lastReceivedFullQuantized = ConstructQuantizedSnapshot(lastReceivedFullSyncData.position, lastReceivedFullSyncData.rotation, lastReceivedFullSyncData.scale);
//lastReceivedFullQuantized = ConstructQuantizedSnapshot(lastReceivedFullSyncData.position, lastReceivedFullSyncData.rotation, lastReceivedFullSyncData.scale);
// We don't care if we are adding 'default' to any field because
// syncing is checked again in Apply before applying the changes.
@ -565,9 +571,10 @@ protected virtual void ClientBroadcastDelta()
if (lastSentFullSyncIndex == 0) return;
SyncDataFull currentFull = ConstructFullSyncData(false);
QuantizedSnapshot currentQuantized = ConstructQuantizedSnapshot(currentFull.position, currentFull.rotation, currentFull.scale);
//QuantizedSnapshot currentQuantized = ConstructQuantizedSnapshot(currentFull.position, currentFull.rotation, currentFull.scale);
SyncDataDelta syncDataDelta = DeriveDelta(currentQuantized);
SyncDataDelta syncDataDelta = DeriveDelta(currentFull);
if (gameObject.name.Contains("Turret")) Debug.Log($"Pos Y Delta = {syncDataDelta.position.y}");
SyncDataDeltaMsg msg = new SyncDataDeltaMsg(netId, ComponentIndex, syncDataDelta);
NetworkClient.Send(msg, Channels.Unreliable);
@ -638,13 +645,13 @@ protected virtual QuantizedSnapshot ConstructQuantizedSnapshot(Vector3 position,
);
}
protected virtual SyncDataDelta DeriveDelta(QuantizedSnapshot current)
protected virtual SyncDataDelta DeriveDelta(SyncDataFull current)
{
SyncDataDelta syncDataDelta = new SyncDataDelta();
syncDataDelta.fullSyncDataIndex = lastSentFullSyncIndex;
syncDataDelta.deltaHeader = DeltaHeader.None;
syncDataDelta.position = current.position - lastSentFullQuantized.position;
Compression.ScaleToLong(current.position - lastSentFullSyncData.position, positionPrecision, out syncDataDelta.position);
if ((fullHeader & FullHeader.SyncPosX) > 0 && syncDataDelta.position.x != 0)
syncDataDelta.deltaHeader |= DeltaHeader.PosX;
@ -674,7 +681,7 @@ protected virtual SyncDataDelta DeriveDelta(QuantizedSnapshot current)
{
if ((fullHeader & FullHeader.UseEulerAngles) > 0)
{
Compression.ScaleToLong(lastSentFullQuantized.rotation.eulerAngles, rotationSensitivity, out Vector3Long lastRotationEuler);
Compression.ScaleToLong(lastSentFullSyncData.rotation.eulerAngles, rotationSensitivity, out Vector3Long lastRotationEuler);
Compression.ScaleToLong(current.rotation.eulerAngles, rotationSensitivity, out Vector3Long currentRotationEuler);
syncDataDelta.eulRotation = currentRotationEuler - lastRotationEuler;
@ -685,7 +692,7 @@ protected virtual SyncDataDelta DeriveDelta(QuantizedSnapshot current)
}
else
{
if (Quaternion.Angle(lastSentFullQuantized.rotation, current.rotation) > rotationSensitivity)
if (Quaternion.Angle(lastSentFullSyncData.rotation, current.rotation) > rotationSensitivity)
{
syncDataDelta.quatRotation = current.rotation;
syncDataDelta.deltaHeader |= DeltaHeader.SendQuat;
@ -699,7 +706,7 @@ protected virtual SyncDataDelta DeriveDelta(QuantizedSnapshot current)
if ((fullHeader & FullHeader.SyncScale) > 0)
{
syncDataDelta.scale = current.scale - lastSentFullQuantized.scale;
Compression.ScaleToLong(current.scale - lastSentFullSyncData.scale, positionPrecision, out syncDataDelta.scale);
if (syncDataDelta.scale != Vector3Long.zero)
{
syncDataDelta.deltaHeader |= DeltaHeader.Scale;
@ -711,11 +718,11 @@ protected virtual SyncDataDelta DeriveDelta(QuantizedSnapshot current)
protected virtual void ApplyDelta(SyncDataDelta delta, out Vector3 position, out Quaternion rotation, out Vector3 scale)
{
position = Compression.ScaleToFloat(lastReceivedFullQuantized.position + delta.position, positionPrecision);
position = lastReceivedFullSyncData.position + Compression.ScaleToFloat(delta.position, positionPrecision);
if ((lastReceivedFullSyncData.fullHeader & FullHeader.UseEulerAngles) > 0)
{
Vector3 eulRotation = Compression.ScaleToFloat(lastReceivedFullQuantized.rotationEuler + delta.eulRotation, rotationSensitivity);
Vector3 eulRotation = lastReceivedFullSyncData.rotation.eulerAngles + Compression.ScaleToFloat(delta.eulRotation, rotationSensitivity);
rotation = Quaternion.Euler(eulRotation);
}
@ -727,7 +734,7 @@ protected virtual void ApplyDelta(SyncDataDelta delta, out Vector3 position, out
rotation = lastReceivedFullSyncData.rotation;
}
scale = Compression.ScaleToFloat(lastReceivedFullQuantized.scale + delta.scale, scalePrecision);
scale = lastReceivedFullSyncData.scale + Compression.ScaleToFloat(delta.scale, scalePrecision);
}
#endregion