Skip to content

Commit 00525f7

Browse files
update
Finalizing editor inspector view UI for excluding animator properties. Added some additional logic to NetworkAnimator. Added first test that verifies excluding parameters works.
1 parent 0fe48b2 commit 00525f7

File tree

10 files changed

+321
-8
lines changed

10 files changed

+321
-8
lines changed

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

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
using System.Linq;
12
using Unity.Netcode.Components;
23
using UnityEditor;
3-
//using UnityEngine;
4+
using UnityEngine;
45

56
namespace Unity.Netcode.Editor
67
{
@@ -11,7 +12,7 @@ namespace Unity.Netcode.Editor
1112
[CanEditMultipleObjects]
1213
public class NetworkAnimatorEditor : NetcodeEditorBase<NetworkAnimator>
1314
{
14-
15+
private static float s_MaxRowWidth = EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + 5;
1516
private SerializedProperty m_AuthorityMode;
1617
private SerializedProperty m_Animator;
1718

@@ -30,10 +31,37 @@ private void DisplayNetworkAnimatorProperties()
3031
if (networkAnimator.Animator != null)
3132
{
3233
EditorGUILayout.Space();
33-
EditorGUILayout.LabelField("Animator Parameters", EditorStyles.boldLabel);
34+
networkAnimator.AnimatorParametersExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(networkAnimator.AnimatorParametersExpanded, $"Animator Parameters to Synchronize");
3435
{
35-
// Add parameter list here
36+
var parameters = networkAnimator.Animator.parameters;
37+
networkAnimator.AnimatorParameterEntryTable.Clear();
38+
foreach (var parameterEntry in networkAnimator.AnimatorParameterEntries)
39+
{
40+
if (!networkAnimator.AnimatorParameterEntryTable.ContainsKey(parameterEntry.NameHash))
41+
{
42+
networkAnimator.AnimatorParameterEntryTable.Add(parameterEntry.NameHash, parameterEntry);
43+
}
44+
}
45+
if (networkAnimator.AnimatorParametersExpanded)
46+
{
47+
foreach (var parameter in parameters)
48+
{
49+
if (!networkAnimator.AnimatorParameterEntryTable.ContainsKey(parameter.nameHash))
50+
{
51+
networkAnimator.AnimatorParameterEntryTable.Add(parameter.nameHash, new NetworkAnimator.AnimatorParameterEntry(parameter));
52+
}
53+
var parameterEntry = networkAnimator.AnimatorParameterEntryTable[parameter.nameHash];
54+
parameterEntry.Synchronize = EditorGUILayout.ToggleLeft($"{parameterEntry.Name} ({parameterEntry.ParameterType.ToString()})", parameterEntry.Synchronize);
55+
parameterEntry.ParameterType = parameter.type;
56+
parameterEntry.Name = parameter.name;
57+
parameterEntry.NameHash = parameter.nameHash;
58+
networkAnimator.AnimatorParameterEntryTable[parameter.nameHash] = parameterEntry;
59+
}
60+
}
61+
networkAnimator.AnimatorParameterEntries = networkAnimator.AnimatorParameterEntryTable.Values.ToList();
3662
}
63+
64+
EditorGUILayout.EndFoldoutHeaderGroup();
3765
}
3866
}
3967

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

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,13 @@ public enum AuthorityModes
221221
Owner,
222222
}
223223

224-
225224
/// <summary>
226225
/// Determines whether this <see cref="NetworkAnimator"/> instance will have state updates pushed by the server or the client owner.
227226
/// <see cref="AuthorityModes"/>
228227
/// </summary>
229228
#if MULTIPLAYER_SERVICES_SDK_INSTALLED
230-
[Tooltip("Selects who has authority (sends state updates) over the <see cref="NetworkAnimator"/> instance. When the network topology is set to distributed authority, this always defaults to owner authority. If server (the default), then only server-side adjustments to the " +
231-
"<see cref="NetworkAnimator"/> instance will be synchronized with clients. If owner (or client), then only the owner-side adjustments to the <see cref="NetworkAnimator"/> instance will be synchronized with both the server and other clients.")]
229+
[Tooltip("Selects who has authority(sends state updates) over the<see cref=\"NetworkAnimator\"/> instance.When the network topology is set to distributed authority, this always defaults to owner authority.If server (the default), then only server-side adjustments to the " +
230+
"<see cref=\"NetworkAnimator\"> instance will be synchronized with clients. If owner (or client), then only the owner-side adjustments to the <see cref=\"NetworkAnimator\"/> instance will be synchronized with both the server and other clients.")]
232231
#else
233232
[Tooltip("Selects who has authority (sends state updates) over the <see cref=\"NetworkAnimator\"/> instance. If server (the default), then only server-side adjustments to the <see cref=\"NetworkAnimator\"/> instance will be synchronized with clients. If owner (or client), " +
234233
"then only the owner-side adjustments to the <see cref=\"NetworkAnimator\"/> instance will be synchronized with both the server and other clients.")]
@@ -265,8 +264,34 @@ private void BuildDestinationToTransitionInfoTable()
265264
}
266265
}
267266

