Files
EVEngine/docs/usr/modules/camera.md
T

150 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 3D 相机控制器(CameraController)
**脚本入口:** `eve.CameraController()`
在 `Camera3D` 之上提供可复用的视角行为:跟随、环绕、俯视、第一人称与过场。
模块还提供优先级 Camera Rig、遮挡修正、构图、Impulse Modifier,以及可发送
`Event` 的 Camera Timeline。`Camera3D` 本身只描述“看哪里”;本模块负责“怎么移动”。
## 基本用法
```squirrel
cam <- eve.Camera3D();
cam.setEye(0.0, 3.0, 8.0);
cam.setTarget(0.0, 1.0, 0.0);
cam.setFov(50.0);
cam.setAmbient(0.3, 0.32, 0.34);
gfx.setDirectionalLight(-0.4, 0.9, 0.35, 1.9, 1.6, 1.3);
ctrl <- eve.CameraController();
ctrl.setCamera(cam);
ctrl.setMode("orbit");
ctrl.setTarget(0.0, 1.0, 0.0);
ctrl.setRadius(8.0);
ctrl.setOrbitSpeed(0.6);
ctrl.snap();
function eve_update(dt) { ctrl.update(dt); }
```
## Rig 与 Director
Rig 是一份可复用的相机参数快照,Director 会选中优先级最高的 enabled Rig:
```squirrel
ctrl.setMode("follow");
ctrl.setOffset(0.0, 2.8, 7.0);
ctrl.setFov(55.0);
ctrl.addRig("gameplay", "follow", 10);
ctrl.setMode("orbit");
ctrl.setRadius(5.0);
ctrl.setElevation(20.0);
ctrl.setFov(42.0);
ctrl.addRig("boss", "orbit", 30);
ctrl.setRigEnabled("boss", false); // gameplay 自动接管
ctrl.activateRig("boss", 0.6); // 显式平滑切换
ctrl.saveRigState("boss"); // 保存当前参数回 preset
```
`addRig(name, mode, priority)` 创建时保存当前的 target、offset、lookAhead、构图、
orbit/first-person 参数、FOV、平滑和限速。`removeRig` 删除,`getActiveRig` 返回当前
Rig。`setRigPriority` / `setRigEnabled` 可在游戏状态变化时驱动 Director。
## 构图、目标和遮挡
- `setTargetNode(nodeRef)` 直接跟随稳定的 `SceneNodeRef`;传 `null` 后可重新使用
`setTarget(x,y,z)`。Scene 的 transform 应先于 camera 更新。
- `setComposition(x,y)` 设置归一化横纵构图偏移;范围会限制在 `-0.9..0.9`。
- `setDeadZone(radius)` 让目标在世界空间死区内移动时不推动镜头。
- `setFov(degrees)` / `getFov()` 管理镜头 FOV,输入限制为 `1..179` 度。
- `addInput(yawDeltaDeg,pitchDeltaDeg,zoomDelta)` 接收与设备无关的输入增量,统一
驱动 orbit / first-person;调用方可从鼠标、手柄或触摸模块提供 delta。
- `setCollisionEnabled` 开启球形探针;`setCollisionRadius` 设置探针半径,
`setCollisionRecovery` 设置遮挡解除后的恢复阻尼。
- 若 Physics/Box3D 模块存在,探针会自动查询所有存活的 `World3D`,无需逐个注册;
`setCollisionMask(mask)` 过滤 category bits,`setCollisionIgnoredBody(id)` 排除玩家刚体,
`getCollisionBodyId()` 返回当前命中的动态刚体。Physics 不存在时 camera 仍可独立使用。
- `addCollisionBox(minX,minY,minZ,maxX,maxY,maxZ)` 注册静态遮挡体,
`clearCollisionBoxes` 清空;`isObstructed()` 查询当前状态。
碰撞缩进会立即发生,恢复采用阻尼,避免相机穿墙或解除遮挡时弹跳。
## Modifier / Impulse
`addImpulse(positionAmplitude, rotationAmplitude, duration, seed)` 叠加一个确定性、
随时间衰减的位置与旋转冲击,适合命中、爆炸和落地反馈;`clearImpulses()` 立即清除。
`addFovImpulse(degrees,duration)` 叠加冲刺/受击常用的 FOV 脉冲。多个 modifier
可以同时叠加,不会改变 Rig 的基础参数。
## Timeline 与 Event
```squirrel
local cameraEvents = eve.PlatformEvent();
ctrl.setEventSink(cameraEvents);
ctrl.clearTimeline();
ctrl.addTimelineCut(0.0, "gameplay", 0.0);
ctrl.addTimelineEvent(1.2, "camera.dialogue", "intro");
ctrl.addTimelineFloat(0.0, "fov", 48.0);
ctrl.addTimelineFloat(2.0, "fov", 36.0);
ctrl.addTimelineCut(2.0, "boss", 0.75);
ctrl.playTimeline(false);
// 既可从共享 Event 队列消费,也可直接从 controller 的 FIFO 队列逐个消费 marker。
local marker = ctrl.consumeTimelineEvent();
if (marker != "") print(marker + ": " + ctrl.getTimelineEventData() + "\n");
```
- `playTimeline(loop)` / `pauseTimeline()` / `stopTimeline()` 控制播放。
- `seekTimeline(time, fireEvents)` 定位;`getTimelineTime()` 和
`isTimelinePlaying()` 查询状态。
- `addTimelineCut(time, rigName, blendTime)` 添加切镜点。
- `addTimelineEvent(time, name, data)` 添加 marker。若设置了 `Event` sink,marker
同时进入全局事件队列;否则仍可通过 `consumeTimelineEvent()` 读取。单帧跨过多个
marker 时不会覆盖,可用 `getPendingTimelineEventCount()` 查询积压数。
- `addTimelineFloat(time, property, value)` 添加线性属性关键帧;property 支持 `fov`、
`radius`、`smooth`、`compositionX`、`compositionY`。
## Camera Asset 与调试快照
`serializeAsset()` 将全部 Rig、cut、marker 和 float track 输出为带 `version` 的 JSON;
`deserializeAsset(json)` 校验后替换当前配置。游戏可配合 Filesystem/Data 模块把字符串
保存为 `.camera.json`。`getRigCount()`、`getTimelineDuration()`、
`getPendingTimelineEventCount()`、`getCollisionBodyId()` 可供编辑器 inspector、测试和
运行时 HUD 生成轻量调试快照。
## 目标导向指南
### 第三人称跟随玩家
`setMode("follow")` + `setTarget(x, y, z)`(每帧更新为玩家坐标)+
`setOffset(0, 2.6, 6.0)` + `setSmooth(6.0)`;玩家高速移动时 `setLookAhead`
让镜头略微前探。
### 过场动画
`setMode("cinematic")` 前用 `addView("front", ...)` 等注册多个命名视角,
`playSequence(3.0)` 在视角间平滑切换,`stopSequence()` / `isPlaying()` 控制。
## API 快查
### `CameraController`
- 绑定:`setCamera(cam)` / `getCamera()`。
- 跟随目标:`setTarget(x,y,z)` / `setTargetNode(nodeRef)` / `getTargetX()` /
`getTargetY()` / `getTargetZ()`、`setOffset(x,y,z)`、`setLookAhead(x,y,z)`。
- 模式:`setMode("follow"|"orbit"|"topdown"|"firstperson"|"cinematic")` / `getMode()`。
- 环绕:`setRadius`、`setAzimuth`、`setElevation`、`setOrbitSpeed`、`setYaw`、`setPitch`。
- 平滑:`setSmooth(k)` 同时设置两路阻尼;也可用 `setPositionSmooth(k)` /
`setTargetSmooth(k)` 独立控制机位与朝向跟随,再配合 `setMaxSpeed(v)`、`snap()`。
- 过场(兼容 API):`addView(name, ex,ey,ez, tx,ty,tz)`、`switchTo(name, blendTime)`、
`playSequence(seconds)`、`stopSequence()`、`isPlaying()`。
- `update(dt)`:每帧驱动(放到 `eve_update`)。
## 生命周期
- `Camera3D` 由脚本创建时默认 active,也可用 `setActive` 控制是否被渲染器采用;
控制器只改其 eye/target,不负责渲染。
- 示例:[`examples/camera-controllers`](../../../examples/camera-controllers/main.nut)。