Skip to content

Commit 08005ff

Browse files
feat: quaternion synchronization, delta position, and NetworkTransform bandwidth optimizations (#2388)
* update Quaternion Synchronization: Added the ability to synchronize by quaternions (full precision). Using quaternion synchronization is recommended for scenarios where multiple axis of rotation can change and the transform in question is within a parent-child hierarchy. When enabled, per axis rotation flags are no longer visible in the editor as the entire quaternion is synchronized when any change in rotation occurs. Quaternion Compression: Added the ability to compress quaternions (requires Quaternion Synchronization to be enabled). Reduces the cost of quaternion synchronization down to 4 bytes at the cost of additional loss in precision (a bit less precise than half float precision). Half Float Precision: Added the ability to enable half float precision which reduces payload size per instance by ~50% at the cost of a decrease in precision. Delta Position Synchronization: When using half float precision NetworkTransform uses delta position synchronization to assure any loss in precision is recovered/handled in the next state update. Added additional virtual methods to be used in prediction calculation scenarios where knowing the exact values being updated are required. This addition includes changing NetworkTransformState to public. Added a bandwidth optimization related property, SynchronizeTransform, to NetworkObject that allows users to disable the automatic synchronization of the associated transform to reduce the total bandwidth cost of spawning and late joining client synchronization. This is particularly useful if the NetworkObject is used more for management related tasks and has no spatial synchronization needs. NetworkTransform now only sends the network tick as opposed to the double precision server time since authority updates state only on each new network tick. NetworkTransformState header properties are now being bit compressed. Added additional check to make sure if SyncPosition axis value changes while using half precision (delta position) that if the delta on that axis exceeds the maximum delta that the NetworkObject is teleported on the tick this condition is detected. * test manual Added a manual test for long-duration testing of delta position compression with precision loss compensation. Updated the manual nested network transform test using delta position with the HalfVector3 struct. Added updates to the nested NetworkTransform manual test to be able to visually see that all automated player instances are in the same relative grid regions. Updated manual tests for additive scene loading manual test with NetworkPrefabPool in order to be able to test turning on and off half float precision, quaternion synchronization, and quaternion compression. Updated the delta position long duration test for precision drift so that it randomly selects x,y,z axis for direction and synchronization in order to determine if enabling and disabling which axis should be synchronized during runtime can cause issues. * test Added fixes to an issue with the NestedNetworkTransform test. Removed the sphere collider from the NetworkTransformOwnershipTests because the test basically ignores collision with other players and collision is not a factor of this test. Added a new IntegrationNetworkTransform for testing purposes.
1 parent 4839210 commit 08005ff

File tree

97 files changed

+17472
-1592
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+17472
-1592
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
77
Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com).
88

99
## [Unreleased]
10-
1110
### Added
1211

