> 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` 组件时，你必须提供以下内容：

* `area`：修改器区域的大小
* `模式`：在此区域中要强制使用哪种摄像机模式，来自 `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 模型包含一个 `camera` 节点作为其内容的一部分，那么它不能被 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/player-avatar.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` 组件的实体影响。该 Transform 的旋转会受到 `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` 地块相匹配。每边 N 个地块的最大高度约为 `log2(N+1) * 20` 米，因此一个 4x4 地块的场景将使用 `Vector3.create(64, 80, 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 // 每像素的度数
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-modifier-areas`](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 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/camera.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.
