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

7.4 KiB
Raw Blame History

3D 相机控制器(CameraController)

脚本入口: eve.CameraController()

在 Camera3D 之上提供可复用的视角行为:跟随、环绕、俯视、第一人称与过场。 模块还提供优先级 Camera Rig、遮挡修正、构图、Impulse Modifier,以及可发送 Event 的 Camera Timeline。Camera3D 本身只描述“看哪里”;本模块负责“怎么移动”。

基本用法

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:

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 的基础参数。

动作时间线中的 presentation:camera 可直接驱动同一套真实 Impulse。先调用 setActionCuesEnabled(true) 显式把控制器注册为当前动作相机;销毁控制器会自动注销,也可传 false 提前断开。payload 至少包含 LogicalId 格式的 cue,并可设置 positionAmplitude、 rotationAmplitude、fovAmplitude、durationSeconds 和确定性 seed。未注册控制器时运行时返回 可观测的 NotFound,不会静默吞掉镜头事件。

ctrl.setActionCuesEnabled(true);
// presentation:camera payload 示例:
// { cue="combat:heavy-impact", positionAmplitude=0.12,
//   rotationAmplitude=2.5, fovAmplitude=3.0, durationSeconds=0.3, seed=47 }

Timeline 与 Event

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()。
  • Action Cue:setActionCuesEnabled(enabled) / getActionCuesEnabled()。
  • 跟随目标: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。