> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/trigger-areas.md).

# 触发区域

了解如何在你的场景中使用触发区域

触发区域允许你对玩家进入或离开某个区域，或任何其他实体进入或离开某个区域的事件做出反应。这是创建交互式场景的基础工具。你可以将它们用于诸如：当玩家靠近时打开门，或者当球进入球门时得分之类的功能。

## 使用触发区域

要使用触发区域，你需要添加一个 `TriggerArea` 组件到某个实体，然后使用 `triggerAreaEventsSystem` 来对这些事件作出反应。

```ts
import { engine, Transform, TriggerArea, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

// 创建实体
const triggerEntity = engine.addEntity()

// 设置 Transform
Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8)
  })

// 触发区域
TriggerArea.setBox(triggerEntity)

// 触发区域被激活时的事件
triggerAreaEventsSystem.onTriggerEnter(triggerEntity, function(result) {
  if (result.trigger?.entity !== engine.PlayerEntity) return;
  console.log('玩家进入了触发区域！')
})
```

默认情况下， `TriggerArea` 组件响应 *任何* 玩家走入该区域的事件。上面的代码添加了 `if (result.trigger?.entity !== engine.PlayerEntity) return` 用于检查触发事件的实体是否是当前玩家，而不是别人的头像

## 触发区域形状

触发区域可以是盒体或球体。

```ts
import { engine, Transform, TriggerArea } from '@dcl/sdk/ecs'

// 盒体
TriggerArea.setBox(triggerEntity)

// 球体
TriggerArea.setSphere(triggerEntity)
```

{% hint style="info" %}
**💡 提示**: 球体是引擎最容易计算的形状，因为它只需检查到球体中心的距离。如果不确定，就使用球体。
{% endhint %}

要改变触发区域的大小，你可以使用 `缩放` 属性从 `Transform` 组件到持有该 `TriggerArea`.

```ts
import { engine, Transform, TriggerArea } from '@dcl/sdk/ecs'

const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity)

Transform.create(triggerEntity, {
  scale: Vector3.create(4, 2, 4),
})
```

### 调试

要调试你的场景并查看触发区域覆盖的范围，你可以添加一个 `MeshRenderer` 组件到带有触发区域的实体上，并将形状设置为你想要调试的形状。默认网格的尺寸将与触发区域的尺寸一致。

```ts
import { engine, Transform, TriggerArea } from '@dcl/sdk/ecs'

const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity)

MeshRenderer.setBox(triggerEntity)

Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})
```

## 触发区域事件

你可以使用 `triggerAreaEventsSystem` 来对触发区域的不同事件作出反应：

* `onTriggerEnter`: 当某个实体进入触发区域时触发。
* `onTriggerExit`: 当某个实体离开触发区域时触发。
* `onTriggerStay`: 当某个实体处于触发区域中时，每帧触发。

```ts
import { engine, Transform, TriggerArea, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity)

// 进入时
triggerAreaEventsSystem.onTriggerEnter(triggerEntity, function(result) {
  console.log('玩家进入了触发区域！')
})

// 离开时
triggerAreaEventsSystem.onTriggerExit(triggerEntity, function(result) {
  console.log('玩家离开了触发区域！')
})

// 停留时
triggerAreaEventsSystem.onTriggerStay(triggerEntity, function(result) {
  console.log('玩家在触发区域中！')
})
```

## 触发事件响应

当触发区域事件被触发时，你可以使用 `result` 参数来获取关于被触发的实体以及触发该事件的实体的信息。

以下属性可在 `result` 参数中使用：

* `triggeredEntity`: 被触发实体的 ID（这是拥有该触发区域的实体）
* `triggeredEntityPosition`: 被触发实体的位置
* `triggeredEntityRotation`: 被触发实体的旋转
* `eventType`: 触发事件的类型（ENTER、EXIT、STAY）
* `时间戳`: 触发事件的时间戳
* `触发器`: 一个包含以下字段的对象：
  * `实体`: 触发该触发器的实体 ID（进入触发区域的实体）
  * `layers`: 触发该触发器的实体的碰撞层
  * `位置`: 触发该触发器的实体的位置
  * `旋转`: 触发该触发器的实体的旋转
  * `缩放`: 触发该触发器的实体的缩放

{% hint style="warning" %}
**常见混淆**: 尽管名字如此， `result.triggeredEntity` 不会 **不是** 指的是触发了事件的实体。这两个字段很容易混淆：

* `result.trigger?.entity`: 进入触发区域的实体。通常你想检查的就是这个，例如识别是哪位玩家或哪个对象进入了区域。
* `result.triggeredEntity`: 拥有该 `TriggerArea` 组件的实体（触发区域本身，而不是进入它的实体）。

使用 `result.trigger?.entity` 当你需要识别进入的实体时。
{% endhint %}

```ts
import { engine, Transform, TriggerArea, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

// 带有触发区域的实体
const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity)

Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})

// 进入时
triggerAreaEventsSystem.onTriggerEnter(triggerEntity, function(result) {
  console.log('有一个实体进入了触发区域！', result.triggeredEntity)
  console.log('被触发实体的位置：', result.triggeredEntityPosition)
  console.log('被触发实体的旋转：', result.triggeredEntityRotation)
  console.log('事件类型：', result.eventType)
  console.log('时间戳：', result.timestamp)
  console.log('触发器实体：', result.trigger.entity)
  console.log('触发器层：', result.trigger.layers)
  console.log('触发器位置：', result.trigger.position)
  console.log('触发器旋转：', result.trigger.rotation)
  console.log('触发器缩放：', result.trigger.scale)
})
```

