> 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/camera.md).

# 摄像机

了解如何控制玩家的摄像机

作为创作者，你可以完全控制玩家的摄像机。默认情况下，玩家在探索你的场景时可以自由选择第一人称或第三人称摄像机模式，但你也可以强制使用不同的摄像机模式。

虚拟摄像机可以是静态的，可以旋转以始终朝向玩家或其他实体，也可以附加到玩家或其他实体上，从而始终伴随其移动。

{% hint style="warning" %}
**📔 注意**：如需在默认的第一人称和第三人称摄像机之间切换，请参见 [摄像机修饰区域](#1st-and-3rd-person-camera-modes).
{% endhint %}

## 第一人称和第三人称摄像机模式

玩家通常可以通过按键盘上的 V 在第一人称和第三人称摄像机之间切换。使用 `CameraModeArea` 来强制让位于场景中特定区域内的所有玩家使用第一人称或第三人称摄像机模式。

```ts
const entity = engine.addEntity()

CameraModeArea.create(entity, {
	area: Vector3.create(4, 3, 4),
	mode: CameraType.CT_FIRST_PERSON,
})
```

如果玩家当前的摄像机模式与……的 `CameraModeArea`，他们将切换到该摄像机模式。屏幕上会显示一条提示，说明此更改是由于场景造成的。在区域内时，玩家无法更改其摄像机模式。当玩家离开 `CameraModeArea`时，其摄像机模式会恢复为进入之前的状态。

使用 `CameraModeArea` 在使用某种特定摄像机模式能显著提升体验的区域中。例如，当玩家需要点击小物体时，第一人称最合适；或者当玩家需要注意到场景在其头顶附加的某个实体时，第三人称会很有用。不要假设玩家知道如何切换摄像机模式，许多首次进入的玩家可能不知道自己有这个选项，也可能不记得该按哪个键。

{% hint style="warning" %}
**📔 注意**：摄像机修饰区域会受到 *位置* 和 *旋转* 其宿主实体的 Transform 组件，但不会受到 *缩放*.
{% endhint %}

{% hint style="warning" %}
**📔 注意**：如果多个摄像机修饰区域重叠，则由你的场景代码最后实例化的那个将优先于其他区域。
{% endhint %}

在创建一个 `CameraModeArea` 组件时，你必须提供以下内容：

* `区域`：修饰区域的大小
* `mode`：要在此区域强制使用哪种摄像机模式，来自 `CameraType` 枚举。

支持的摄像机模式有：

* `CameraType.CT_FIRST_PERSON`
* `CameraType.CT_THIRD_PERSON`

### 查询摄像机模式

你可以通过使用 `CameraMode` 组件来查询玩家的摄像机模式，位于 `engine.CameraEntity`.

```ts
const cameraMode = CameraMode.get(engine.CameraEntity)
if (cameraMode.mode === CameraType.CT_FIRST_PERSON) {
	console.log('玩家正在使用第一人称摄像机')
} else {
	console.log('玩家正在使用第三人称摄像机')
}
```

你也可以通过使用 `onChange` 在……上的函数 `CameraMode` 组件。

```ts
CameraMode.onChange(engine.CameraEntity, (cameraMode) => {
	if (!cameraMode) return
	console.log('玩家的摄像机模式已更改为', cameraMode.mode)
})
```

## 使用虚拟摄像机

要在你的场景中使用自定义摄像机行为，你需要两样东西：

* 创建一个虚拟摄像机：在场景中创建一个实体，并给它添加一个 `VirtualCamera`.
* 分配该虚拟摄像机：添加一个 `MainCamera` 组件到 [保留实体](/creator/content-creator-zh/chang-jing-sdk7/jia-gou/entities-components.md#reserved-entities) `engine.CameraEntity`，并引用带有 `VirtualCamera` 组件。

摄像机随后将附加到带有 `VirtualCamera` 组件的实体上。如果该实体移动或旋转，摄像机也会随之移动。

```ts
function main() {
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

在这个示例中，只要玩家留在场景边界内，摄像机就会始终处于场景中的固定位置。一旦玩家走出场景边界，默认的摄像机行为就会恢复。

### 视野

你可以通过设置 `fov` 属性（以度为单位）来覆盖虚拟摄像机的 Explorer 默认视野（FOV）。该覆盖仅在此虚拟摄像机处于活动状态时生效。省略 `fov` 时，将使用 Explorer 的默认值（通常为 60 度）。

```ts
const cinematicCamera = engine.addEntity()
Transform.create(cinematicCamera, {
	position: Vector3.create(8, 3, 2),
})
VirtualCamera.create(cinematicCamera, {
	fov: 45,
})
```

更窄的 FOV（较低值）会放大画面，适合过场动画或瞄准。更宽的 FOV（较高值）会显示更多场景内容，适合全景视图。

你的场景可以包含任意多个带有 `VirtualCamera`组件的实体，并随着玩家移动或执行某些动作，在多个虚拟摄像机之间动态切换。在任何给定时刻只会有一个虚拟摄像机处于活动状态，这是由 `MainCamera` 组件中的 `engine.CameraEntity`.

若要恢复为默认摄像机行为，请将值设置为 `undefined` 位于 `MainCamera.virtualCameraEntity`。此后玩家就可以自由在第一人称和第三人称摄像机之间切换。如果你希望玩家只使用这两种模式中的一种，可以使用 [摄像机修饰区域](#1st-and-3rd-person-camera-modes) 来强制使用其中一种。

{% hint style="warning" %}
**📔 注意**：只有在没有活动虚拟摄像机时，摄像机修饰区域才会对玩家生效。如果场景当前正在使用虚拟摄像机，而玩家进入了摄像机修饰区域，则不会发生任何事情。

如果一个 3D 模型包含一个 `摄像机` 节点作为其内容的一部分，SDK 无法使用它。你必须使用 SDK 将所有摄像机都创建为实体。
{% endhint %}

```ts
function main() {
	// 自定义虚拟摄像机
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})

	// 可点击方块
	const clickCube = engine.addEntity()
	Transform.create(clickCube, { position: Vector3.create(8, 0, 8) })
	MeshRenderer.setBox(clickCube)
	MeshCollider.setBox(clickCube)
	pointerEventsSystem.onPointerDown(
		{
			entity: clickCube,
			opts: { button: InputAction.IA_POINTER, hoverText: '重置摄像机' },
		},
		() => {
			// 将摄像机重置为默认行为
			const mainCamera = MainCamera.getMutable(engine.CameraEntity)
			mainCamera.virtualCameraEntity = undefined
		}
	)
}
```

{% hint style="info" %}
**💡 提示**：当摄像机转离头像时，通常也最好冻结头像的移动。这样玩家就不会盲目地撞上障碍物。参见 [输入修饰器](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/tou-xiang/locomotion.md#freeze-the-player)
{% endhint %}

要让玩家使用鼠标操控虚拟摄像机，请读取 `screenDelta` 组件的 `PrimaryPointerInfo` 组件，查看每一帧光标移动了多远，然后将该移动应用到摄像机的旋转上。即使光标被锁定，这也适用。参见 [鼠标移动](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/mouse-movement.md) 以查看完整的鼠标视角示例。

## 鸟瞰视角

你可以使用虚拟摄像机从俯视角度查看场景，这可以作为你的头像常规视角的一种有趣变体，并启用不同的游戏机制。

你应避免将摄像机放置为完全垂直向下的方向。相反，应始终让摄像机稍微倾斜，即使 1 度也足够。这是因为玩家方向控制是基于摄像机视角，而不是头像朝向。如果摄像机是完美的鸟瞰视图，那么就无法清晰定义哪个方向对应哪个方向。只需 1 度的微小倾斜就足以建立前进方向。

```ts
function main() {
	// 鸟瞰视角摄像机
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(8, 5, 8),
		rotation: Quaternion.fromEulerDegrees(91, 0, 0),
		// 注意旋转角度是 91º，而不是 90º
	})
	VirtualCamera.create(myCustomCamera, {})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

