Skip to content
7 changes: 3 additions & 4 deletions com.unity.netcode.gameobjects/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,21 @@ Additional documentation and release notes are available at [Multiplayer Documen

### Changed

- Changed `NetworkTransform.UseHalfFloatPrecision` to synchronize position with a resolution of approximately 1mm regardless of how far an object has travelled. Previously the resolution could degrade to approximately 3cm. This does not increase bandwidth, but projects using `NetworkTransform.UseUnreliableDeltas` will send full precision position updates more often. (#4129)

- All editor assembly definitions are renamed with `Unity.Netcode.GameObjects.x` variants
- `Unity.Netcode.Editor` → `Unity.Netcode.GameObjects.Editor`
- `Unity.Netcode.Editor.CodeGen` → `Unity.Netcode.GameObjects.Editor.CodeGen`
- `Unity.Netcode.Editor.PackageChecker` → `Unity.Netcode.GameObjects.Editor.PackageChecker`
- `Unity.Netcode.Editor.Tests` → `Unity.Netcode.GameObjects.Editor.Tests`



### Deprecated


### Removed


### Fixed

- Issue where objects using `NetworkTransform.UseHalfFloatPrecision` appeared to jitter on non-authority instances while they were stationary or coming to rest, even though the authority was not moving them. (#4129)
- Issue with not being able to spawn initially disabled in-scene placed objects. (#4093)
- Issue with pre-instantiated network prefab instances being marked as in-scene placed. Now pre-instantiated network prefabs are dynamically spawned. (#4093)
- Issue where a user could spawn runtime created `NetworkObject` that has a GlobalObjectIdHash of zero. These are not valid instances and will no longer be allowed to spawn. (#4093)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ namespace Unity.Netcode.Components
[Serializable]
public struct NetworkDeltaPosition : INetworkSerializable
{
internal const float MaxDeltaBeforeAdjustment = 64f;
/// <summary>
/// How far the delta may grow before it is folded into the base position.
/// </summary>
/// <remarks>
/// This determines the transmitted position resolution, since a half float's step size grows with its
/// magnitude. Keeping the delta small keeps that step small: at 2 the coarsest step is roughly 1mm.
/// </remarks>
internal const float MaxDeltaBeforeAdjustment = 2f;

/// <summary>
/// The HalfVector3 used to synchronize the delta in position
Expand Down Expand Up @@ -138,14 +145,29 @@ public void UpdateFrom(ref Vector3 vector3, int networkTick)
{
CollapsedDeltaIntoBase = false;
NetworkTick = networkTick;
DeltaPosition = (vector3 + PrecisionLossDelta) - CurrentBasePosition;
for (int i = 0; i < HalfVector3.Length; i++)
{
if (HalfVector3.AxisToSynchronize[i])
{
var rawDelta = vector3[i] - CurrentBasePosition[i];

// Adding the previous rounding loss back in keeps the average position accurate while the
// value is moving, but it also changes the value being sent. Once the value stops moving
// that is all it does, which makes a stationary object appear to oscillate.
var movedSinceLastSend = Mathf.Abs(vector3[i] - PreviousPosition[i]);
var applyPrecisionLoss = movedSinceLastSend >= HalfPrecisionQuantum(rawDelta);

DeltaPosition[i] = applyPrecisionLoss ? rawDelta + PrecisionLossDelta[i] : rawDelta;

HalfVector3.Axis[i] = math.half(DeltaPosition[i]);
HalfDeltaConvertedBack[i] = Mathf.HalfToFloat(HalfVector3.Axis[i].value);
PrecisionLossDelta[i] = DeltaPosition[i] - HalfDeltaConvertedBack[i];

// Left unchanged when skipped so it is still applied once movement resumes.
if (applyPrecisionLoss)
{
PrecisionLossDelta[i] = DeltaPosition[i] - HalfDeltaConvertedBack[i];
}

if (Mathf.Abs(HalfDeltaConvertedBack[i]) >= MaxDeltaBeforeAdjustment)
{
CurrentBasePosition[i] += HalfDeltaConvertedBack[i];
Expand All @@ -165,6 +187,26 @@ public void UpdateFrom(ref Vector3 vector3, int networkTick)
}
}

/// <summary>
/// The smallest change a half float can represent at the magnitude of the value passed in.
/// </summary>
/// <param name="value">The value to get the step size for.</param>
/// <returns>The distance to the next representable half float value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static float HalfPrecisionQuantum(float value)
{
// The step size is symmetric about zero, so the sign is dropped.
var magnitude = (ushort)(math.half(value).value & 0x7FFF);

// Guard only: stepping past the largest finite half float would give infinity.
if (magnitude >= 0x7BFF)
{
return MaxDeltaBeforeAdjustment;
}

return Mathf.HalfToFloat((ushort)(magnitude + 1)) - Mathf.HalfToFloat(magnitude);
}

/// <summary>
/// Constructor
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Unity.Netcode
/// </summary>
internal static class NetworkConstants
{
internal const string PROTOCOL_VERSION = "15.0.0";
internal const string PROTOCOL_VERSION = "15.1.0";
}
}
Loading