在 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);
}
梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/7922.html
欢迎加入梓喵出没博客交流群:313732000

我来吐槽

*

*