Unity Button等悬浮高亮状态不重置的问题(Selectable)

在 Unity 2018.4 及以下版本中,偶现在悬浮状态(hover)时隐藏并再次显示该 UI 后,高亮状态不重置的问题,其中以 Button 居多。
问题描述
UGUI 按钮 A,点击时隐藏自身(SetActive(false)
)。之后通过其他方式将其开启,发现 A 仍然保持高亮状态,并没有重置。
此情况为偶现 Bug,对于克隆出的物体 + 自定义 EventSystem 事件分发组件,出现频率略高。
对于使用 UGUI 原生 EventSystem 的人来说,直接把Navigation
改成None
可解决一个相似的问题,但本文讨论的不是这种情况。
问题原因
因 UGUI 已开源,所以直接翻 UGUI 源码。
在Selectable.cs
中,有这样一段:
// Select on enable and add to the list.
protected override void OnEnable()
{
base.OnEnable();
s_List.Add(this);
var state = SelectionState.Normal;
// The button will be highlighted even in some cases where it shouldn't.
// For example: We only want to set the State as Highlighted if the StandaloneInputModule.m_CurrentInputMode == InputMode.Buttons
// But we dont have access to this, and it might not apply to other InputModules.
// TODO: figure out how to solve this. Case 617348.
if (hasSelection)
state = SelectionState.Highlighted;
m_CurrentSelectionState = state;
InternalEvaluateAndTransitionToSelectionState(true);
}
注释里的 TODO 有点意思。
继续往下追,发现设置完 State 后,InternalEvaluateAndTransitionToSelectionState
会调用设置状态的方法DoStateTransition
:
var transitionState = m_CurrentSelectionState;
if (IsActive() && !IsInteractable())
transitionState = SelectionState.Disabled;
DoStateTransition(transitionState, instant);
所以,因某些情况下hasSelection
没有重置成 false ,使得继承自 Selectable 的 UI 开启时依旧保持高亮状态。
查一下hasSelection
的引用:
public virtual void OnSelect(BaseEventData eventData)
{
hasSelection = true;
EvaluateAndTransitionToSelectionState(eventData);
}
public virtual void OnDeselect(BaseEventData eventData)
{
hasSelection = false;
EvaluateAndTransitionToSelectionState(eventData);
}
问题搞清楚了,Hover 状态时隐藏 UI 物体,某些情况下并不会触发OnDeselect
,尤其是对于自定义的 EventSystem 事件分发器来说。
了解了这些,再看 OnEnable 中的 TODO 注释,哭笑不得。
解决方法
对于确定要在关闭时重置状态的 Selectable UI,可以手动调用OnDeselect
方法:
private void OnDisable(){
mBtn.OnDeselect(null);
}