Version: Unity 6.0 (6000.0)
语言 : 中文
运行时 UI 事件系统和输入处理
运行时 UI 的性能注意事项

结合使用输入系统和事件系统与 UI 工具包的常见问题解答

本页面包含将事件系统和输入系统与__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
See in Glossary
工具包结合使用的常见问题。

  1. 如何知道鼠标是否位于运行时面板中的视觉元素上?
  2. 如何重新映射基本的 UI 操作?
  3. 使用方向导航时,如何更改下一个聚焦的元素?
  4. 能否禁用方向导航使用的 WASD 按键或提交操作使用的空格键?
  5. 如何在不使用鼠标点击任何位置的情况下开始输入键盘输入?

如何知道鼠标是否位于运行时面板中的视觉元素上?

方法有两种:

第一种方法

  1. 在场景中添加事件系统组件,添加方式与从 com.unity.uGUI 包创建基于游戏对象的 UI 内容相同。

  2. 使用 EventSystem.current.IsPointerOverGameObject 方法,如果指针位于 uGUI 或 UI 工具包中的 UI 内容上方,则返回 true

  3. 使用 EventSystem.current.RaycastAll 方法以查看鼠标下的视觉元素。

  4. 交叉的 UI 工具包面板在事件系统的环境中通过游戏对象表示:

    • 游戏对象的名称与相应的 PanelSettings 匹配。
    • 游戏对象的父项是包含当前事件系统组件的游戏对象。
    • 游戏对象有两个组件:PanelRaycasterPanelEventHandler。这两个组件都有一个 panel 属性,该属性返回其目标 IPanel

在指针下找到面板后,调用 panel.Pick 方法以查找指针位置处的视觉元素。

必须使用 RuntimePanelUtils.ScreenToPanel 方法将指针的屏幕坐标变换为面板坐标。

uGUI 的屏幕坐标系使用左下角原点,而 UI 工具包屏幕坐标从左上角表示。两个系统之间的转换需要使用 yTopLeft = Screen.height - yBottomLeft 镜像 Y 坐标,反之亦然。

第二种方法

  1. 每个不同的 PanelSettings 使用一个 UIDocument 中的 UIDocument.rootVisualElement 属性,用于获取指针下可能包含的所有运行时面板的列表,您可以收集这些面板
  2. 按深度顺序手动遍历面板,依次调用每个面板的 panel.Pick,直到找到返回视觉元素的面板。

如何重新映射基本的 UI 操作?

要重新映射基本 UI 操作,请执行以下操作:

  1. 在场景中添加事件系统组件,添加方式与从 com.unity.uGUI 包创建基于游戏对象的 UI 内容相同。
  2. 在检视面板窗口中,配置独立输入模块 (Stand alone Input Module)输入系统 UI 输入模块 (Input System UI Input Module) 字段来控制每个操作的输入映射。

注意:映射到 Tab 和 Shift+Tab 输入的操作无法重新映射,因为未通过事件系统输入模块公开。

使用方向导航时,如何更改下一个聚焦的元素?

可以将方向导航配置为具有默认目标以外的其他目标。

以下代码示例允许元素 A 分别在向上、向下、向左和向右导航时导航到元素 U、D、L、R:

A.RegisterCallback <NavigationMoveEvent>(e =>
{
    switch(e.direction)
    {
        case NavigationMoveEvent.Direction.Up: U.Focus(); break;
        case NavigationMoveEvent.Direction.Down: D.Focus(); break;
        case NavigationMoveEvent.Direction.Left: L.Focus(); break;
        case NavigationMoveEvent.Direction.Right: R.Focus(); break;
    }
    e.PreventDefault();
});

能否禁用方向导航使用的 WASD 按键或提交操作使用的空格键?

是的。可以使用检视面板窗口中 EventSystem 的 StandaloneInputModuleInputSystemUIInputModule 字段来控制每个操作的输入映射。但是,由于这些操作与 uGUI 输入共享,因此也会更改 uGUI 控件。

要在不影响 uGUI 控件的情况下重新映射 UI 工具包输入,请禁用 UI 工具包的运行时事件处理,并手动将所有事件发送到面板。为此,请在当前 EventSystem 的启动方法(例如场景组件的 Awake 方法)启动之前调用 EventSystem.SetUITookitEventSystemOverride(null, true, false);。有关此 uGUI 方法的更多信息,请参阅 SetUITookitEventSystemOverride

如何在不使用鼠标点击任何位置的情况下开始输入键盘输入?

在给定时间,例如首次加载游戏场景时,可能没有元素或面板获得焦点。在这种情况下,键盘导航不会从可预测的第一个元素开始。对于完全不使用鼠标的游戏,这可能是一个问题。

可以添加 C# 脚本,以便从一开始就实现可预测的导航行为,并将脚本附加到与您选择负责获取初始焦点的元素的 UIDocument 相同的游戏对象。

假设脚本命名为 FirstFocus,并且初始聚焦元素命名为 first-focused。在脚本的 Start() 方法中,添加一行以聚焦该元素,如下所示:

public class FirstFocus : MonoBehaviour
{
    void Start()
    {
        FocusFirstElement();
    }

    public void FocusFirstElement()
    {
        GetComponent<UIDocument>().rootVisualElement.
            Q<VisualElement>("first-focused").Focus();
    }
}

注意:如果禁用 UIDocument 的游戏对象,则会从头开始重新创建其所有底层层级视图。因此,必须在重新启用游戏对象后再次运行自定义 FocusFirstElement() 方法。

其他资源

运行时 UI 事件系统和输入处理
运行时 UI 的性能注意事项