## 检测进入区域的玩家

触发区域最常见的用途是对玩家走入或走出作出反应。两个碰撞层可以检测头像，而使用哪一个取决于场景应对谁作出反应：

* `ColliderLayer.CL_MAIN_PLAYER`: 检测 **仅本地机器上使用的玩家**。当响应只针对该玩家本人时使用，例如传送他们、为他们播放声音，或追踪他们在任务中的进度。这在性能方面也是最便宜的选择。
* `ColliderLayer.CL_PLAYER`: 检测 **所有头像**，包括本地玩家以及场景中渲染的任何其他玩家。当任何人走入都很重要时使用，例如有人靠近时门打开，或者统计房间里有多少人。如果未指定，这是默认层。

以下示例仅对本地玩家作出反应：

```ts
import { engine, Transform, TriggerArea, ColliderLayer, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

// 创建实体
const triggerEntity = engine.addEntity()

// 设置 Transform
Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})

// 只检测本地玩家的触发区域
TriggerArea.setBox(triggerEntity, ColliderLayer.CL_MAIN_PLAYER)

// 触发区域被激活时的事件
triggerAreaEventsSystem.onTriggerEnter(triggerEntity, function (result) {
  console.log('你进入了触发区域！')
})
```

当使用 `CL_PLAYER`时，所有头像都会激活该触发区域。要判断触发它的头像是否是本地玩家，请将结果中的实体与 `engine.PlayerEntity`:

```ts
import { engine, Transform, TriggerArea, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

// 创建实体
const triggerEntity = engine.addEntity()

// 设置 Transform
Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})

// 使用默认的 CL_PLAYER 层的触发区域
TriggerArea.setBox(triggerEntity)

// 触发区域被激活时的事件
triggerAreaEventsSystem.onTriggerEnter(triggerEntity, function (result) {
  if (result.trigger?.entity === engine.PlayerEntity) {
    console.log('你进入了触发区域！')
  } else {
    console.log('另一位玩家进入了触发区域！')
  }
})
```

在大多数情况下，与其尝试检测所有玩家，理想做法是只检测当前玩家（通过 `CL_MAIN_PLAYER`）然后在所有玩家之间同步这个触发器的效果。例如，一个滑动门只会为你的头像打开，但随后该门的打开状态会共享给所有其他玩家。

{% hint style="info" %}
**💡 提示**: 其掩码仅包含头像层（`CL_PLAYER`, `CL_MAIN_PLAYER`，或两者皆有）的触发区域已优化：引擎会将它们放在仅限头像的物理层上，因此除了头像以外的任何重叠都会在到达场景代码之前被物理引擎丢弃。一个掩码恰好等于 `CL_MAIN_PLAYER` 的触发区域会得到进一步优化：它会在到达处理程序之前，对任何与非本地玩家碰撞体的重叠进行短路处理，因此只检测本地玩家几乎是零成本的。
{% endhint %}

## 触发区域层

使用 `TriggerArea` 组件可选的第二个参数来设置将激活触发区域的层。默认情况下，触发区域仅由层 `ColliderLayer.CL_PLAYER`，见 [检测进入区域的玩家](#detect-players-entering-an-area).

激活。你可以通过将其作为 `TriggerArea` 组件。

```ts
import { engine, Transform, TriggerArea, MeshCollider, ColliderLayer, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

// 触发区域
const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity, ColliderLayer.CL_CUSTOM1)

Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})

// 将激活触发区域的实体
const movingEntity = engine.addEntity()

Transform.create(movingEntity, {
  position: Vector3.create(8, 0, 8),
})

MeshCollider.setBox(movingEntity, ColliderLayer.CL_CUSTOM1)
```

可用值与 `MeshCollider` 组件遍历所有玩家。参见 [碰撞层](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/colliders.md#Collision-layers) 了解更多详情。

* `ColliderLayer.CL_PLAYER`: 任何头像（本地 + 远程）
* `ColliderLayer.CL_MAIN_PLAYER`: 仅本地玩家
* `ColliderLayer.CL_PHYSICS`
* `ColliderLayer.CL_POINTER`
* `ColliderLayer.CL_CUSTOM1` 到 `CL_CUSTOM8`
* `ColliderLayer.CL_NONE`

{% hint style="info" %}
**💡 提示**: 这些层 `CL_CUSTOM1` 到 `CL_CUSTOM8` 本身没有任何特殊行为，你可以将它们用于最适合你场景的任何用途。
{% endhint %}

你也可以设置一个触发区域，一次检测多个层。

```ts
import { engine, Transform, TriggerArea, ColliderLayer, triggerAreaEventsSystem } from '@dcl/sdk/ecs'

const triggerEntity = engine.addEntity()

TriggerArea.setBox(triggerEntity, ColliderLayer.CL_CUSTOM1 | ColliderLayer.CL_CUSTOM2)

Transform.create(triggerEntity, {
  position: Vector3.create(8, 0, 8),
})
```

当任何具有层 `CL_CUSTOM1` 或 `CL_CUSTOM2` 的实体进入触发区域时，这将激活该触发区域。

{% hint style="info" %}
**💡 提示**: 对于一个可正常工作的端到端示例，请查看 `TriggerArea` 中的 [`75,-9-trigger-areas`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/75,-9-trigger-areas) 测试场景，其中涵盖了 ENTER/EXIT 线协议以及 SDK 的逐 tick `onTriggerStay` 合成、旋转区域、在自定义碰撞层上的移动触发器，以及附着在下落实体上的区域。要了解碰撞层本身的行为，请参见 [`5,5-collider-layers`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/5,5-collider-layers).
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/trigger-areas.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
