Skip to content

Commit 16c4409

Browse files
fix: networktransform double lerp (MTTB-539) (#3337)
This PR fixes the issue with double lerping by providing two types of interpolators to select from while also exposing the `MaximumInterpolationTime` for each respective interpolator type. Smooth Dampening is added as an alternative to using lerp for each respective interpolator (position, rotation, and scale). This PR includes a few new additions: - Additional updates to the inspector view which allows for interpolator type selection and if available additional properties associated with the interpolator. ![image](https://github.com/user-attachments/assets/f643c015-646f-4c1a-a979-05a6287b41d7) ![image](https://github.com/user-attachments/assets/335cd68d-98fd-44b7-b6f3-88c4d44a60fd) ![image](https://github.com/user-attachments/assets/63c6d44c-09a4-4bad-b74e-46218a3a4b8c) ![image](https://github.com/user-attachments/assets/d966dd7c-0c82-4bcd-85ce-e7cf8455d3a6) - A new `NetworkTimeSystem.TickLatency` property that provides the average latency of a client. - An new `NetworkTime.FixedDeltaTimeAsDouble` property that returns a `double` version of the `NetworkTime.FixedDeltaTime`. This PR also starts the deprecation process for `BufferedLinearInterpolator<T>.Update(float deltaTime, NetworkTime serverTime)` as this method is only for internal testing purposes. [MTTB-539](https://jira.unity3d.com/browse/MTTB-539) [MTT-11338](https://jira.unity3d.com/browse/MTT-11338) -- Fixing disabled tests fix: #3112 close: #3112 ## Changelog - Added: Interpolator types as an inspector view selection for position, rotation, and scale. - Added: A new smooth dampening interpolator type that provides a nice balance between precision and smoothing results. - Added: `NetworkTimeSystem.TickLatency` property that provides the average latency of a client. - Fixed: Issue where the `MaximumInterpolationTime` could not be modified from within the inspector view or runtime. - Changed: `BufferedLinearInterpolator<T>.Update(float deltaTime, NetworkTime serverTime)` as being deprecated since this method is only used for internal testing purposes. ## Testing and Documentation - Includes integration test updates: - `InterpolatorTests` was updated to changes and two disabled tests were refactored and re-enabled. - `NetworkTransformGeneral` includes additional TestFixture passes using Smooth Dampening. - `NetworktTransformTests` includes additional TestFixture passes using Smooth Dampening. - `NestedNetworkTransformTests` includes additional TestFixture passes using Smooth Dampening. - Includes updates and additions to public documentation ([PR-1443](Unity-Technologies/com.unity.multiplayer.docs#1443)) <!-- Uncomment and mark items off with a * if this PR deprecates any API: ### Deprecated API - [ ] An `[Obsolete]` attribute was added along with a `(RemovedAfter yyyy-mm-dd)` entry. - [ ] An [api updater] was added. - [ ] Deprecation of the API is explained in the CHANGELOG. - [ ] The users can understand why this API was removed and what they should use instead. -->
1 parent e5362a4 commit 16c4409

26 files changed

+1279
-588
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ Additional documentation and release notes are available at [Multiplayer Documen
1010

1111
### Added
1212

13+
- Added interpolator types as an inspector view selection for position, rotation, and scale. (#3337)
14+
- Added a new smooth dampening interpolator type that provides a nice balance between precision and smoothing results. (#3337)
15+
- Added `NetworkTimeSystem.TickLatency` property that provides the average latency of a client. (#3337)
1316
- Added `FastBufferReader(ArraySegment<byte> buffer, Allocator copyAllocator)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset and the `ArraySegment.Count` as the `FastBufferReader` length. (#3321)
1417
- Added `FastBufferReader(ArraySegment<byte> buffer, Allocator copyAllocator, int length = -1)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset. (#3321)
1518

1619
### Fixed
1720

21+
- Fixed issue where the `MaximumInterpolationTime` could not be modified from within the inspector view or runtime. (#3337)
1822
- Fixed `ChangeOwnership` changing ownership to clients that are not observers. This also happened with automated object distribution. (#3323)
1923
- Fixed issue where `AnticipatedNetworkVariable` previous value returned by `AnticipatedNetworkVariable.OnAuthoritativeValueChanged` is updated correctly on the non-authoritative side. (#3306)
2024
- Fixed `OnClientConnectedCallback` passing incorrect `clientId` when scene management is disabled. (#3312)
@@ -31,6 +35,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
3135

3236
### Changed
3337

38+
- Changed `BufferedLinearInterpolator<T>.Update(float deltaTime, NetworkTime serverTime)` as being deprecated since this method is only used for internal testing purposes. (#3337)
3439
- Ensured that a useful error is thrown when attempting to build a dedicated server with Unity Transport that uses websockets. (#3336)
3540
- Changed root in-scene placed `NetworkObject` instances now will always have either the `Distributable` permission set unless the `SessionOwner` permission is set. (#3305)
3641
- Changed the `DestroyObject` message to reduce the serialized message size and remove the unnecessary message field. (#3304)

com.unity.netcode.gameobjects/Editor/Configuration/NetcodeForGameObjectsProjectSettings.cs

+13
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@
33

44
namespace Unity.Netcode.Editor.Configuration
55
{
6+
/// <summary>
7+
/// A <see cref="ScriptableSingleton{T}"/> of type <see cref="NetcodeForGameObjectsProjectSettings"/>.
8+
/// </summary>
69
[FilePath("ProjectSettings/NetcodeForGameObjects.asset", FilePathAttribute.Location.ProjectFolder)]
710
public class NetcodeForGameObjectsProjectSettings : ScriptableSingleton<NetcodeForGameObjectsProjectSettings>
811
{
912
internal static readonly string DefaultNetworkPrefabsPath = "Assets/DefaultNetworkPrefabs.asset";
13+
/// <summary>
14+
/// The path and name for the DefaultNetworkPrefabs asset.
15+
/// </summary>
1016
[SerializeField] public string NetworkPrefabsPath = DefaultNetworkPrefabsPath;
17+
18+
/// <summary>
19+
/// A temporary network prefabs path used internally.
20+
/// </summary>
1121
public string TempNetworkPrefabsPath;
1222

1323
private void OnEnable()
@@ -19,6 +29,9 @@ private void OnEnable()
1929
TempNetworkPrefabsPath = NetworkPrefabsPath;
2030
}
2131

32+
/// <summary>
33+
/// Used to determine whether the default network prefabs asset should be generated or not.
34+
/// </summary>
2235
[SerializeField]
2336
public bool GenerateDefaultNetworkPrefabs = true;
2437

com.unity.netcode.gameobjects/Editor/Configuration/NetworkPrefabProcessor.cs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ namespace Unity.Netcode.Editor.Configuration
99
/// </summary>
1010
public class NetworkPrefabProcessor : AssetPostprocessor
1111
{
12+
/// <summary>
13+
/// The path to the default network prefabs list.
14+
/// </summary>
1215
public static string DefaultNetworkPrefabsPath
1316
{
1417
get

com.unity.netcode.gameobjects/Editor/Configuration/NetworkPrefabsEditor.cs

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Unity.Netcode.Editor
66
{
7+
/// <summary>
8+
/// The custom editor for the <see cref="NetworkPrefabsList"/> <see cref="ScriptableObject"/>.
9+
/// </summary>
710
[CustomEditor(typeof(NetworkPrefabsList), true)]
811
[CanEditMultipleObjects]
912
public class NetworkPrefabsEditor : UnityEditor.Editor
@@ -82,6 +85,7 @@ private void OnEnable()
8285
m_NetworkPrefabsList.drawHeaderCallback = rect => EditorGUI.LabelField(rect, "NetworkPrefabs");
8386
}
8487

88+
/// <inheritdoc />
8589
public override void OnInspectorGUI()
8690
{
8791
using (new EditorGUI.DisabledScope(true))

com.unity.netcode.gameobjects/Editor/NetcodeEditorBase.cs

+72-1
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,87 @@ namespace Unity.Netcode.Editor
88
/// The base Netcode Editor helper class to display derived <see cref="MonoBehaviour"/> based components <br />
99
/// where each child generation's properties will be displayed within a FoldoutHeaderGroup.
1010
/// </summary>
11+
/// <remarks>
12+
/// <see cref="TT"/> Defines the base <see cref="MonoBehaviour"/> derived component type where <see cref="DrawFoldOutGroup"/>'s type T
13+
/// refers to any child derived class of <see cref="TT"/>. This provides the ability to have multiple child generation derived custom
14+
/// editos that each child derivation handles drawing its unique properies from that of its parent class.
15+
/// </remarks>
16+
/// <typeparam name="TT">The base <see cref="MonoBehaviour"/> derived component type</typeparam>
1117
[CanEditMultipleObjects]
1218
public partial class NetcodeEditorBase<TT> : UnityEditor.Editor where TT : MonoBehaviour
1319
{
20+
private const int k_IndentOffset = 15;
21+
private int m_IndentOffset = 0;
22+
private int m_IndentLevel = 0;
23+
private float m_OriginalLabelWidth;
24+
1425
/// <inheritdoc cref="UnityEditor.Editor.OnEnable"/>
1526
public virtual void OnEnable()
1627
{
1728
}
1829

30+
/// <summary>
31+
/// Draws a <see cref="SerializedProperty"/> with the option to provide the font style to use.
32+
/// </summary>
33+
/// <param name="property">The serialized property (<see cref="SerializedProperty"/>) to draw within the inspector view.</param>
34+
/// <param name="fontStyle">The font style (<see cref="FontStyle"/>) to use when drawing the label of the property field.</param>
35+
private protected void DrawPropertyField(SerializedProperty property, FontStyle fontStyle = FontStyle.Normal)
36+
{
37+
var originalWidth = EditorGUIUtility.labelWidth;
38+
EditorGUIUtility.labelWidth = originalWidth - (m_IndentOffset * m_IndentLevel);
39+
var originalLabelFontStyle = EditorStyles.label.fontStyle;
40+
EditorStyles.label.fontStyle = fontStyle;
41+
EditorGUILayout.PropertyField(property);
42+
EditorStyles.label.fontStyle = originalLabelFontStyle;
43+
EditorGUIUtility.labelWidth = originalWidth;
44+
}
45+
46+
/// <summary>
47+
/// Will begin a new indention level for drawing propery fields.
48+
/// </summary>
49+
/// <remarks>
50+
/// You *must* call <see cref="EndIndent"/> when returning back to the previous indention level.<br />
51+
/// For additional information:<br />
52+
/// - <see cref="EndIndent"/><br />
53+
/// - <see cref="DrawPropertyField"/><br />
54+
/// </remarks>
55+
/// <param name="offset">(optional) The size in pixels of the offset. If no value passed, then it uses a default of 15 pixels.</param>
56+
private protected void BeginIndent(int offset = k_IndentOffset)
57+
{
58+
m_IndentOffset = offset;
59+
m_IndentLevel++;
60+
GUILayout.BeginHorizontal();
61+
GUILayout.Space(m_IndentOffset);
62+
GUILayout.BeginVertical();
63+
}
64+
65+
/// <summary>
66+
/// Will end the current indention level when drawing propery fields.
67+
/// </summary>
68+
/// <remarks>
69+
/// For additional information:<br />
70+
/// - <see cref="BeginIndent"/><br />
71+
/// - <see cref="DrawPropertyField"/><br />
72+
/// </remarks>
73+
private protected void EndIndent()
74+
{
75+
if (m_IndentLevel == 0)
76+
{
77+
Debug.LogWarning($"Invoking {nameof(EndIndent)} when the indent level is already 0!");
78+
return;
79+
}
80+
m_IndentLevel--;
81+
GUILayout.EndVertical();
82+
GUILayout.EndHorizontal();
83+
}
84+
1985
/// <summary>
2086
/// Helper method to draw the properties of the specified child type <typeparamref name="T"/> component within a FoldoutHeaderGroup.
2187
/// </summary>
22-
/// <typeparam name="T">The specific child type that should have its properties drawn.</typeparam>
88+
/// <remarks>
89+
/// <see cref="T"/> must be a sub-class of the root parent class type <see cref="TT"/>.
90+
/// </remarks>
91+
/// <typeparam name="T">The specific child derived type of <see cref="TT"/> or the type of <see cref="TT"/> that should have its properties drawn.</typeparam>
2392
/// <param name="type">The component type of the <see cref="UnityEditor.Editor.target"/>.</param>
2493
/// <param name="displayProperties">The <see cref="Action"/> to invoke that will draw the type <typeparamref name="T"/> properties.</param>
2594
/// <param name="expanded">The <typeparamref name="T"/> current expanded property value</param>
@@ -30,9 +99,11 @@ protected void DrawFoldOutGroup<T>(Type type, Action displayProperties, bool exp
3099
EditorGUI.BeginChangeCheck();
31100
serializedObject.Update();
32101
var currentClass = typeof(T);
102+
33103
if (type.IsSubclassOf(currentClass) || (!type.IsSubclassOf(currentClass) && currentClass.IsSubclassOf(typeof(TT))))
34104
{
35105
var expandedValue = EditorGUILayout.BeginFoldoutHeaderGroup(expanded, $"{currentClass.Name} Properties");
106+
36107
if (expandedValue)
37108
{
38109
EditorGUILayout.EndFoldoutHeaderGroup();

com.unity.netcode.gameobjects/Editor/NetworkTransformEditor.cs

+78-7
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public class NetworkTransformEditor : NetcodeEditorBase<NetworkTransform>
2828
private SerializedProperty m_ScaleThresholdProperty;
2929
private SerializedProperty m_InLocalSpaceProperty;
3030
private SerializedProperty m_InterpolateProperty;
31+
private SerializedProperty m_PositionInterpolationTypeProperty;
32+
private SerializedProperty m_RotationInterpolationTypeProperty;
33+
private SerializedProperty m_ScaleInterpolationTypeProperty;
34+
35+
private SerializedProperty m_PositionMaximumInterpolationTimeProperty;
36+
private SerializedProperty m_RotationMaximumInterpolationTimeProperty;
37+
private SerializedProperty m_ScaleMaximumInterpolationTimeProperty;
3138

3239
private SerializedProperty m_UseQuaternionSynchronization;
3340
private SerializedProperty m_UseQuaternionCompression;
@@ -36,6 +43,7 @@ public class NetworkTransformEditor : NetcodeEditorBase<NetworkTransform>
3643
private SerializedProperty m_AuthorityMode;
3744

3845
private static int s_ToggleOffset = 45;
46+
3947
private static float s_MaxRowWidth = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + 5;
4048
private static GUIContent s_PositionLabel = EditorGUIUtility.TrTextContent("Position");
4149
private static GUIContent s_RotationLabel = EditorGUIUtility.TrTextContent("Rotation");
@@ -61,6 +69,15 @@ public override void OnEnable()
6169
m_ScaleThresholdProperty = serializedObject.FindProperty(nameof(NetworkTransform.ScaleThreshold));
6270
m_InLocalSpaceProperty = serializedObject.FindProperty(nameof(NetworkTransform.InLocalSpace));
6371
m_InterpolateProperty = serializedObject.FindProperty(nameof(NetworkTransform.Interpolate));
72+
73+
m_PositionInterpolationTypeProperty = serializedObject.FindProperty(nameof(NetworkTransform.PositionInterpolationType));
74+
m_PositionMaximumInterpolationTimeProperty = serializedObject.FindProperty(nameof(NetworkTransform.PositionMaxInterpolationTime));
75+
m_RotationInterpolationTypeProperty = serializedObject.FindProperty(nameof(NetworkTransform.RotationInterpolationType));
76+
m_RotationMaximumInterpolationTimeProperty = serializedObject.FindProperty(nameof(NetworkTransform.RotationMaxInterpolationTime));
77+
m_ScaleInterpolationTypeProperty = serializedObject.FindProperty(nameof(NetworkTransform.ScaleInterpolationType));
78+
m_ScaleMaximumInterpolationTimeProperty = serializedObject.FindProperty(nameof(NetworkTransform.ScaleMaxInterpolationTime));
79+
80+
6481
m_UseQuaternionSynchronization = serializedObject.FindProperty(nameof(NetworkTransform.UseQuaternionSynchronization));
6582
m_UseQuaternionCompression = serializedObject.FindProperty(nameof(NetworkTransform.UseQuaternionCompression));
6683
m_UseHalfFloatPrecision = serializedObject.FindProperty(nameof(NetworkTransform.UseHalfFloatPrecision));
@@ -141,9 +158,21 @@ private void DisplayNetworkTransformProperties()
141158
}
142159
EditorGUILayout.Space();
143160
EditorGUILayout.LabelField("Thresholds", EditorStyles.boldLabel);
144-
EditorGUILayout.PropertyField(m_PositionThresholdProperty);
145-
EditorGUILayout.PropertyField(m_RotAngleThresholdProperty);
146-
EditorGUILayout.PropertyField(m_ScaleThresholdProperty);
161+
if (networkTransform.SynchronizePosition)
162+
{
163+
EditorGUILayout.PropertyField(m_PositionThresholdProperty);
164+
}
165+
166+
if (networkTransform.SynchronizeRotation)
167+
{
168+
EditorGUILayout.PropertyField(m_RotAngleThresholdProperty);
169+
}
170+
171+
if (networkTransform.SynchronizeScale)
172+
{
173+
EditorGUILayout.PropertyField(m_ScaleThresholdProperty);
174+
}
175+
147176
EditorGUILayout.Space();
148177
EditorGUILayout.LabelField("Delivery", EditorStyles.boldLabel);
149178
EditorGUILayout.PropertyField(m_TickSyncChildren);
@@ -158,9 +187,53 @@ private void DisplayNetworkTransformProperties()
158187
EditorGUILayout.PropertyField(m_InLocalSpaceProperty);
159188
if (!networkTransform.HideInterpolateValue)
160189
{
161-
EditorGUILayout.PropertyField(m_InterpolateProperty);
190+
if (networkTransform.Interpolate)
191+
{
192+
EditorGUILayout.Space();
193+
}
194+
DrawPropertyField(m_InterpolateProperty, networkTransform.Interpolate ? FontStyle.Bold : FontStyle.Normal);
195+
if (networkTransform.Interpolate)
196+
{
197+
BeginIndent();
198+
if (networkTransform.SynchronizePosition)
199+
{
200+
DrawPropertyField(m_PositionInterpolationTypeProperty);
201+
// Only display when using Lerp.
202+
if (networkTransform.PositionInterpolationType == NetworkTransform.InterpolationTypes.Lerp)
203+
{
204+
BeginIndent();
205+
DrawPropertyField(m_SlerpPosition);
206+
DrawPropertyField(m_PositionMaximumInterpolationTimeProperty);
207+
EndIndent();
208+
}
209+
}
210+
if (networkTransform.SynchronizeRotation)
211+
{
212+
DrawPropertyField(m_RotationInterpolationTypeProperty);
213+
// Only display when using Lerp.
214+
if (networkTransform.RotationInterpolationType == NetworkTransform.InterpolationTypes.Lerp)
215+
{
216+
BeginIndent();
217+
DrawPropertyField(m_RotationMaximumInterpolationTimeProperty);
218+
EndIndent();
219+
}
220+
}
221+
if (networkTransform.SynchronizeScale)
222+
{
223+
DrawPropertyField(m_ScaleInterpolationTypeProperty);
224+
// Only display when using Lerp.
225+
if (networkTransform.ScaleInterpolationType == NetworkTransform.InterpolationTypes.Lerp)
226+
{
227+
BeginIndent();
228+
DrawPropertyField(m_ScaleMaximumInterpolationTimeProperty);
229+
EndIndent();
230+
}
231+
}
232+
EndIndent();
233+
EditorGUILayout.Space();
234+
}
162235
}
163-
EditorGUILayout.PropertyField(m_SlerpPosition);
236+
164237
EditorGUILayout.PropertyField(m_UseQuaternionSynchronization);
165238
if (m_UseQuaternionSynchronization.boolValue)
166239
{
@@ -190,8 +263,6 @@ private void DisplayNetworkTransformProperties()
190263
#endif // COM_UNITY_MODULES_PHYSICS2D
191264
}
192265

193-
194-
195266
/// <inheritdoc/>
196267
public override void OnInspectorGUI()
197268
{

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ private void SerializeRead(FastBufferReader reader)
7474
}
7575
}
7676

77-
/// <summary>
78-
/// The serialization implementation of <see cref="INetworkSerializable"/>.
79-
/// </summary>
77+
/// <inheritdoc />
8078
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
8179
{
8280
if (serializer.IsReader)

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,7 @@ private void SerializeRead(FastBufferReader reader)
5858
}
5959
}
6060

61-
/// <summary>
62-
/// The serialization implementation of <see cref="INetworkSerializable"/>.
63-
/// </summary>
61+
/// <inheritdoc />
6462
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
6563
{
6664
if (serializer.IsReader)

0 commit comments

Comments
 (0)