## 视野

你可以使用 `fov` 属性在虚拟摄像机上设置自定义视野（FOV）。该值以度为单位。若省略，则默认为 60。

```ts
VirtualCamera.create(myCustomCamera, {
	fov: 90,
})
```

更宽的 FOV（更高的值）会一次显示更多场景内容，并营造速度感，这对赛车游戏很有用。更窄的 FOV（较低值）会放大画面，适合瞄准或电影式镜头。

## 摄像机过渡

每当场景在虚拟摄像机之间，或在默认摄像机行为与虚拟摄像机之间切换时，玩家都会看到过渡效果。虚拟摄像机的位置、旋转以及其他任何参数都会在一段时间内平滑变化。

虚拟摄像机上的过渡设置决定了你如何将视角过渡 *到* 该摄像机，从场景中的任何其他摄像机（包括默认摄像机）切换过来。它们不会影响你如何从该摄像机过渡 *out* 离开。

```ts
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Time(6) },
})
```

{% hint style="info" %}
**💡 提示**：若想避免过渡并立即切换到某个摄像机，可将过渡时间或速度设为 0。
{% endhint %}

根据你的使用场景，你可能更倾向于设置过渡速度而不是持续时间：

* **固定时间**：你设置过渡的持续时间，摄像机将以完成该路径所需的速度移动，在这段时间内完成切换。
* **固定速度**：你设置希望虚拟摄像机在过渡期间移动的速度，持续时间将取决于距离。用于速度的值会被解释为 **米/秒**.

