CD Code Digest Hub /GTA V

演出、镜头与音频

10 分钟阅读 7 个章节 1 张图

返回总览。本篇分析剧情过场、游戏内同步场景、镜头和音频如何被玩法编排。它们复用原生资源系统,但具有不同的占用与退出协议;以下均为静态源码结论,未播放或验证实际素材。

1. 演出是玩法状态与表现资源的交接#

机制脚本控制内容原生系统承担内容
Cutscene请求、开始条件、角色绑定、跳过与完成后的玩法状态过场资源、场景角色和播放生命周期
同步场景场景原点、参与实体、动画、阶段及退出条件多实体动画相位与运动协调
脚本镜头创建、激活、插值、动画、回交游戏镜头相机实体、ScriptDirector、插值及最终镜头选择
对话与环境语音说话人、会话内容、触发条件、优先级和网络选项语音资源、音频实体及播放
Audio scene / 音乐事件启停情境、修改场景变量、发送事件混音场景和音乐系统的具体响应

任务脚本决定“现在应当演什么”,而不是在脚本中逐骨骼求解动画或混音。演出结束还必须恢复玩家控制、HUD、实体行为和后续任务条件;只处理播放完成,会留下比视觉错误更难追踪的玩法占用。

2. 非任务过场有独立预加载仲裁#

cutscene_control.sch 明确处理多个脚本同时请求预加载 off-mission cutscene 的情况,一次只许可一个请求。[S1] 请求 ID、请求类型、allowed ID 和 active ID 分开维护:取得加载许可与实际活跃是两件事。

UPDATE_CUTSCENE_CONTROL 首先检查当前玩法类型是否允许相关内容,或是否正在加载 Flow 的 intro;只在请求列表变化时扫描。优先级来自请求类型的枚举数值。代码找到一个比当前许可更高的候选就停止本轮搜索,不能将其描述为每帧对全部请求完成排序、选出绝对最高项。列表为空时同时清空 allowed 和 active。

这是对共享表现资源的调度,不是简单给每个任务加一个独立 REQUEST_CUTSCENE。常驻世界内容越多,这种集中仲裁越有价值。

3. 角色绑定包含资源、时序和所有权语义#

REGISTER_ENTITY_FOR_CUTSCENE 最终进入 CommandRegisterEnityWithCutScene。[S3,L634] 对已有实体,它检查模型、drawable 和 skeleton;随后验证模型 hash、scene handle,以及与场景开始相关的同帧约束。脚本若在角色登记和开始之间任意 WAIT,需要先核对接口约定,不能把它们当成完全无关的异步步骤。

登记 flags 还决定实体生命周期:已有脚本实体交给过场动画、交给过场动画并删除、由过场创建脚本实体、或不参与动画。因而“过场结束后任务角色消失”应同时检查登记选项和任务清理,不能只查动画资源。珠宝店抢劫的角色登记是具体内容侧入口。[S7]

cutscene_private.sch 则处理横跨脚本的边界:[S2]

  • 标为 cutscene-safe 期间,每帧隐藏 feed,避免常驻通知侵入演出。
  • 加载失败保护激活时,通过淡出降低世界呈现压力、协助 streaming。
  • 过场开始播放或被放弃后,都恢复淡入并清除 failsafe,防止取消路径留下黑屏。

这体现了“成功、跳过、取消、未加载完成”必须共同设计。场景脚本不能只依赖动画自然走到末尾。

4. 镜头是受脚本资源管理的原生对象#

CREATE_CAM 构造 CScriptResource_Camera,登记到当前脚本的 handler。[S4,L122] 源码特意指出相机引用使用真实 pool index,与其他资源的引用约定并不完全一致;不能假定所有 Native handle 都有相同内部表示。

RENDER_SCRIPT_CAMS 经 camInterface::GetScriptDirector() 启停脚本镜头。停止可作用于本线程,也有跨所有线程的强制路径;原生注释明确指出后者可能与并发脚本冲突。[S4,L72] 对商店、手机、任务和切人而言,局部结束自身镜头与全局抢夺镜头应严格区分。

