点击事件
了解如何处理场景中的用户点击。
Decentraland 场景可以检测用于控制玩家化身的所有按钮所触发的输入操作。这些包括指针点击、若干操作按钮,以及用于移动化身的按键。按钮事件可以来自桌面客户端上的鼠标和键盘、来自 移动应用中上的屏幕控件、来自 VR 控制器,或来自其他输入设备——SDK 会将这些都以相同方式解释。
你可以检测针对某个实体的输入操作。这涉及在玩家的光标指向该实体的碰撞体时按下一个按钮。你也可以检测 global 输入事件,这类事件是在任何时候激活输入时发生的,不考虑指针当前瞄准的位置。
根据使用场景的不同,有几种不同的方式来处理输入操作。
注册回调:为单个实体添加交互的最简单方式。写一条语句来设置回调函数和悬停反馈。
基于系统的:非常适合处理多个具有相似行为的实体。使用系统遍历相似实体,并查询每个实体的输入操作,用相同的逻辑处理它们。悬停反馈需要单独设置。这种方法也适用于处理全局输入操作。
高级:读取每个实体的原始响应数据,包括时间戳和输入事件历史记录。这对于定义自定义交互模式很有用。
在 Creator Hub 中使用 Scene Editor
处理实体上的点击事件最简单的方法是使用场景编辑器。使用无代码 点击时 或 在输入操作时 在项目上触发器,在点击时调用操作。或者使用 全局点击时, 全局主键时 或 全局次键时 触发器来响应全局按钮事件。参见 让任意项目变为智能项目.
简单示例
要检测实体上的点击,请使用 pointerEventsSystem.onPointerDown.
pointerEventsSystem.onPointerDown(
{
entity: myEntity,
opts: { button: InputAction.IA_PRIMARY, hoverText: '点击' },
},
function () {
console.log('已点击实体')
}
)参见 注册回调 以获取更多信息。
悬停反馈
让玩家知道某个实体可交互非常重要。否则,他们可能会完全错过你构建的体验。让玩家挨个点击每个对象,只期待其中一个有反应,这种体验并不好。
当你使用 注册回调 方法时,只要玩家将光标移到对象上方,就会显示两种反馈:
实体边缘会被高亮显示(仅在 Decentraland 2.0 桌面客户端上)。如果实体足够近,可以点击,高亮为绿色;如果实体太远,高亮为红色。
光标附近会出现一个带有 UI 文本的悬停提示,表明如果点击将会发生什么。
当使用 基于系统的 方法时,你可以通过添加一个 PointerEvents 组件到可点击实体上来达到相同效果。
实体高亮和悬停提示都可以通过这些方法和组件中的属性来禁用。
你也可以实现 高级自定义提示,例如你可以播放声音,让实体在被指向时变色、旋转或放大等。无论你做什么,都要确保它是一个清晰的提示标识。
障碍
按钮事件会发射射线,只与路径上订阅了指针事件碰撞层的第一个实体发生交互。只要实体处于其距离限制范围内,这一点就成立。如果实体同时为摄像机和化身定义了距离限制,那么两者中任意一个足够近就可以。
要让实体被指针事件的射线拦截,必须满足以下任一条件:
该模型必须包含 碰撞网格.
该
GltfContainer必须配置为使用 带碰撞遮罩的可见几何体.该实体必须有一个 MeshCollider 组件.
如果另一个实体的碰撞体挡在玩家想交互的实体前面,玩家就无法点击后面的实体,除非该实体没有碰撞体,或者这个碰撞体被配置为不响应指针事件碰撞层。
指针按钮
以下输入可由检测输入事件的任一方法来处理。
的鼠标,以及一个鼠标用于: 鼠标左键 在电脑上, 交互按钮 在移动端。InputAction.IA_PRIMARY: E 在电脑上的按键, E 按钮 在移动端。用于: F 在电脑上的按键, F 按钮 在移动端。InputAction.IA_ACTION_3: 1 在电脑上的按键, 1 按钮 在移动端。 在移动端上不易触及——不建议用于移动端交互。InputAction.IA_ACTION_4: 2 在电脑上的按键, 2 按钮 在移动端。 在移动端上不易触及——不建议用于移动端交互。InputAction.IA_ACTION_5: 3 在电脑上的按键, 3 按钮 在移动端。 在移动端上不易触及——不建议用于移动端交互。InputAction.IA_ACTION_6: 4 在电脑上的按键, 4 按钮 在移动端。 在移动端上不易触及——不建议用于移动端交互。InputAction.IA_JUMP: 空格 在电脑上的按键, 跳跃按钮 在移动端。InputAction.IA_FORWARD: W 在电脑上的按键。InputAction.IA_LEFT: 一个 在电脑上的按键。InputAction.IA_RIGHT: D 在电脑上的按键。InputAction.IA_BACKWARD: S 在电脑上的按键。InputAction.IA_WALK: 控制 在电脑上的按键。InputAction.IA_MODIFIER: Shift 在电脑上的按键。
每个 InputAction 被从键盘上的字面输入中抽象出来,这样它就可以根据设备映射到不同的输入。出于同样的原因,键盘上的所有按钮都不能用于跟踪按钮事件,只有用于移动和交互的按钮可以。这个有意的限制可确保内容能跨桌面端、 移动客户端以及未来的设备(如 VR 控制器和其他游戏控制器)兼容。
指针事件类型
每种输入都可以产生以下类型的指针事件。下面每一项都是 PointerEventType 枚举。
PET_DOWN:玩家在光标指向实体的碰撞体时按下某个特定按钮。PET_UP:玩家在光标指向实体的碰撞体时松开某个特定按钮。PET_HOVER_ENTER:玩家的光标开始指向实体的碰撞体。PET_HOVER_LEAVE:玩家的光标停止指向实体的碰撞体。PET_PROXIMITY_ENTER:玩家走进实体的接近范围,无论他们在看什么。PET_PROXIMITY_LEAVE:玩家离开实体的接近范围。
参见 近距离事件 了解如何使用基于接近距离的交互。
来自输入操作的数据
所有输入操作都包含事件数据,包括被激活的按钮以及当时指针指向的位置等信息。
可从任何输入事件中获得以下信息:
模拟:可选数字,仅出现在来自模拟输入(如摇杆)的事件中,用于存储输入的模拟值。按钮连接您的钱包:按下的是哪个按钮 ID。该数字对应于InputAction枚举,其中列出了所有可用按钮。state:指针事件类型,来自枚举PointerEventType. 0 指的是PointerEventType.PET_UP, 1 为PointerEventType.PET_DOWN, 2 为PointerEventType.PET_HOVER_ENTER, 3 为PointerEventType.PET_HOVER_LEAVE, 4 为PointerEventType.PET_PROXIMITY_ENTER, 5 为PointerEventType.PET_PROXIMITY_LEAVE时间戳:一个 Lamport 时间戳 用于标识每个按钮事件。注意:此时间戳并不是基于当前时间编号的。可以将其视为一个从 0 开始、每发生一个事件就加 1 的计数器。
命中:一个包含有关命中事件以下数据的对象:entityId:被射线命中的实体的 ID 数字。meshName: 字符串 ,包含被命中的 3D 模型中具体网格的内部名称。当一个 3D 模型由多个网格组成时,这很有用。globalOrigin: Vector3 用于表示射线起点的位置(相对于场景)方向: Vector3 与射线的方向向量一起,位于全局坐标中位置: Vector3 用于表示射线与命中实体相交的位置(相对于场景)length:射线从起点到命中实体发生位置的长度。normalHit: Vector3 带有一个归一化方向向量,用于描述世界空间中命中法线的角度。
根据你使用的输入操作处理方式,这些数据的访问方法不同。
使用 注册回调 方法时,传入回调函数的第一个参数包含整个数据结构。
使用 基于系统的 方法时,请使用 inputSystem.getInputCommand() 来获取这些数据。
使用 高级 方法中, PointerEventsResult 包含一个该实体最近所有指针事件的历史列表。
锁定或解锁光标
Decentraland 桌面客户端中的玩家可以用光标在两种不同的交互模式之间切换:
锁定光标:移动鼠标会改变摄像机,点击事件会发生在屏幕中央的准星处
解锁光标:光标可以独立于摄像机自由移动,玩家可以点击屏幕任意位置,与 3D 空间或 UI 进行交互
这些交互模式适用于不同类型的游戏机制,你可能希望让玩家根据你的场景需求采用其中一种。你也可能希望暂时确保玩家的光标处于解锁状态,以便他们与 UI 交互;这对不熟悉这一控制方式的新玩家尤其有帮助。
要更改玩家的光标状态,请使用 PointerLock 组件,作用于 engine.CameraEntity 实体,从玩家摄像机位置向前追踪一条射线。
你也可以通过读取 PointerLock 组件的状态来查询玩家的光标状态。
使用 .onChange 函数来响应指针状态的变化。下面的示例会强制光标始终处于解锁状态。
最后更新于