267+
[Serializable]
268+
internal class AnimatorParameterEntry
269+
{
270+
public bool Synchronize;
271+
public int NameHash;
272+
public string Name;
273+
public AnimatorControllerParameterType ParameterType;
274+
#if UNITY_EDITOR
275+
public AnimatorParameterEntry(AnimatorControllerParameter parameter)
276+
{
277+
Synchronize = true;
278+
NameHash = parameter.nameHash;
279+
Name = parameter.name;
280+
ParameterType = parameter.type;
281+
}
282+
#endif
283+
public AnimatorParameterEntry() { }
284+
}
285+
286+
[HideInInspector]
287+
[SerializeField]
288+
internal List<AnimatorParameterEntry> AnimatorParameterEntries;
289+
290+
internal Dictionary<int, AnimatorParameterEntry> AnimatorParameterEntryTable = new Dictionary<int, AnimatorParameterEntry>();
268291

269292
#if UNITY_EDITOR
293+
internal bool AnimatorParametersExpanded;
294+
270295
private void ParseStateMachineStates(int layerIndex, ref AnimatorController animatorController, ref AnimatorStateMachine stateMachine)
271296
{
272297
for (int y = 0; y < stateMachine.states.Length; y++)
@@ -639,6 +664,14 @@ protected virtual void Awake()
639664
return;
640665
}
641666

667+
foreach (var parameterEntry in AnimatorParameterEntries)
668+
{
669+
if (!AnimatorParameterEntryTable.ContainsKey(parameterEntry.NameHash))
670+
{
671+
AnimatorParameterEntryTable.Add(parameterEntry.NameHash, parameterEntry);
672+
}
673+
}
674+
642675
int layers = m_Animator.layerCount;
643676
// Initializing the below arrays for everyone handles an issue
644677
// when running in owner authoritative mode and the owner changes.
@@ -682,11 +715,17 @@ protected virtual void Awake()
682715
for (var i = 0; i < parameters.Length; i++)
683716
{
684717
var parameter = parameters[i];
718+
var synchronizeParameter = true;
719+
if (AnimatorParameterEntryTable.ContainsKey(parameter.nameHash))
720+
{
721+
synchronizeParameter = AnimatorParameterEntryTable[parameter.nameHash].Synchronize;
722+
}
685723

686724
var cacheParam = new AnimatorParamCache
687725
{
688726
Type = UnsafeUtility.EnumToInt(parameter.type),
689-
Hash = parameter.nameHash
727+
Hash = parameter.nameHash,
728+
Exclude = !synchronizeParameter
690729
};
691730

692731
unsafe
@@ -793,6 +832,10 @@ private void WriteSynchronizationData<T>(ref BufferSerializer<T> serializer) whe
793832
m_ParametersToUpdate.Clear();
794833
for (int i = 0; i < m_CachedAnimatorParameters.Length; i++)
795834
{
835+
if (m_CachedAnimatorParameters[i].Exclude)
836+
{
837+
continue;
838+
}
796839
m_ParametersToUpdate.Add(i);
797840
}
798841
// Write, apply, and serialize
@@ -1184,6 +1227,7 @@ private unsafe void WriteParameters(ref FastBufferWriter writer)
11841227

11851228
if (cacheValue.Exclude)
11861229
{
1230+
Debug.LogWarning($"Parameter hash:{cacheValue.Hash} should be excluded but is in the parameters to update list when writing parameter values!");
11871231
continue;
11881232
}
11891233

testproject/Assets/DefaultNetworkPrefabs.asset

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,21 @@ MonoBehaviour:
224224
SourcePrefabToOverride: {fileID: 0}
225225
SourceHashToOverride: 0
226226
OverridingTargetPrefab: {fileID: 0}
227+
- Override: 0
228+
Prefab: {fileID: 8188135024827620138, guid: c000e98bc12da2941a59ec61c260dd6a,
229+
type: 3}
230+
SourcePrefabToOverride: {fileID: 0}
231+
SourceHashToOverride: 0
232+
OverridingTargetPrefab: {fileID: 0}
233+
- Override: 0
234+
Prefab: {fileID: 1488386875393216933, guid: 7752ac8c0bfaed64c8de839537204114,
235+
type: 3}
236+
SourcePrefabToOverride: {fileID: 0}
237+
SourceHashToOverride: 0
238+
OverridingTargetPrefab: {fileID: 0}
239+
- Override: 0
240+
Prefab: {fileID: 6958138586392507362, guid: 4b31f769283d3c24ca2a5d6baf28a806,
241+
type: 3}
242+
SourcePrefabToOverride: {fileID: 0}
243+
SourceHashToOverride: 0
244+
OverridingTargetPrefab: {fileID: 0}

testproject/Assets/Tests/Manual/NetworkAnimatorTests/CubeAnimatorController.controller

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,12 @@ AnimatorController:
761761
m_DefaultInt: 0
762762
m_DefaultBool: 0
763763
m_Controller: {fileID: 9100000}
764+
- m_Name: ExcludeFromSync
765+
m_Type: 1
766+
m_DefaultFloat: 0
767+
m_DefaultInt: 0
768+
m_DefaultBool: 0
769+
m_Controller: {fileID: 9100000}
764770
m_AnimatorLayers:
765771
- serializedVersion: 5
766772
m_Name: Base Layer

testproject/Assets/Tests/Runtime/Animation/AnimatorTestHelper.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ public void UpdateParameters(ParameterValues parameterValues)
108108
m_Animator.SetBool("TestBool", parameterValues.BoolValue);
109109
}
110110

