For the complete documentation index, see llms.txt. This page is also available as Markdown.

基于系统的事件

了解如何处理场景中的用户点击。

如果你的场景中有多个相似实体,而且它们都使用相同逻辑来激活,你可以编写一个系统来遍历它们所有,并只描述一次这种行为。这也是性能最高,而且更 数据导向 的方法。

你也可以使用一个系统来检测 全局输入事件,这样无论玩家光标瞄准哪里,只要按下某个键,场景就会做出反应。

如果你只想要做的是点击或按下单个实体上的按钮来激活它,最简单的方法是使用 注册回调 的方法。

。要设置更具体的自定义逻辑,你可能需要直接处理原始数据,并使用 高级 的方法。

要使实体可交互,它必须具有 碰撞体。参见 障碍物 以了解更多细节。这也适用于接近点击事件。

使用系统

通过在输入 inputSystem 命名空间中每个 tick 运行其中一个辅助函数来检查按钮事件 系统.

例如,以下系统使用 inputSystem.isTriggered() 函数来检查指针是否被点击。每个 tick 它都会检查按钮是否被按下。如果 inputSystem.isTriggered() 返回 true,系统就会响应并运行一些自定义逻辑。

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
		// 响应按钮按下的逻辑
	}
})

以下辅助函数可在 inputSystem 命名空间中使用,并且同样可以在每个 tick 中调用:

  • inputSystem.isTriggered:如果自上一个 tick 以来发生了某个输入动作,则返回 true。

  • inputSystem.isPressed:如果某个输入当前正被按住,则返回 true。只要按钮再次松开之前,它会在每个 tick 都返回 true。

  • inputSystem.getInputCommand:返回一个包含输入动作数据的对象。

更多细节请参见下面的各节。

在处理实体上的按钮事件时,一定要给玩家反馈,让玩家知道该实体可以交互。如果你添加一个 PointerEvents 组件到实体上,玩家在将光标悬停在该实体上时会看到一个提示。参见 显示反馈 了解如何为可交互实体添加悬停提示。

全局输入事件

使用 inputSystem.isTriggered 来检测 SDK 跟踪的任意输入上的按下和松开事件。

上面的示例会检查按钮是否被按下,而不考虑指针位于何处,或者路径中可能有哪些实体。

inputSystem.isTriggered() 返回 true 只有当所指示的按钮在游戏循环的当前 tick 中被按下时才会返回 true。如果按钮没有被按下,或者它已经在之前的 tick 中被按下,则返回 false.

该 inputSystem.isTriggered 函数需要以下必填参数:

  • InputAction:要监听哪个输入,取值来自 InputAction 枚举。参见 指针按钮 以查看支持的选项。

  • PointerEventType:要监听哪种类型的事件,取值来自 PointerEventType 枚举。参见 指针事件类型 以查看支持的选项。

激活一个实体

要在指向特定实体时检测按钮事件,请向 inputSystem.isTriggered 添加第三个可选参数,以指定要检查的实体。

上面的示例会在每个 tick 检查是否有一个硬编码的实体被指针按钮(左键鼠标)按下。

该 inputSystem.isTriggered 函数接受以下参数:

  • InputAction:要监听哪个输入,取值来自 InputAction 枚举。参见 指针按钮 以查看支持的选项。

  • PointerEventType:要监听哪种类型的事件,取值来自 PointerEventType 枚举。参见 指针事件类型 以查看支持的选项。

  • Entity (可选):要检查哪些实体上发生这些事件。如果不提供值,它将检查该按钮的全局按下情况,而不考虑玩家光标指向哪里。

请注意,在这个示例中我们还向要交互的实体添加了一个 PointerEvents 组件。如果没有这个组件,实体将不会被 inputSystem的任何函数检测到。参见 显示反馈 了解更多关于该 PointerEvents 组件。

如果有多个实体可以以相同方式与玩家交互,考虑使用 inputSystem.getInputCommand。这个命令会返回关于一次全局点击命令的信息,包括实体 ID,你可以用它来执行一个能同时处理所有实体的单一函数。

参见 来自输入动作的数据 以获取更多信息。此方法还能为你提供关于指针事件命中的更详细数据。

输入按钮抬起

你也可以用类似的方式,通过使用 PointerEventType.PET_UP.

检查按住的按钮

通过使用 inputSystem.isPressed() 来检查某个按钮当前是否正被按下。

inputSystem.isPressed() 返回 true 如果按钮当前正被按住,无论按钮是什么时候被按下的,也无论玩家光标指向哪里。否则返回 false.

该 inputSystem.isPressed 函数只需要一个参数:

  • InputAction:要监听哪个输入,取值来自 InputAction 枚举。参见 指针按钮 以查看支持的选项。

