This commit is contained in:
陈思海 2025-12-17 18:44:18 +08:00
parent b54983c866
commit bac473fe0f

View File

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