12+
- Added `NetworkTransform.UseHalfFloatPrecision` property that, when enabled, will use half float values for position, rotation, and scale. This yields a 50% bandwidth savings a the cost of precision. (#2388)
13+
- Added `NetworkTransform.UseQuaternionSynchronization` property that, when enabled, will synchronize the entire quaternion. (#2388)
14+
- Added `NetworkTransform.UseQuaternionCompression` property that, when enabled, will use a smallest three implementation reducing a full quaternion synchronization update to the size of an unsigned integer. (#2388)
15+
- Added `NetworkTransform.SlerpPosition` property that, when enabled along with interpolation being enabled, will interpolate using `Vector3.Slerp`. (#2388)
16+
- Added `BufferedLinearInterpolatorVector3` that replaces the float version, is now used by `NetworkTransform`, and provides the ability to enable or disable `Slerp`. (#2388)
17+
- Added `HalfVector3` used for scale when half float precision is enabled. (#2388)
18+
- Added `HalfVector4` used for rotation when half float precision and quaternion synchronization is enabled. (#2388)
19+
- Added `HalfVector3DeltaPosition` used for position when half float precision is enabled. This handles loss in position precision by updating only the delta position as opposed to the full position. (#2388)
20+
- Added `NetworkTransform.GetSpaceRelativePosition` and `NetworkTransform.GetSpaceRelativeRotation` helper methods to return the proper values depending upon whether local or world space. (#2388)
21+
- Added `NetworkTransform.OnAuthorityPushTransformState` virtual method that is invoked just prior to sending the `NetworkTransformState` to non-authoritative instances. This provides users with the ability to obtain more precise delta values for prediction related calculations. (#2388)
22+
- Added `NetworkTransform.OnNetworkTransformStateUpdated` virtual method that is invoked just after the authoritative `NetworkTransformState` is applied. This provides users with the ability to obtain more precise delta values for prediction related calculations. (#2388)
23+
- Added `NetworkTransform.OnInitialize`virtual method that is invoked after the `NetworkTransform` has been initialized or re-initialized when ownership changes. This provides for a way to make adjustments when `NetworkTransform` is initialized (i.e. resetting client prediction etc) (#2388)
24+
- Added `NetworkObject.SynchronizeTransform` property (default is true) that provides users with another way to help with bandwidth optimizations where, when set to false, the `NetworkObject`'s associated transform will not be included when spawning and/or synchronizing late joining players. (#2388)
1325
- Added `NetworkSceneManager.ActiveSceneSynchronizationEnabled` property, disabled by default, that enables client synchronization of server-side active scene changes. (#2383)
1426
- Added `NetworkObject.ActiveSceneSynchronization`, disabled by default, that will automatically migrate a `NetworkObject` to a newly assigned active scene. (#2383)
1527
- Added `NetworkObject.SceneMigrationSynchronization`, enabled by default, that will synchronize client(s) when a `NetworkObject` is migrated into a new scene on the server side via `SceneManager.MoveGameObjectToScene`. (#2383)
1628

1729
### Changed
1830

31+
- Changed `NetworkTransform` authority handles delta checks on each new network tick and no longer consumes processing cycles checking for deltas for all frames in-between ticks. (#2388)
32+
- Changed the `NetworkTransformState` structure is now public and now has public methods that provide access to key properties of the `NetworkTransformState` structure. (#2388)
33+
- Changed `NetworkTransform` interpolation adjusts its interpolation "ticks ago" to be 2 ticks latent if it is owner authoritative and the instance is not the server or 1 tick latent if the instance is the server and/or is server authoritative. (#2388)
1934
- Updated `NetworkSceneManager` to migrate dynamically spawned `NetworkObject`s with `DestroyWithScene` set to false into the active scene if their current scene is unloaded. (#2383)
2035
- Updated the server to synchronize its local `NetworkSceneManager.ClientSynchronizationMode` during the initial client synchronization. (#2383)
2136

@@ -25,6 +40,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
2540
- Fixed registry of public `NetworkVariable`s in derived `NetworkBehaviour`s (#2423)
2641
- Fixed issue where runtime association of `Animator` properties to `AnimationCurve`s would cause `NetworkAnimator` to attempt to update those changes. (#2416)
2742
- Fixed issue where `NetworkAnimator` would not check if its associated `Animator` was valid during serialization and would spam exceptions in the editor console. (#2416)
43+
- Fixed issue with a child's rotation rolling over when interpolation is enabled on a `NetworkTransform`. Now using half precision or full quaternion synchronization will always update all axis. (#2388)
44+
- Fixed issue where `NetworkTransform` was not setting the teleport flag when the `NetworkTransform.InLocalSpace` value changed. This issue only impacted `NetworkTransform` when interpolation was enabled. (#2388)
2845
- Fixed issue when the `NetworkSceneManager.ClientSynchronizationMode` is `LoadSceneMode.Additive` and the server changes the currently active scene prior to a client connecting then upon a client connecting and being synchronized the NetworkSceneManager would clear its internal ScenePlacedObjects list that could already be populated. (#2383)
2946
- Fixed issue where a client would load duplicate scenes of already preloaded scenes during the initial client synchronization and `NetworkSceneManager.ClientSynchronizationMode` was set to `LoadSceneMode.Additive`. (#2383)
3047
- Fixed float NetworkVariables not being rendered properly in the inspector of NetworkObjects. (#2441)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System.Runtime.CompilerServices;
2+
using UnityEngine;
3+
4+
namespace Unity.Netcode.Components
5+
{
6+
/// <summary>
7+
/// Half float precision <see cref="Vector3"/>.
8+
/// </summary>
9+
/// <remarks>
10+
/// The Vector3T<ushort> values are half float values returned by <see cref="Mathf.FloatToHalf(float)"/> for each
11+
/// individual axis and the 16 bits of the half float are stored as <see cref="ushort"/> values since C# does not have
12+
/// a half float type.
13+
/// </remarks>
14+
public struct HalfVector3 : INetworkSerializable
15+
{
16+
/// <summary>
17+
/// The half float precision value of the x-axis as a <see cref="ushort"/>.
18+
/// </summary>
19+
public ushort X => Axis.X;
20+
/// <summary>
21+
/// The half float precision value of the y-axis as a <see cref="ushort"/>.
22+
/// </summary>
23+
public ushort Y => Axis.Y;
24+
/// <summary>
25+
/// The half float precision value of the z-axis as a <see cref="ushort"/>.
26+
/// </summary>
27+
public ushort Z => Axis.Z;
28+
29+
/// <summary>
30+
/// Used to store the half float precision value as a <see cref="ushort"/>.
31+
/// </summary>
32+
public Vector3T<ushort> Axis;
33+
34+
internal Vector3AxisToSynchronize AxisToSynchronize;
35+
36+
/// <summary>
37+
/// The serialization implementation of <see cref="INetworkSerializable"/>.
38+
/// </summary>
39+
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
40+
{
41+
for (int i = 0; i < Axis.Length; i++)
42+
{
43+
if (AxisToSynchronize.SyncAxis[i])
44+
{
45+
var axisValue = Axis[i];
46+
serializer.SerializeValue(ref axisValue);
47+
if (serializer.IsReader)
48+
{
49+
Axis[i] = axisValue;
50+
}
51+
}
52+
}
53+
}
54+
55+
/// <summary>
56+
/// Gets the full precision value as a <see cref="Vector3"/>.
57+
/// </summary>
58+
/// <returns>a <see cref="Vector3"/> as the full precision value.</returns>
59+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
60+
public Vector3 ToVector3()
61+
{
62+
Vector3 fullPrecision = Vector3.zero;
63+
for (int i = 0; i < Axis.Length; i++)
64+
{
65+
if (AxisToSynchronize.SyncAxis[i])
66+
{
67+
fullPrecision[i] = Mathf.HalfToFloat(Axis[i]);
68+
}
69+
}
70+
return fullPrecision;
71+
}
72+
73+
/// <summary>
74+
/// Converts a full precision <see cref="Vector3"/> to half precision and updates the current instance.
75+
/// </summary>
76+
/// <param name="vector3">The <see cref="Vector3"/> to convert.</param>
77+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
78+
public void UpdateFrom(ref Vector3 vector3)
79+
{
80+
for (int i = 0; i < Axis.Length; i++)
81+
{
82+
if (AxisToSynchronize.SyncAxis[i])
83+
{
84+
Axis[i] = Mathf.FloatToHalf(vector3[i]);
85+
}
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Constructor
91+
/// </summary>
92+
/// <param name="vector3">The initial axial values (converted to half floats) when instantiated.</param>
93+
/// <param name="vector3AxisToSynchronize">The axis to synchronize.</param>
94+
public HalfVector3(Vector3 vector3, Vector3AxisToSynchronize vector3AxisToSynchronize)
95+
{
96+
Axis = default;
97+
AxisToSynchronize = vector3AxisToSynchronize;
98+
UpdateFrom(ref vector3);
99+
}
100+
101+
/// <summary>
102+
/// Constructor that defaults to all axis being synchronized.
103+
/// </summary>
104+
/// <param name="vector3">The initial axial values (converted to half floats) when instantiated.</param>
105+
public HalfVector3(Vector3 vector3) : this(vector3, Vector3AxisToSynchronize.AllAxis)
106+
{
107+
108+
}
109+
110+
/// <summary>
111+
/// Constructor
112+
/// </summary>
113+
/// <param name="x">The initial x axis (converted to half float) value when instantiated.</param>
114+
/// <param name="y">The initial y axis (converted to half float) value when instantiated.</param>
115+
/// <param name="z">The initial z axis (converted to half float) value when instantiated.</param>
116+
/// <param name="vector3AxisToSynchronize">The axis to synchronize.</param>
117+
public HalfVector3(float x, float y, float z, Vector3AxisToSynchronize vector3AxisToSynchronize) : this(new Vector3(x, y, z), vector3AxisToSynchronize)
118+
{
119+
}
120+
121+
/// <summary>
122+
/// Constructor that defaults to all axis being synchronized.
123+
/// </summary>
124+
/// <param name="x">The initial x axis (converted to half float) value when instantiated.</param>
125+
/// <param name="y">The initial y axis (converted to half float) value when instantiated.</param>
126+
/// <param name="z">The initial z axis (converted to half float) value when instantiated.</param>
127+
public HalfVector3(float x, float y, float z) : this(new Vector3(x, y, z), Vector3AxisToSynchronize.AllAxis)
128+
{
129+
}
130+
}
131+
}

com.unity.netcode.gameobjects/Components/HalfVector3.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)