以下是这两种过渡模式的示例：

```ts
// 固定时长
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Time(6) },
})

// 固定速度
VirtualCamera.create(myCustomCamera1, {
	defaultTransition: { transitionMode: VirtualCamera.Transition.Speed(3) },
})
```

下面是一个包含两个虚拟摄像机及其之间过渡的完整示例：

```ts
function main() {
	// 自定义虚拟摄像机 1
	const myCustomCamera1 = engine.addEntity()
	Transform.create(myCustomCamera1, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera1, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(1) },
	})

	// 自定义虚拟摄像机 2
	const myCustomCamera2 = engine.addEntity()
	Transform.create(myCustomCamera2, {
		position: Vector3.create(1, 2, 1),
	})
	VirtualCamera.create(myCustomCamera2, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(3) },
	})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera1,
	})

	// 可点击方块
	const clickCube = engine.addEntity()
	Transform.create(clickCube, { position: Vector3.create(8, 0, 8) })
	MeshRenderer.setBox(clickCube)
	MeshCollider.setBox(clickCube)
	pointerEventsSystem.onPointerDown(
		{
			entity: clickCube,
			opts: { button: InputAction.IA_POINTER, hoverText: '重置摄像机' },
		},
		() => {
			// 将摄像机重置为默认行为
			const mainCamera = MainCamera.getMutable(engine.CameraEntity)
			mainCamera.virtualCameraEntity =
				mainCamera.virtualCameraEntity == myCustomCamera1
					? myCustomCamera2
					: myCustomCamera1
		}
	)
}
```

