From 90882e7e3a118753522dddaee3a55376149ff44a Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Sat, 19 Oct 2024 18:21:21 -0500 Subject: [PATCH 1/3] fix Pre-calculate the required parameter write size needed as opposed to using the legacy constant value. --- .../Runtime/Components/NetworkAnimator.cs | 45 ++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs index 16b77ca5af..94dd9872e0 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs @@ -207,6 +207,10 @@ internal class TransitionStateinfo [SerializeField] internal List TransitionStateInfoList; + [HideInInspector] + [SerializeField] + private int m_TotalParameterSize; + // Used to get the associated transition information required to synchronize late joining clients with transitions // [Layer][DestinationState][TransitionStateInfo] private Dictionary> m_DestinationStateToTransitioninfo = new Dictionary>(); @@ -230,6 +234,7 @@ private void BuildDestinationToTransitionInfoTable() } } + #if UNITY_EDITOR private void ParseStateMachineStates(int layerIndex, ref AnimatorController animatorController, ref AnimatorStateMachine stateMachine) { @@ -263,7 +268,6 @@ private void ParseStateMachineStates(int layerIndex, ref AnimatorController anim { case AnimatorControllerParameterType.Trigger: { - if (transition.destinationStateMachine != null) { var destinationStateMachine = transition.destinationStateMachine; @@ -297,6 +301,32 @@ private void ParseStateMachineStates(int layerIndex, ref AnimatorController anim } } } + + private void OnValidate() + { + m_TotalParameterSize = sizeof(uint); + var parameters = m_Animator.parameters; + // Calculate the size of the parameter write buffer needed + foreach (var parameter in parameters) + { + switch (parameter.type) + { + case AnimatorControllerParameterType.Int: + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + { + m_TotalParameterSize += sizeof(int) * 2; + break; + } + case AnimatorControllerParameterType.Float: + { + m_TotalParameterSize += sizeof(float) + sizeof(int); + break; + } + } + } + } + #endif /// @@ -507,10 +537,6 @@ protected virtual bool OnIsServerAuthoritative() return NetworkManager ? !NetworkManager.DistributedAuthorityMode : true; } - // Animators only support up to 32 parameters - // TODO: Look into making this a range limited property - private const int k_MaxAnimationParams = 32; - private int[] m_TransitionHash; private int[] m_AnimationHash; private float[] m_LayerWeights; @@ -534,7 +560,7 @@ private unsafe struct AnimatorParamCache } // 128 bytes per Animator - private FastBufferWriter m_ParameterWriter = new FastBufferWriter(k_MaxAnimationParams * sizeof(float), Allocator.Persistent); + private FastBufferWriter m_ParameterWriter; private NativeArray m_CachedAnimatorParameters; @@ -586,6 +612,13 @@ public override void OnDestroy() protected virtual void Awake() { + if (m_ParameterWriter.IsInitialized) + { + m_ParameterWriter.Dispose(); + } + m_ParameterWriter = new FastBufferWriter(m_TotalParameterSize, Allocator.Persistent); + + int layers = m_Animator.layerCount; // Initializing the below arrays for everyone handles an issue // when running in owner authoritative mode and the owner changes. From 851d4325451da44c78e89214cc0c3bbb9c7864f9 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Mon, 21 Oct 2024 14:08:06 -0500 Subject: [PATCH 2/3] fix Decided this all could be handled during the Awake method with no need to pre-calculate during validation. Also made adjustments to have a more precise calculation for the size needed. --- .../Runtime/Components/NetworkAnimator.cs | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs index 94dd9872e0..e122e8f46f 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/NetworkAnimator.cs @@ -207,10 +207,6 @@ internal class TransitionStateinfo [SerializeField] internal List TransitionStateInfoList; - [HideInInspector] - [SerializeField] - private int m_TotalParameterSize; - // Used to get the associated transition information required to synchronize late joining clients with transitions // [Layer][DestinationState][TransitionStateInfo] private Dictionary> m_DestinationStateToTransitioninfo = new Dictionary>(); @@ -302,31 +298,6 @@ private void ParseStateMachineStates(int layerIndex, ref AnimatorController anim } } - private void OnValidate() - { - m_TotalParameterSize = sizeof(uint); - var parameters = m_Animator.parameters; - // Calculate the size of the parameter write buffer needed - foreach (var parameter in parameters) - { - switch (parameter.type) - { - case AnimatorControllerParameterType.Int: - case AnimatorControllerParameterType.Bool: - case AnimatorControllerParameterType.Trigger: - { - m_TotalParameterSize += sizeof(int) * 2; - break; - } - case AnimatorControllerParameterType.Float: - { - m_TotalParameterSize += sizeof(float) + sizeof(int); - break; - } - } - } - } - #endif /// @@ -612,12 +583,13 @@ public override void OnDestroy() protected virtual void Awake() { - if (m_ParameterWriter.IsInitialized) + if (!m_Animator) { - m_ParameterWriter.Dispose(); +#if !UNITY_EDITOR + Debug.LogError($"{nameof(NetworkAnimator)} {name} does not have an {nameof(UnityEngine.Animator)} assigned to it. The {nameof(NetworkAnimator)} will not initialize properly."); +#endif + return; } - m_ParameterWriter = new FastBufferWriter(m_TotalParameterSize, Allocator.Persistent); - int layers = m_Animator.layerCount; // Initializing the below arrays for everyone handles an issue @@ -648,6 +620,9 @@ protected virtual void Awake() } } + // The total initialization size calculated for the m_ParameterWriter write buffer. + var totalParameterSize = sizeof(uint); + // Build our reference parameter values to detect when they change var parameters = m_Animator.parameters; m_CachedAnimatorParameters = new NativeArray(parameters.Length, Allocator.Persistent); @@ -688,7 +663,37 @@ protected virtual void Awake() } m_CachedAnimatorParameters[i] = cacheParam; + + // Calculate parameter sizes (index + type size) + switch (parameter.type) + { + case AnimatorControllerParameterType.Int: + { + totalParameterSize += sizeof(int) * 2; + break; + } + case AnimatorControllerParameterType.Bool: + case AnimatorControllerParameterType.Trigger: + { + // Bool is serialized to 1 byte + totalParameterSize += sizeof(int) + 1; + break; + } + case AnimatorControllerParameterType.Float: + { + totalParameterSize += sizeof(int) + sizeof(float); + break; + } + } } + + if (m_ParameterWriter.IsInitialized) + { + m_ParameterWriter.Dispose(); + } + + // Create our parameter write buffer for serialization + m_ParameterWriter = new FastBufferWriter(totalParameterSize, Allocator.Persistent); } /// From 3843b26ae7326afc18ccc2983bc2e56e5f79e170 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Mon, 21 Oct 2024 14:08:59 -0500 Subject: [PATCH 3/3] update Adding change log entry --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index c335f3cdfb..13d8143f6a 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -12,6 +12,8 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed +- Fixed issue where `NetworkAnimator` would statically allocate write buffer space for `Animator` parameters that could cause a write error if the number of parameters exceeded the space allocated. + ### Changed ## [2.1.1] - 2024-10-18