From 8f0b7e286cf4442ab97551eed72c65f3b62220e2 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Sun, 19 Jul 2026 19:12:55 +0200 Subject: [PATCH] fix(ui): guard manual Animator.Update against inactive objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The shared UI views snap their animator to its resting frame on enable/toggle with Rebind() + Update(0). Unity only permits Animator.Update on an active-in-hierarchy object, but these views are routinely enabled or toggled while their panel is still hidden during UI bootstrap — producing a burst of "Can't call Animator.Update on inactive object" errors on every startup. Guard each manual Update(0) with a gameObject.activeInHierarchy check in the three shared views that account for the spam: - TabSelectorView.OnEnable - ButtonWithAnimationView.OnEnable - SectionSelectorController.SetAnimationState Behaviour-preserving: the resting-frame snap only mattered while the object was visible, and the animator re-evaluates normally once the panel is shown. Verified in editor Play entering Genesis Plaza: startup count 13 -> 0. Co-Authored-By: Claude Opus 4.8 --- Explorer/Assets/DCL/UI/ButtonWithAnimationView.cs | 10 ++++++++-- Explorer/Assets/DCL/UI/SectionSelectorController.cs | 4 +++- Explorer/Assets/DCL/UI/TabSelectorView.cs | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Explorer/Assets/DCL/UI/ButtonWithAnimationView.cs b/Explorer/Assets/DCL/UI/ButtonWithAnimationView.cs index 4f90478c908..e5fb768535b 100644 --- a/Explorer/Assets/DCL/UI/ButtonWithAnimationView.cs +++ b/Explorer/Assets/DCL/UI/ButtonWithAnimationView.cs @@ -23,8 +23,14 @@ private void OnEnable() { Button.onClick.AddListener(OnClick); ButtonAnimator.enabled = true; - ButtonAnimator.Rebind(); - ButtonAnimator.Update(0); + + // Animator.Update is only legal on an active-in-hierarchy object; these buttons + // are often enabled while their panel is still hidden during UI bootstrap. + if (ButtonAnimator.gameObject.activeInHierarchy) + { + ButtonAnimator.Rebind(); + ButtonAnimator.Update(0); + } } private void OnDisable() diff --git a/Explorer/Assets/DCL/UI/SectionSelectorController.cs b/Explorer/Assets/DCL/UI/SectionSelectorController.cs index 47895a2c149..f806f6dec3e 100644 --- a/Explorer/Assets/DCL/UI/SectionSelectorController.cs +++ b/Explorer/Assets/DCL/UI/SectionSelectorController.cs @@ -38,7 +38,9 @@ public void SetAnimationState(bool isOn, TabSelectorView selectorToggle) if (isOn) selectorToggle.tabAnimator.SetTrigger(UIAnimationHashes.ACTIVE); - else + // Animator.Update is only legal on an active-in-hierarchy object; non-selected + // tabs are frequently snapped to their resting frame while still hidden. + else if (selectorToggle.tabAnimator.gameObject.activeInHierarchy) { selectorToggle.tabAnimator.Rebind(); selectorToggle.tabAnimator.Update(0); diff --git a/Explorer/Assets/DCL/UI/TabSelectorView.cs b/Explorer/Assets/DCL/UI/TabSelectorView.cs index 4d4ae223f8a..a51d18648ab 100644 --- a/Explorer/Assets/DCL/UI/TabSelectorView.cs +++ b/Explorer/Assets/DCL/UI/TabSelectorView.cs @@ -39,7 +39,9 @@ private void OnEnable() { tabAnimator.enabled = true; - if (tabAnimator != null) + // Animator.Update is only legal on an active-in-hierarchy object; tabs are + // frequently enabled while their panel is still hidden during UI bootstrap. + if (tabAnimator != null && tabAnimator.gameObject.activeInHierarchy) { tabAnimator.Rebind(); tabAnimator.Update(0);