SET_CAM_ACTIVE_WITH_INTERP 不仅调用插值,还检查源、目标相机及脚本控制资格,并处理“源镜头正从目标镜头插值过来”的循环引用情况。[S4,L1724] PLAY_CAM_ANIM 查询已加载的动画 clip,将场景位置与欧拉角转换成原点矩阵,再交给 ScriptDirector。动画名存在于脚本并不表示对应动画字典已经可用。

游戏内同步场景与完整 cutscene 不必使用同一控制器。player_timetable_scene.sc 中同步镜头的插回、同步 task 的混合退出,展示了“接回日常玩法”的具体处理。[S8] 内容作者既要设计入场动作,也要设计在场景中途恢复常态时的角色姿态和镜头过渡。

5. 音频把内容标识与播放机制分开#

script_audio.sch 将会话 root、可选行号和后缀组合后交给 GET_FILENAME_FOR_AUDIO_CONVERSATION,让脚本围绕对话标识组织内容。[S5] 两个 ambient speech wrapper 显式暴露 bSyncOverNetwork,而且默认值不同:普通指定 voice 的包装默认 FALSE,speech-and-clone 包装默认 TRUE。不能只看函数名相近就忽略网络行为。

长对话由 dialogue_handler 协调面对面、电话、multipart 会话和邀请,详见手机通讯与社交。会话能否启动、播放是否中断、任务等待什么结果,属于玩法协议;音频存在与否只是其中一个条件。

START_AUDIO_SCENE 经名称 hash 调用 g_ScriptAudioEntity.StartScene,原生断言还检查相应 MixerScene 是否存在;另有停止和设置变量接口。[S6,L3137] 这允许任务以“进入某种声音情境”组织表现,而把底层混音配置留给音频资源。音乐事件也是触发接口,不能据脚本中的事件名推导完整音乐编排内容。

6. 内容扩展与故障定位#

新增一段演出,可按以下顺序检查:准入与占用、资源请求、角色绑定、演出开始、正常结束与跳过、异常撤销、任务状态回交。镜头/音频的资源释放与玩法状态恢复应逐项对应。

加载卡住优先查许可和 streaming;角色错位查 scene handle、原点和骨架;演后无法操作查控制权、camera director 和全局占用;多人重复语音查同步选项、host/owner 和本地触发次数。后几项是由上述机制推导的排查方法,不代表已在本版本复现缺陷。

源码证据#

编号阅读位置
[S1]cutscene_control.sch L7 设计说明;L17 清理;L70 请求仲裁
[S2]cutscene_private.sch L19 cutscene-safe;L28 加载 failsafe
[S3]commands_cutscene.cpp L634 角色登记;L1229/1276 Native 注册
[S4]commands_camera.cpp L72 渲染控制;L122 资源登记;L1724 插值;L2046 动画
[S5]script_audio.sch L5 对话资源名;L26/30 网络语音包装
[S6]commands_audio.cpp L3137 Audio scene;L4243 音乐事件注册
[S7]jewelry_heist.sc L828 起过场角色登记
[S8]player_timetable_scene.sc L7925 同步镜头;L8048 同步 task 混合退出

[S1]: <../../../GTAV Source/script/dev_ng/singleplayer/include/private/cutscene_control.sch> [S2]: <../../../GTAV Source/script/dev_ng/singleplayer/include/private/cutscene_private.sch> [S3]: <../../../GTAV Source/src/dev_ng/game/script/commands_cutscene.cpp> [S4]: <../../../GTAV Source/src/dev_ng/game/script/commands_camera.cpp> [S5]: <../../../GTAV Source/script/dev_ng/shared/include/public/script_audio.sch> [S6]: <../../../GTAV Source/src/dev_ng/game/script/commands_audio.cpp> [S7]: <../../../GTAV Source/script/dev_ng/singleplayer/scripts/heists/heistJewelry/jewelry_heist.sc> [S8]: <../../../GTAV Source/script/dev_ng/singleplayer/scripts/playercontrol/player_timetable_scene.sc>