过渡总是沿直线移动，不考虑路径上的任何障碍物。你也可以改为手动创建过渡，使用另一个虚拟摄像机作为中介，这样你就能完全控制其移动。这个中介虚拟摄像机可以执行 [补间](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/move-entities.md#move-between-two-points) 从第一台摄像机的位置到第二台摄像机的位置的过渡，或者遵循一条更自定义的路径，以避开障碍物或进行电影式绕行。

## 摄像机跟随

你可以配置一个虚拟摄像机，使其始终面向玩家的方向，或者场景中的某个特定实体。摄像机的位置将保持静态，但它的旋转会改变，以始终让该实体居中。

这可以通过 `lookAtEntity` 属性在 `VirtualCamera` 组件来实现。要跟随玩家，请使用 [保留实体](/creator/content-creator-zh/chang-jing-sdk7/jia-gou/entities-components.md#reserved-entities) `engine.PlayerEntity`.

```ts
const myCustomCamera1 = engine.addEntity()
Transform.create(myCustomCamera1, {
	position: Vector3.create(1, 2, 1),
})
VirtualCamera.create(myCustomCamera1, {
	lookAtEntity: engine.PlayerEntity,
})
```

如果摄像机正在跟随某个实体，这只会改变旋转，不会改变摄像机的位置。

当摄像机旋转时，带有 `VirtualCamera` 组件的实体的 Transform 不会改变。不过，你可以从 `engine.CameraEntity`上的 Transform 中读取摄像机的旋转。该实体的旋转和位置将是绝对的，不会受到带有 `VirtualCamera` 组件的实体的影响。此变换的旋转会受到 `lookAtEntity` 行为的影响。

{% hint style="warning" %}
**📔 注意**：如果你将虚拟摄像机配置为带有一个 `lookAtEntity` ，而它引用的实体与持有虚拟摄像机的实体相同，或者 `engine.CameraEntity` 实体，那么最终行为将与根本未分配任何实体相同。
{% endhint %}

## 附加到玩家

虚拟摄像机的另一种用途是通过将虚拟摄像机附加到玩家实体，以自定义距离或角度跟随玩家。请注意，玩家不能自由改变摄像机的旋转，因此在这种情况下，摄像机的旋转将固定为虚拟摄像机的旋转。这对例如赛车游戏很有用，因为玩家预计始终向前看。

```ts
function main() {
	const myCustomCamera = engine.addEntity()
	Transform.create(myCustomCamera, {
		position: Vector3.create(0, 1, 5),
		parent: engine.PlayerEntity,
	})
	VirtualCamera.create(myCustomCamera, {
		defaultTransition: { transitionMode: VirtualCamera.Transition.Time(2) },
	})

	const mainCamera = MainCamera.createOrReplace(engine.CameraEntity, {
		virtualCameraEntity: myCustomCamera,
	})
}
```

## 摄像机与碰撞体

当玩家的摄像机以第三人称模式移动时，摄像机可能会被碰撞体阻挡，也可能不会，这取决于分配给实体的碰撞层。在设计场景时要注意这一点，你可能会希望阻止摄像机穿过墙壁或其他实体。

参见 [碰撞体](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/colliders.md#cameras-and-colliders) 以了解更多关于如何为你的场景配置碰撞体的细节。

## 旁观模式（观察者摄像机）

你可以构建一种旁观模式，将玩家从正常的头像移动切换到自由漫游或跟随玩家的摄像机。这对于竞技游戏中的观察者角色、现场活动中的导演摄像机或回放系统都很有用。

这种模式组合了多个 SDK 功能：

| 功能       | SDK API                                   | 用途                    |
| -------- | ----------------------------------------- | --------------------- |
| 自定义摄像机视图 | `VirtualCamera` + `MainCamera`            | 替换玩家的摄像机              |
| 冻结头像移动   | `InputModifier` (`disableAll: true`)      | 释放 WASD 来操控摄像机        |
| 跟踪场景中的玩家 | `onEnterScene` / `onLeaveScene`           | 构建跟随目标名单              |
| 摄像机控制    | `inputSystem.isPressed(InputAction.IA_*)` | WASD 控制俯仰/偏航，E/F 控制缩放 |
| 鼠标视角     | `PrimaryPointerInfo.screenDelta`          | 使用鼠标旋转摄像机             |

### 摄像机支架架构

使用一个 **双实体支架** 使偏航和俯仰保持独立：

```
rigRoot (实体)           -- 世界位置 + 偏航旋转
└── rigCamera (子级)      -- 俯仰旋转 + 环绕偏移
    └── VirtualCamera
```

`rigRoot` 保存偏航（左/右转），并朝向跟随目标或自由摄像机枢轴进行插值。 `rigCamera` 处理俯仰（上下倾斜）以及从根节点到环绕距离。将偏航和俯仰拆分到两个 Transform 上，可使欧拉角运算更直接。

### 启用和禁用

```ts
// 激活旁观模式
const rigRoot = engine.addEntity()
Transform.create(rigRoot, {
  position: Vector3.create(8, 8, 8),
  rotation: Quaternion.fromEulerDegrees(0, 0, 0),
})

const rigCamera = engine.addEntity()
Transform.create(rigCamera, { parent: rigRoot })
VirtualCamera.create(rigCamera, {})

MainCamera.createOrReplace(engine.CameraEntity, { virtualCameraEntity: rigCamera })
InputModifier.createOrReplace(engine.PlayerEntity, {
  mode: InputModifier.Mode.Standard({ disableAll: true }),
})
```

```ts
// 取消激活旁观模式
// 重要：在移除 VirtualCamera 实体之前，先清空 MainCamera。
// 如果你先移除该实体，引擎会继续绑定到一个失效实体
// 并且视角会掉到玩家的脚边。
const mainCamera = MainCamera.getMutableOrNull(engine.CameraEntity)
if (mainCamera) mainCamera.virtualCameraEntity = undefined

engine.removeEntity(rigCamera)
engine.removeEntity(rigRoot)

InputModifier.createOrReplace(engine.PlayerEntity, {
  mode: InputModifier.Mode.Standard({ disableAll: false }),
})
```

{% hint style="danger" %}
**警告：** 始终清空 `MainCamera.virtualCameraEntity` 在移除摄像机实体之前。先移除实体会使引擎指向一个失效引用，导致视图损坏。
{% endhint %}

### 摄像机边界

引擎会禁用 `VirtualCamera` 超出场景地块边界移动的实体。如果摄像机离开场景范围，它会静默停止工作。每帧都将摄像机位置限制在场景的轴对齐包围盒（AABB）内，并留出一点边距。

```ts
// 1x1 地块场景的示例边界（16m x 16m）
const BOUNDS_MIN = Vector3.create(0, 0, 0)
const BOUNDS_MAX = Vector3.create(16, 20, 16)
const BOUNDS_MARGIN = 0.5
```

对于更大的场景，请将边界设置为与你的 `scene.json` 地块相匹配。无论地块数量多少，场景高度上限都是 330 米。一个 4x4 地块的场景可以使用 `Vector3.create(64, 330, 64)`.

### 跟随玩家

使用 `onEnterScene` 和 `onLeaveScene` 以在场景中构建一个实时玩家名单。然后玩家可以使用按键在跟随目标之间轮换（例如， `IA_ACTION_3` 和 `IA_ACTION_4`）。当跟随某个玩家时，支架根节点会向被跟随玩家的 Transform 位置插值，子摄像机则会以可配置的距离环绕。

```ts
import { onEnterScene, onLeaveScene } from '@dcl/sdk/src/players'

const playerEntities = new Map<string, Entity>()
let playerIds: string[] = []

onEnterScene((player) => {
  if (!player) return
  playerIds.push(player.userId)
  playerEntities.set(player.userId, player.entity)
})

onLeaveScene((userId) => {
  if (!userId) return
  playerIds = playerIds.filter((id) => id !== userId)
  playerEntities.delete(userId)
})
```

要在每帧跟随玩家，请将支架根节点插值到其位置：

```ts
const followEntity = playerEntities.get(followTargetId)
if (followEntity) {
  const targetPos = Transform.get(followEntity).position
  const rootTransform = Transform.getMutable(rigRoot)
  rootTransform.position = Vector3.lerp(
    rootTransform.position,
    Vector3.add(targetPos, Vector3.create(0, 1, 0)),
    0.1
  )
}
```

参见 [玩家进入或离开场景](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/event-listeners.md#player-enters-or-leaves-scene) 更多关于 `onEnterScene` 和 `onLeaveScene`.

### 旁观时的鼠标视角

阅读 `PrimaryPointerInfo.screenDelta` 每帧来使用鼠标旋转摄像机。即使指针被锁定，这也有效。参见 [鼠标移动](/creator/content-creator-zh/chang-jing-sdk7/jiao-hu-xing/mouse-movement.md) 以查看完整的鼠标视角示例。

```ts
const MOUSE_SENSITIVITY = 0.15 // degrees per pixel
let yaw = 0
let pitch = 45

function spectateMouseLook() {
  const isLocked = PointerLock.getOrNull(engine.CameraEntity)?.isPointerLocked ?? false
  if (!isLocked) return

  const delta = PrimaryPointerInfo.getOrNull(engine.RootEntity)?.screenDelta
  if (!delta) return

  yaw = (yaw + delta.x * MOUSE_SENSITIVITY) % 360
  // delta.y 向下增大，因此鼠标向上为负值：将其加上会让摄像机向上倾斜；通过限制防止翻转
  pitch = Math.max(-25, Math.min(80, pitch + delta.y * MOUSE_SENSITIVITY))
}
```

{% hint style="warning" %}
**注意：** `screenDelta` 仅限桌面端。在移动端它始终返回 `0`。如果你的场景面向移动端，请设计基于触控的后备方案。
{% endhint %}

### 完整参考实现

该 [`33,20-旁观模式`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/33,20-spectate-mode) 测试场景中在 `src/spectate.ts`中包含一个自包含的旁观模块。它支持自由摄像机和跟随摄像机模式、WASD + 鼠标视角控制、玩家轮换、环绕距离缩放、边界限制，以及一个显示控制和当前跟随目标的屏幕 HUD。

要在你自己的项目中使用它：

1. 复制 `src/spectate.ts` 到你的场景中。
2. 更新 `PIVOT`, `BOUNDS_MIN`、以及 `BOUNDS_MAX` 在文件顶部，使其与你的场景地块相匹配。这是最常见的集成错误。
3. 连接 `toggleSpectate()` 到任何触发方式：可点击实体、UI 按钮或按键。

{% hint style="info" %}
**💡 提示**：如需摄像机控制的实际示例，请参见 [`2,22-虚拟摄像机`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/2,22-virtual-cameras) 测试场景，它会轮换多个 `VirtualCamera` 实体通过 `MainCamera` 包括 `lookAtEntity` 面向玩家的摄像机和一个缓动摄像机； [`32,20-virtual-camera-mouse-look`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/32,20-virtual-camera-mouse-look)，它在指针锁定时驱动鼠标视角摄像机； [`33,20-旁观模式`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/33,20-spectate-mode)，它实现了一个完整的旁观/观察者摄像机，包含跟随摄像机和自由摄像机模式；以及 [`9,99-修饰区域`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/9,99-modifier-areas)，它强制在一个体积内使用某种摄像机模式 `CameraModeArea`.
{% 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/camera.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.
