> 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`时，所有化身都会激活触发区域。要判断触发它的化身是否为本地玩家，将 result 中的实体与 `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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
