diff --git a/Runtime/UXComponent/Button/UXButton.cs b/Runtime/UXComponent/Button/UXButton.cs index 435a178..c00aff5 100644 --- a/Runtime/UXComponent/Button/UXButton.cs +++ b/Runtime/UXComponent/Button/UXButton.cs @@ -47,6 +47,9 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand private bool m_IsNavFocused = false; + // ===== 新增:延迟撤销选择的 pending 标记,用于避免在协程尚未完成时读取过时的锁状态 ===== + private bool _deferredDeselectPending = false; + #endregion #region Properties @@ -118,6 +121,8 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand { if (_resetRoutine != null) StopCoroutine(_resetRoutine); + if (_deferredDeselectRoutine != null) + StopCoroutine(_deferredDeselectRoutine); base.OnDestroy(); } @@ -199,7 +204,9 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand if (navigation.mode != UXNavigation.Mode.None) { - if ((m_Mode == ButtonModeType.Normal && m_IsFocusLocked) || + // ===== 修改:当有 deferred deselect pending 时,不应认为 focus 仍旧被 lock ===== + bool focusLockedEffective = m_IsFocusLocked && !_deferredDeselectPending; + if ((m_Mode == ButtonModeType.Normal && focusLockedEffective) || (m_Mode == ButtonModeType.Toggle && _mTogSelected)) { SetState(SelectionState.Selected); @@ -233,7 +240,9 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand if (navigation.mode != UXNavigation.Mode.None) { - if ((m_Mode == ButtonModeType.Normal && m_IsFocusLocked) || + // ===== 修改:同上,不要在 deferred pending 时误用旧的 lock 状态 ===== + bool focusLockedEffective = m_IsFocusLocked && !_deferredDeselectPending; + if ((m_Mode == ButtonModeType.Normal && focusLockedEffective) || (m_Mode == ButtonModeType.Toggle && _mTogSelected)) { SetState(SelectionState.Selected); @@ -369,17 +378,24 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand private IEnumerator DeferredDeselectCheck() { - yield return null; + // 标记开始:表示我们在等待 EventSystem 正确更新选择(避免竞态) + _deferredDeselectPending = true; + + yield return null; // 等一帧让 EventSystem 更新 currentSelectedGameObject bool selectionIsNull = EventSystem.current == null || EventSystem.current.currentSelectedGameObject == null; if (selectionIsNull) { m_IsNavFocused = false; - s_LockedButton = null; + // ===== 更安全的解锁:仅当静态锁指向自己时才清理它,避免影响其他按钮 ===== + if (s_LockedButton == this) + s_LockedButton = null; m_IsFocusLocked = false; } + // 取消 pending 标记并清理协程引用 + _deferredDeselectPending = false; _deferredDeselectRoutine = null; } @@ -395,6 +411,7 @@ public class UXButton : UXSelectable, IButton, IPointerClickHandler, ISubmitHand { StopCoroutine(_deferredDeselectRoutine); _deferredDeselectRoutine = null; + _deferredDeselectPending = false; } // 延迟一帧再判断 EventSystem.current.currentSelectedGameObject,避免读取到旧值