Skip to content

Commit 5f1b0ed

Browse files
fix: NetworkAnimator not synchronizing changes to layer weights (#2399)
* fix This resolves the regression bug where layer weight updates were not being synchronized if no state transition was occurring. * test Adding test to verify layer weight changes are updated for connected clients and that late joining clients are synchronized to the updated weight value. * test manual Adding small manual test adjustment to verify the change in a layer weight is synchronized.
1 parent 2400c2d commit 5f1b0ed

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
2121
- Network prefabs are now stored in a ScriptableObject that can be shared between NetworkManagers, and have been exposed for public access. By default, a Default Prefabs List is created that contains all NetworkObject prefabs in the project, and new NetworkManagers will default to using that unless that option is turned off in the Netcode for GameObjects settings. Existing NetworkManagers will maintain their existing lists, which can be migrated to the new format via a button in their inspector. (#2322)
2222

2323
### Fixed
24+
- Fixed issue where changes to a layer's weight would not synchronize unless a state transition was occurring.(#2399)
2425
- Fixed issue where `NetworkManager.LocalClientId` was returning the `NetworkTransport.ServerClientId` as opposed to the `NetworkManager.m_LocalClientId`. (#2398)
2526
- Fixed a UTP test that was failing when you install Unity Transport package 2.0.0 or newer. (#2347)
2627
- Fixed issue where `NetcodeSettingsProvider` would throw an exception in Unity 2020.3.x versions. (#2345)

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,16 @@ internal unsafe void UpdateParameters(ref ParametersUpdateMessage parametersUpda
11001100
/// </summary>
11011101
internal void UpdateAnimationState(AnimationState animationState)
11021102
{
1103+
// Handle updating layer weights first.
1104+
if (animationState.Layer < m_LayerWeights.Length)
1105+
{
1106+
if (m_LayerWeights[animationState.Layer] != animationState.Weight)
1107+
{
1108+
m_Animator.SetLayerWeight(animationState.Layer, animationState.Weight);
1109+
}
1110+
}
1111+
1112+
// If there is no state transition then return
11031113
if (animationState.StateHash == 0)
11041114
{
11051115
return;
@@ -1147,7 +1157,6 @@ internal void UpdateAnimationState(AnimationState animationState)
11471157
m_Animator.Play(animationState.StateHash, animationState.Layer, animationState.NormalizedTime);
11481158
}
11491159
}
1150-
m_Animator.SetLayerWeight(animationState.Layer, animationState.Weight);
11511160
}
11521161

11531162
/// <summary>

testproject/Assets/Tests/Manual/NetworkAnimatorTests/AnimatedCubeController.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,27 @@ private void BeginAttack(int weaponType)
179179
m_NetworkAnimator.SetTrigger("Attack");
180180
}
181181

182+
private void SetLayerWeight(int layer, float weight)
183+
{
184+
m_Animator.SetLayerWeight(layer, weight);
185+
}
186+
187+
private float GetLayerWeight(int layer)
188+
{
189+
return m_Animator.GetLayerWeight(layer);
190+
}
191+
182192
private void LateUpdate()
183193
{
184194

185195
if (!IsSpawned || !IsOwner)
186196
{
187197
if (!IsOwner && IsSpawned)
188198
{
199+
if (Input.GetKeyDown(KeyCode.Alpha4))
200+
{
201+
Debug.Log($"Layer 1 weight: {GetLayerWeight(1)}");
202+
}
189203
DisplayTestIntValueIfChanged();
190204
return;
191205
}
@@ -229,6 +243,10 @@ private void LateUpdate()
229243
BeginAttack(2);
230244
}
231245

246+
if (Input.GetKeyDown(KeyCode.Alpha3))
247+
{
248+
SetLayerWeight(1, 0.75f);
249+
}
232250
}
233251
}
234252
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,15 @@ public NetworkAnimator GetNetworkAnimator()
153153
{
154154
return m_NetworkAnimator;
155155
}
156+
157+
public void SetLayerWeight(int layer, float weight)
158+
{
159+
m_Animator.SetLayerWeight(layer, weight);
160+
}
161+
162+
public float GetLayerWeight(int layer)
163+
{
164+
return m_Animator.GetLayerWeight(layer);
165+
}
156166
}
157167
}

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

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ public IEnumerator ParameterUpdateTests([Values] OwnerShipMode ownerShipMode, [V
190190

191191
private bool AllTriggersDetected(OwnerShipMode ownerShipMode)
192192
{
193-
var serverParameters = AnimatorTestHelper.ServerSideInstance.GetParameterValues();
194193
if (ownerShipMode == OwnerShipMode.ClientOwner)
195194
{
196195
if (!TriggerTest.ClientsThatTriggered.Contains(m_ServerNetworkManager.LocalClientId))
@@ -213,6 +212,31 @@ private bool AllTriggersDetected(OwnerShipMode ownerShipMode)
213212
return true;
214213
}
215214

215+
private bool AllInstancesSameLayerWeight(OwnerShipMode ownerShipMode, int layer, float targetWeight)
216+
{
217+
218+
if (ownerShipMode == OwnerShipMode.ClientOwner)
219+
{
220+
if (AnimatorTestHelper.ServerSideInstance.GetLayerWeight(layer) != targetWeight)
221+
{
222+
return false;
223+
}
224+
}
225+
226+
foreach (var animatorTestHelper in AnimatorTestHelper.ClientSideInstances)
227+
{
228+
if (ownerShipMode == OwnerShipMode.ClientOwner && animatorTestHelper.Value.OwnerClientId == m_ClientNetworkManagers[0].LocalClientId)
229+
{
230+
continue;
231+
}
232+
if (animatorTestHelper.Value.GetLayerWeight(layer) != targetWeight)
233+
{
234+
return false;
235+
}
236+
}
237+
return true;
238+
}
239+
216240
private bool WaitForClientsToInitialize()
217241
{
218242
foreach (var networkManager in m_ClientNetworkManagers)
@@ -367,6 +391,56 @@ protected override void OnNewClientCreated(NetworkManager networkManager)
367391
networkManager.NetworkConfig.Prefabs.Add(networkPrefab);
368392
}
369393

394+
/// <summary>
395+
/// Verifies that triggers are synchronized with currently connected clients
396+
/// </summary>
397+
/// <param name="authoritativeMode">Server or Owner authoritative</param>
398+
[UnityTest]
399+
public IEnumerator WeightUpdateTests([Values] OwnerShipMode ownerShipMode, [Values] AuthoritativeMode authoritativeMode)
400+
{
401+
CheckStateEnterCount.ResetTest();
402+
TriggerTest.ResetTest();
403+
VerboseDebug($" ++++++++++++++++++ Weight Test [{ownerShipMode}] Starting ++++++++++++++++++ ");
404+
TriggerTest.IsVerboseDebug = m_EnableVerboseDebug;
405+
AnimatorTestHelper.IsTriggerTest = m_EnableVerboseDebug;
406+
407+
// Spawn our test animator object
408+
var objectInstance = SpawnPrefab(ownerShipMode == OwnerShipMode.ClientOwner, authoritativeMode);
409+
410+
// Wait for it to spawn server-side
411+
yield return WaitForConditionOrTimeOut(() => AnimatorTestHelper.ServerSideInstance != null);
412+
AssertOnTimeout($"Timed out waiting for the server-side instance of {GetNetworkAnimatorName(authoritativeMode)} to be spawned!");
413+
414+
// Wait for it to spawn client-side
415+
yield return WaitForConditionOrTimeOut(WaitForClientsToInitialize);
416+
AssertOnTimeout($"Timed out waiting for the client-side instance of {GetNetworkAnimatorName(authoritativeMode)} to be spawned!");
417+
var animatorTestHelper = ownerShipMode == OwnerShipMode.ClientOwner ? AnimatorTestHelper.ClientSideInstances[m_ClientNetworkManagers[0].LocalClientId] : AnimatorTestHelper.ServerSideInstance;
418+
var layerCount = animatorTestHelper.GetAnimator().layerCount;
419+
420+
var animationStateCount = animatorTestHelper.GetAnimatorStateCount();
421+
Assert.True(layerCount == animationStateCount, $"AnimationState count {animationStateCount} does not equal the layer count {layerCount}!");
422+
423+
if (authoritativeMode == AuthoritativeMode.ServerAuth)
424+
{
425+
animatorTestHelper = AnimatorTestHelper.ServerSideInstance;
426+
}
427+
428+
animatorTestHelper.SetLayerWeight(1, 0.75f);
429+
// Wait for all instances to update their weight value for layer 1
430+
yield return WaitForConditionOrTimeOut(() => AllInstancesSameLayerWeight(ownerShipMode, 1, 0.75f));
431+
AssertOnTimeout($"Timed out waiting for all instances to match weight 0.75 on layer 1!");
432+
433+
// Now late join a client
434+
yield return CreateAndStartNewClient();
435+
436+
// Verify the late joined client is synchronized to the changed weight
437+
yield return WaitForConditionOrTimeOut(() => AllInstancesSameLayerWeight(ownerShipMode, 1, 0.75f));
438+
AssertOnTimeout($"[Late-Join] Timed out waiting for all instances to match weight 0.75 on layer 1!");
439+
440+
AnimatorTestHelper.IsTriggerTest = false;
441+
VerboseDebug($" ------------------ Weight Test [{ownerShipMode}] Stopping ------------------ ");
442+
}
443+
370444
/// <summary>
371445
/// Verifies that late joining clients are synchronized to an
372446
/// animator's trigger state.

0 commit comments

Comments
 (0)