111+
public void UpdateExcludedParameter(float value)
112+
{
113+
m_Animator.SetFloat("ExcludeFromSync", value);
114+
}
115+
116+
public float GetExcludedParameter()
117+
{
118+
return m_Animator.GetFloat("ExcludeFromSync");
119+
}
120+
111121
public bool GetCurrentTriggerState()
112122
{
113123
return m_Animator.GetBool("TestTrigger");

testproject/Assets/Tests/Runtime/Animation/NetworkAnimatorTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,39 @@ private bool ParameterValuesMatch(OwnerShipMode ownerShipMode, AuthoritativeMode
157157
return true;
158158
}
159159

160+
private bool ExcludedParameterValuesDoNotMatch()
161+
{
162+
var objectToUpdate = AnimatorTestHelper.ServerSideInstance;
163+
var excludedParameterValue = objectToUpdate.GetExcludedParameter();
164+
if (m_AuthoritativeMode == AuthoritativeMode.OwnerAuth)
165+
{
166+
objectToUpdate = m_OwnerShipMode == OwnerShipMode.ClientOwner ? AnimatorTestHelper.ClientSideInstances[m_ClientNetworkManagers[0].LocalClientId] : AnimatorTestHelper.ServerSideInstance;
167+
excludedParameterValue = objectToUpdate.GetExcludedParameter();
168+
if (m_OwnerShipMode == OwnerShipMode.ClientOwner)
169+
{
170+
if (excludedParameterValue == AnimatorTestHelper.ServerSideInstance.GetExcludedParameter())
171+
{
172+
return false;
173+
}
174+
}
175+
}
176+
177+
foreach (var animatorTestHelper in AnimatorTestHelper.ClientSideInstances)
178+
{
179+
if (objectToUpdate == animatorTestHelper.Value)
180+
{
181+
continue;
182+
}
183+
var clientExcludedParameter = animatorTestHelper.Value.GetExcludedParameter();
184+
if (clientExcludedParameter == excludedParameterValue)
185+
{
186+
return false;
187+
}
188+
}
189+
return true;
190+
}
191+
192+
160193
public enum OwnerShipMode
161194
{
162195
ServerOwner,
@@ -268,6 +301,42 @@ public void ParameterUpdateTests()
268301
VerboseDebug($" ------------------ Parameter Test [{m_OwnerShipMode}] Stopping ------------------ ");
269302
}
270303

304+
[Test]
305+
public void ParameterExcludedTests()
306+
{
307+
VerboseDebug($" ++++++++++++++++++ Parameter Excluded Test [{m_OwnerShipMode}] Starting ++++++++++++++++++ ");
308+
309+
// Spawn our test animator object
310+
var objectInstance = SpawnPrefab(m_OwnerShipMode == OwnerShipMode.ClientOwner, m_AuthoritativeMode);
311+
312+
// Wait for it to spawn server-side
313+
var success = WaitForConditionOrTimeOutWithTimeTravel(() => AnimatorTestHelper.ServerSideInstance != null);
314+
Assert.True(success, $"Timed out waiting for the server-side instance of {GetNetworkAnimatorName(m_AuthoritativeMode)} to be spawned!");
315+
316+
// Wait for it to spawn client-side
317+
success = WaitForConditionOrTimeOutWithTimeTravel(() => AnimatorTestHelper.ClientSideInstances.ContainsKey(m_ClientNetworkManagers[0].LocalClientId));
318+
Assert.True(success, $"Timed out waiting for the client-side instance of {GetNetworkAnimatorName(m_AuthoritativeMode)} to be spawned!");
319+
320+
if (m_AuthoritativeMode == AuthoritativeMode.OwnerAuth)
321+
{
322+
var objectToUpdate = m_OwnerShipMode == OwnerShipMode.ClientOwner ? AnimatorTestHelper.ClientSideInstances[m_ClientNetworkManagers[0].LocalClientId] : AnimatorTestHelper.ServerSideInstance;
323+
// Set the excluded parameter value via the owner instance
324+
objectToUpdate.UpdateExcludedParameter(Random.Range(1.5f, 100.0f));
325+
}
326+
else
327+
{
328+
// Set the excluded parameter value via the server instance
329+
AnimatorTestHelper.ServerSideInstance.UpdateExcludedParameter(Random.Range(1.5f, 100.0f));
330+
}
331+
332+
TimeTravel(0.5, 60);
333+
// Wait for the client side to update to the new parameter values
334+
success = WaitForConditionOrTimeOutWithTimeTravel(ExcludedParameterValuesDoNotMatch);
335+
Assert.True(success, $"The excluded parameter was synchronized!");
336+
VerboseDebug($" ------------------ Parameter Test [{m_OwnerShipMode}] Stopping ------------------ ");
337+
}
338+
339+
271340

272341
private bool AllTriggersDetected(OwnerShipMode ownerShipMode)
273342
{

testproject/Assets/Tests/Runtime/Animation/Resources/AnimatorObject.prefab

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ MonoBehaviour:
386386
SpawnWithObservers: 1
387387
DontDestroyWithOwner: 0
388388
AutoObjectParentSync: 1
389+
SyncOwnerTransformWhenParented: 1
390+
AllowOwnerToParent: 0
389391
--- !u!95 &6515743261518512780
390392
Animator:
391393
serializedVersion: 7
@@ -420,6 +422,9 @@ MonoBehaviour:
420422
m_Script: {fileID: 11500000, guid: e8d0727d5ae3244e3b569694d3912374, type: 3}
421423
m_Name:
422424
m_EditorClassIdentifier:
425+
ShowTopMostFoldoutHeaderGroup: 1
426+
NetworkAnimatorExpanded: 0
427+
AuthorityMode: 0
423428
TransitionStateInfoList:
424429
- IsCrossFadeExit: 0
425430
Layer: 0
@@ -463,6 +468,51 @@ MonoBehaviour:
463468
TransitionDuration: 0.25
464469
TriggerNameHash: 1080829965
465470
TransitionIndex: 2
471+
AnimatorParameterEntries:
472+
- Synchronize: 1
473+
NameHash: 807753530
474+
Name: Rotate
475+
ParameterType: 4
476+
- Synchronize: 1
477+
NameHash: -623385122
478+
Name: Pulse
479+
ParameterType: 9
480+
- Synchronize: 1
481+
NameHash: -758535706
482+
Name: TestFloat
483+
ParameterType: 1
484+
- Synchronize: 1
485+
NameHash: -1682086748
486+
Name: TestInt
487+
ParameterType: 3
488+
- Synchronize: 1
489+
NameHash: 953368263
490+
Name: TestBool
491+
ParameterType: 4
492+
- Synchronize: 1
493+
NameHash: 1033918907
494+
Name: TestTrigger
495+
ParameterType: 9
496+
- Synchronize: 1
497+
NameHash: -1545343146
498+
Name: LateJoinTest
499+
ParameterType: 4
500+
- Synchronize: 1
501+
NameHash: 1080829965
502+
Name: Attack
503+
ParameterType: 9
504+
- Synchronize: 1
505+
NameHash: -1936256502
506+
Name: WeaponType
507+
ParameterType: 3
508+
- Synchronize: 1
509+
NameHash: 1855955664
510+
Name: Weapon
511+
ParameterType: 3
512+
- Synchronize: 0
513+
NameHash: -1993481368
514+
Name: ExcludeFromSync
515+
ParameterType: 1
466516
m_Animator: {fileID: 6515743261518512780}
467517
--- !u!114 &-8876216387850298050
468518
MonoBehaviour:
@@ -476,6 +526,7 @@ MonoBehaviour:
476526
m_Script: {fileID: 11500000, guid: 48b31fae64dc3c14c98e3c5d09cb1269, type: 3}
477527
m_Name:
478528
m_EditorClassIdentifier:
529+
ShowTopMostFoldoutHeaderGroup: 1
479530
--- !u!114 &5194088446451573146
480531
MonoBehaviour:
481532
m_ObjectHideFlags: 0
@@ -488,3 +539,4 @@ MonoBehaviour:
488539
m_Script: {fileID: 11500000, guid: a915cfb2e4f748e4f9526a8bf5ee84f2, type: 3}
489540
m_Name:
490541
m_EditorClassIdentifier:
542+
ShowTopMostFoldoutHeaderGroup: 1

0 commit comments

Comments
 (0)