处理多个实体

如果你的场景中有多个以相同方式受指针事件影响的实体,那么编写一个遍历它们所有的系统是合理的。

这个示例使用了一个 组件查询 来遍历所有带有 PointerEvents 组件的实体。然后它使用 inputSystem.isTriggered检查这些实体,逐个遍历。如果在其中任何一个实体上检测到输入动作,它就会执行自定义逻辑。

与其遍历 所有 带有 PointerEvents 组件的实体并放在一个系统中,你也许希望编写不同的系统来处理应以不同方式表现的实体。推荐的方法是用特定的 自定义组件标记不同类型的实体,并在独立的系统中遍历它们。

这个示例有一个系统来遍历所有具有名为 IsDoor 的自定义组件的实体,还有另一个系统遍历所有具有名为 isGem的自定义组件的实体。在这两个系统中,它都会检查每个匹配的实体,看看它们是否使用指针按钮被激活。

这样组织场景代码的方式非常 数据导向 ,而且应能非常高效地使用内存资源。

## 一个实体上的多个按钮

使用诸如 pointerEventsSystem.onPointerDown组件时,每个实体都只能有一种事件类型。你不能注册两个不同的按钮事件。使用基于系统的事件时则没有这个限制。例如,这里有一个实体,玩家既可以按 E 也可以按 F 与之交互,而且分别触发不同的功能。

显示反馈

要在指向实体时显示 UI 提示,请使用实体的 PointerEvents 组件。

每当玩家的光标指向该实体中的碰撞体时,UI 就会显示一个悬停提示,以表明该实体可以交互。关于你可以配置的内容,请参见下面各节。

该 PointerEvents 组件至少需要一个指针事件定义。每个指针事件定义可以配置以下内容:

  • eventType:要监听哪种类型的事件,取值来自 PointerEventType 枚举。参见 指针事件类型 以查看支持的选项。

  • eventInfo:一个可以包含以下字段的对象:

    • 按钮连接您的钱包 (必需):要监听哪个输入,取值来自 InputAction 枚举。参见 指针按钮 以查看支持的选项。

    • hoverText (可选):在悬停反馈提示中显示的字符串内容。默认值为“交互”。

    • showFeedback (可选):如果为 false,则会同时隐藏该实体的悬停提示和边缘高亮。 true 。

    • showHighlight (可选):如果为 true,当玩家将光标悬停在实体上时,会看到边缘高亮。 true 默认值。仅当 showFeedback 为 true.

    • maxDistance (可选):玩家的 化身 可以距离实体多远仍然能与之交互,单位为米。默认值为 10 米。参见 最大距离.

    • maxCameraDistance (可选):该 活动摄像机 可以距离实体多远仍然能与之交互,单位为米。默认未设置。参见 最大距离.

    • 优先级 (可选):当多个实体重叠时,哪个实体胜出。数值越高优先级越高。 0 。

单个 PointerEvents 组件可以包含多个指针事件定义,这些定义可以检测不同按钮的不同事件。每个实体只能有一个 一个 PointerEvents 组件,但该组件的 pointerEvents 数组中可以包含多个对象,每个对象对应一个要响应的事件。

玩家会看到多个标签,每个指针事件一个,这些标签以放射状显示在光标周围。

下面的示例将使用 PointerEvents 来显示悬停提示,并结合一个真正用自定义逻辑处理玩家动作的系统。

悬停反馈

当玩家将光标悬停在带有一个 PointerEvents 组件的物品上时,他们会看到:

  • 实体上的边缘高亮

  • 光标附近的一个悬停提示,带有他们需要按下的按钮图标,以及显示“Interact”的字符串。

这些元素都可以切换开关并自定义。

UI 上的悬停反馈会根据你在 按钮连接您的钱包 字段中选择的输入而显示不同的图标。在 PC 上,它会显示一个 E 用于 InputAction.IA_PRIMARY,一个 F 用于 用于InputAction.IA_SECONDARY 的鼠标,以及一个鼠标用于.

通过修改 hoverText 值来更改字符串。保持此字符串简短,以便快速阅读,并且不会对屏幕造成太大干扰。

在上面的示例中,指针事件包含了一个 hoverText的值。该字段定义了当玩家指向实体时要在 UI 中显示的字符串。默认情况下,这个字符串写的是 交互.

💡 提示:该 hoverText 字符串应该描述交互时发生的动作。例如 打开, 激活, 拿取, 选择。这些字符串应尽可能简短,以免过多分散玩家注意力。

如果实体上有多个指针事件,那么每个事件的悬停提示都会以放射状显示在光标周围。

该 hoverText 某个 .UP 指针事件只会在玩家已经按住对应按键并指向实体时显示。

