Skip to content

Commit bd0c255

Browse files
update
Applying Paolo's suggested changes. Improved the comment that was a tad confusing.
1 parent d16954d commit bd0c255

2 files changed

Lines changed: 26 additions & 9 deletions

File tree

com.unity.netcode.gameobjects/Runtime/Components/NetworkDeltaPosition.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ public struct NetworkDeltaPosition : INetworkSerializable
2020
/// </remarks>
2121
internal const float MaxDeltaBeforeAdjustment = 2f;
2222

23+
/// <summary>
24+
/// Masks off a half float's sign bit, leaving its magnitude.
25+
/// </summary>
26+
internal const ushort HalfMagnitudeMask = 0x7FFF;
27+
28+
/// <summary>
29+
/// The bit pattern of the largest finite half float (65504); anything above it is an infinity or a NaN.
30+
/// </summary>
31+
internal const ushort LargestFiniteHalfBits = 0x7BFF;
32+
2333
/// <summary>
2434
/// The HalfVector3 used to synchronize the delta in position
2535
/// </summary>
@@ -162,7 +172,8 @@ public void UpdateFrom(ref Vector3 vector3, int networkTick)
162172
HalfVector3.Axis[i] = math.half(DeltaPosition[i]);
163173
HalfDeltaConvertedBack[i] = Mathf.HalfToFloat(HalfVector3.Axis[i].value);
164174

165-
// Left unchanged when skipped so it is still applied once movement resumes.
175+
// Only recompute the carried loss when it was applied. Leaving it alone otherwise is
176+
// what keeps it around to apply once movement resumes.
166177
if (applyPrecisionLoss)
167178
{
168179
PrecisionLossDelta[i] = DeltaPosition[i] - HalfDeltaConvertedBack[i];
@@ -196,10 +207,10 @@ public void UpdateFrom(ref Vector3 vector3, int networkTick)
196207
internal static float HalfPrecisionQuantum(float value)
197208
{
198209
// The step size is symmetric about zero, so the sign is dropped.
199-
var magnitude = (ushort)(math.half(value).value & 0x7FFF);
210+
var magnitude = (ushort)(math.half(value).value & HalfMagnitudeMask);
200211

201-
// Guard only: stepping past the largest finite half float would give infinity.
202-
if (magnitude >= 0x7BFF)
212+
// Guard only: stepping past this would give infinity.
213+
if (magnitude >= LargestFiniteHalfBits)
203214
{
204215
return MaxDeltaBeforeAdjustment;
205216
}

com.unity.netcode.gameobjects/Tests/Editor/NetworkDeltaPositionTests.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ internal class NetworkDeltaPositionTests
1616
// Lossy as a half float, and two of them still fit under the collapse threshold.
1717
private const float k_LossyStep = 0.7f;
1818

19+
// The largest finite half float.
20+
private const float k_LargestFiniteHalf = 65504.0f;
21+
22+
// Finite, but far enough past the half float range that the conversion itself rounds to infinity,
23+
// which reaches the guard by a different path than handing it an infinity outright.
24+
private const float k_RoundsToInfinity = 70000.0f;
25+
1926
// Past the threshold and exactly representable, so the collapse cannot hinge on rounding.
2027
private const float k_CollapsingStep = NetworkDeltaPosition.MaxDeltaBeforeAdjustment + 0.5f;
2128

@@ -307,11 +314,9 @@ public void QuantumIsTheSmallestChangeTheEncodingCanSee()
307314
[Test]
308315
public void QuantumIsGuardedAtTheTopOfTheRange()
309316
{
310-
// 70000f is the finite one: the conversion itself rounds to infinity, which reaches the guard
311-
// by a different path than handing it an infinity outright.
312317
var values = new[]
313318
{
314-
65504.0f, -65504.0f, 70000.0f,
319+
k_LargestFiniteHalf, -k_LargestFiniteHalf, k_RoundsToInfinity,
315320
float.PositiveInfinity, float.NegativeInfinity, float.NaN,
316321
};
317322

@@ -328,13 +333,14 @@ public void QuantumIsNeverNonFiniteOrZero()
328333
{
329334
// Why the guard exists: an infinite step size would make the "has it moved?" comparison in
330335
// UpdateFrom false for every input, silently stopping the rounding loss from being applied.
331-
var unguarded = Mathf.HalfToFloat(0x7BFF + 1) - Mathf.HalfToFloat(0x7BFF);
336+
const ushort topOfRange = NetworkDeltaPosition.LargestFiniteHalfBits;
337+
var unguarded = Mathf.HalfToFloat(topOfRange + 1) - Mathf.HalfToFloat(topOfRange);
332338
Assert.IsTrue(float.IsInfinity(unguarded) || float.IsNaN(unguarded),
333339
"The unguarded computation at the top of the range should be non-finite, which is why the guard exists.");
334340

335341
var values = new[]
336342
{
337-
0.0f, float.Epsilon, 1e-7f, 0.5f, 1.0f, 100.0f, 65503.0f, 65504.0f, -65504.0f, 70000.0f,
343+
0.0f, float.Epsilon, 1e-7f, 0.5f, 1.0f, 100.0f, 65503.0f, k_LargestFiniteHalf, -k_LargestFiniteHalf, k_RoundsToInfinity,
338344
float.PositiveInfinity, float.NegativeInfinity, float.NaN,
339345
};
340346

0 commit comments

Comments
 (0)