如果一个实体同时具有一个 DOWN 指针事件和一个 UP 事件时, DOWN 动作的提示会在按钮未被按下时显示。提示会切换为 UP 事件的提示,只有当按钮被按下并持续按住时才会显示。

要隐藏悬停提示但保留边缘高亮,请将 hoverText 的值设为“”。

要隐藏边缘高亮但保留悬停提示,请设置 showHighlight 为 false.

要同时隐藏悬停提示和边缘高亮,请设置 showFeedback 为 false。这样做时,光标不会显示任何图标、文本或边缘高亮。你也可以直接移除该 PointerEvents 组件。

最大距离

有些实体可以故意只在近距离内可交互。如果玩家离实体太远,悬停提示就不会显示在光标旁边。

默认情况下,只有当玩家的 化身 位于 10 米 之内时,实体才可点击。你可以通过设置指针事件的 maxDistance 属性来更改该范围。

上面的示例将悬停提示的最大距离设置为 6 米。确保处理输入动作的逻辑也遵循相同规则。参见 来自输入动作的数据 了解如何获取输入动作的距离。

maxDistance 是从玩家的 化身测量的,因此在第一人称和第三人称中行为相同。

要按 活动摄像机 与实体之间的距离来限制交互,请改用 maxCameraDistance。同时设置这两者意味着任一检查通过就足够了。参见 距离限制 了解完整规则集。

高级自定义提示

该 PointerEvents 组件会在玩家光标开始悬停在实体上时轻松添加 UI 提示。提示的行为与玩家在其他 Decentraland 场景中习惯看到的内容保持一致,这通常是件好事。不过,在某些情况下,你可能希望用自定义方式来表明某物可交互。例如,当玩家开始悬停在实体上时,你可以播放一个微妙的声音。你也可以在悬停期间为实体显示发光高亮,并在不再悬停时隐藏它。它也可以用于特定的游戏机制。

使用 inputSystem.isTriggered() 函数与 PointerEventType.PET_HOVER_ENTER 和 PointerEventType.PET_HOVER_LEAVE 事件一起使用,以便在玩家光标开始指向实体的碰撞体时以及当光标停止指向它时执行自定义行为。

下面的示例会把实体放大到 1.5 当光标开始指向它们的碰撞体时,并在光标离开它们时将其恢复为 1 的大小。

接近事件

使用 PET_DOWN 在一个使用 InteractionType.PROXIMITY的实体上,即可无论光标瞄准哪里都检查接近按钮按下。将 interactionType 字段设置在指针事件定义中,位于 eventInfo旁边,以将该事件标记为基于接近。

参见 近距离事件 以了解更多细节,包括可用的辅助函数。

使用诸如 pointerEventsSystem.onProximityDown之类的辅助函数时,一个实体可以同时拥有一个光标处理器和一个接近处理器,而且两个回调都会运行。它不能做的是为同一个处理器注册两个不同的按钮。基于系统的事件没有这些限制:你为每种行为定义一条条目。例如,这里有一个实体,既可以通过光标指向并按 E 来交互,也可以通过走近它并按 E 来交互,而无需用光标指着它。

你也可以随时使用 inputSystem.isTriggered() 配合 PET_PROXIMITY_ENTER 和 PET_PROXIMITY_LEAVE 事件类型,用于在玩家进入或离开实体的接近范围时触发反应。这对于显示接近激活实体的额外反馈很有用,例如播放声音或动画。

要实现这一点,实体必须有一个 PointerEvents 组件,并定义相应的接近事件类型。

来自输入动作的数据

获取来自输入动作的数据,例如按下的按钮、被击中的实体、射线的方向和长度等。参见(查看文档)以了解所有可用数据的说明。

要获取此数据,请使用 inputSystem.getInputCommand。此函数会返回包含输入事件数据的完整数据结构。

如果没有与查询匹配的输入动作,那么 inputSystem.getInputCommand 返回 null。请确保在逻辑中处理这种情况。

最大点击距离

要强制限制最大距离,使实体只能在近距离被点击,请获取 hit.length 事件数据的属性。

模型中的不同网格

通常, .glTF 3D 模型由多个网格组成,而每个网格都有各自的内部名称。所有按钮事件都包含被点击的是哪个具体网格的信息,因此你可以利用此信息在不同情况下触发不同的点击行为。

要查看模型内部网格的命名,你必须使用一个编辑工具打开该 3D 模型,例如 Blender 。



💡 提示:你也可以通过记录日志并从控制台读取来了解被点击网格的名称。

你可以访问 meshName 属性作为 命中 对象的一部分,该对象由点击事件返回。

在下面的示例中,我们有一个房屋模型,其中包含一个名为 firePlace的网格。我们只想在对应网格被点击时打开壁炉。

最后更新于