演示视频:Previze 虚拟制片预演系统功能演示
系统介绍:基于 UE5 的影视/舞台三维预演工具,覆盖场景搭建、灯光机位、动画时间轴到逐帧渲染的全流程;我独立完成了客户端主体开发、自研 Editor 插件,并设计了与云端资产系统的对接方案。
项目背景
在影视制作、舞台演出和虚拟拍摄场景中,导演、摄影和灯光团队往往需要在实拍前反复验证场景布局、灯光方案和机位调度。传统流程依赖多个软件切换,沟通成本高、试错代价大。
PreviewTool(虚拟预演系统) 是我从 2024 年起持续开发的 ToB 端产品:
- 预演系统(主体):面向导演、摄影、灯光师的实时三维预演工作台(本人独立设计与实现)
- Editor工具插件:Pak 资产的 Cook、打包与上传工具(本人独立设计与实现)
- Pak 资产管理后台:资产上传、分类与版本管理(需求与 API 契约由本人定义,CRUD 实现借助 AI 辅助开发)
项目目前处于可演示、可实际使用的阶段,已在内部预演流程中验证核心链路。
系统架构
技术栈
客户端开发(核心)
| 类别 | 技术 |
|---|---|
| 主语言 | C++(Gameplay / UI / 动画 / 渲染 / 资产同步) |
| UI 框架 | UMG + C++(UUserWidget + BindWidget) |
| 蓝图 | Sku Actor 资产逻辑、部分交互;核心系统以 C++ 为主 |
| 输入与编辑 | 继承 RuntimeTransformer 的 Gizmo 变换、拖放放置、多选 |
| 动画 | UTimelineComponent + UCurveFloat + 自研多轨道关键帧 |
| 渲染输出 | UTextureRenderTarget2D + IImageWrapper,Timer 驱动逐帧导出 |
| 程序化 | ProceduralMeshComponent(LED 幕墙 / 墙体生成) |
| 媒体 | MediaAssets(LED 屏本地视频播放) |
插件
| 插件 | 类型 | 用途 |
|---|---|---|
| CameraCapture(自研) | Runtime | 摄影机实时取景预览 (相关技术获得专利证书) |
| PakTools(自研) | Editor + Runtime | CreatePak:Cook / 打 Pak / 上传;PakLoader:运行时挂载与加载 |
| RuntimeTransformer | Runtime | 运行时 Gizmo 变换(基于商城插件二次修改) |
配套后台(非主攻,了解联调)
Django 4 + DRF + PostgreSQL + Redis + React 17 — 我负责 API 契约定义 与 UE 端同步实现,后台 CRUD 借助 AI 辅助搭建。
我负责的核心模块
1. 资产类型设计与场景编辑
所有场景对象继承自 ACPT_BaseSkuActor,实现 IFocusableObject 接口,统一处理选中高亮与属性暴露。通过 EActorType 枚举区分模型、灯光、摄影机、动画、环境、LED 舞台等类型。
主控制器 ABPT_TransformerPawn 继承 RuntimeTransformer 的 ATransformerPawn,负责:
- 视口输入、Gizmo 变换(移动 / 旋转 / 缩放)
- 拖放式资产放置、多选与克隆
- 创建并持有 UMG 根控件
UCPT_MainUI,与主界面双向联动
设计要点:Actor 根组件必须继承 UPrimitiveComponent,以支持 RuntimeTransformer 的组件级选取;属性面板通过 ConfigPropertys() 动态生成,避免为每种 Actor 硬编码 UI。
2. 动画时间轴系统
UCPT_AnimManager 管理 Actor 与 UCPT_AnimTrack 的一对多映射,支持:
- 多轨道关键帧编辑(位置 / 旋转 / 缩放)
- 播放、暂停、循环、逐帧跳转(J/K 快捷键)
- 时间轴长度、帧率、播放速率调节
FAnimTimelineData与项目 JSON 的双向序列化
动画播放通过 UTimelineComponent + UCurveFloat 驱动 UI 滑条,并与渲染模块共享同一套时间基准,保证「预览所见」与「渲染输出」一致。
3. 逐帧渲染管线
UCPT_RenderManager 实现与时间轴联动的离线帧序列导出:
|
|
渲染参数由 FRenderOptionData 定义:分辨率、帧率、画质、输出格式、起止时间等。这是预演方案汇报的核心输出能力。
4. Pak 资产云端同步(客户端侧)
这是我投入较多精力的模块,解决了「资产与程序分离、按需更新、离线可用」的需求。
核心类:
| 类 | 职责 |
|---|---|
FCPT_AssetManifestUtils |
加载/保存本地清单,远端与本地 diff |
FCPT_AssetSyncService |
异步拉取远端资产列表 |
FCPT_AssetDownloadService |
并发下载队列(最多 3 路),进度回调到 UI |
| PakLoader 集成 | 运行时 MountPak、RegisterMountPoint、加载 Blueprint Actor |
同步流程:
|
|
下载侧采用线程池执行 HTTP 阻塞 IO,完成后通过 AsyncTask 回调到 GameThread;通过 TWeakObjectPtr<UCPT_UnitSkuButton> 与 UI 按钮弱关联,避免下载完成时控件已销毁导致的悬空引用。
踩坑记录:批量打包时不同 Pak 的 Mount Point 不一致(有的以 Content/ 开头,有的以 PreviewTool/Content/ 开头),导致路径拼接失败。最终改为统一 RegisterMountPoint("/PTPakDLC/", "../../../PreviewTool/Content/"),并从 Pak 内路径截取 Content/ 之后的相对段来构造引擎可识别的资产路径。详见个人笔记《使用 UE 挂载 Pak 时遇到的一个问题》。
5. 撤销系统(命令模式)
采用经典 Command Pattern,将可撤销操作封装为 IUndoableCommand(Do() / Undo()),由单例 FUndoManager 维护最多 5 步撤销栈。已实现平移、属性修改、删除等命令,绑定 Ctrl+Z。
选择限制 5 步而非无限栈,是早期版本的 pragmatic 取舍——预演场景以快速迭代为主,后续可扩展为可配置深度。
6. 自研 Editor 插件 PakTools
自研 PakTools 插件包含两个模块,与客户端 Runtime 侧 PakLoader 形成完整资产管线:
| 模块 | 类型 | 职责 |
|---|---|---|
CreatePak |
Editor | Slate 面板(SCreatePakMainWidget),Cook → 打 Pak → 上传服务器 |
PakLoader |
Runtime | 运行时 MountPak、RegisterMountPoint、加载 Blueprint Actor |
Editor 侧通过 FPakToolsSetting 管理打包配置,FPTUploadTask 异步执行上传任务。打包阶段与客户端约定了统一的 Mount Point 和路径规则,避免 Runtime 加载失败。
7. 其他功能模块
- 摄影机系统:电影级摄影机组件 + 实时取景窗口(CameraCapture 插件),支持焦距、光圈、对焦距离调节
- 灯光与环境:方向光、天光、体积雾、后处理、色彩校正;专业灯具 Actor(聚光、柔光、吊灯等)
- LED 虚拟拍摄舞台:多种预设方案 + 弧形 LED 幕墙程序化生成(
CPT_WallBuilderManager) - 项目持久化:场景、环境、动画、渲染设置统一 JSON 序列化(
ConstructJsonObject()体系)
PreviewBMS 资产后台(简要)
配套的 Pak 资产管理平台(Django REST + React),负责运营侧上传、分类与 OBS 存储。我负责资产元数据模型与 API 契约设计、客户端同步协议(清单 diff / MD5 / 按需下载)及 UE 端全部联调实现;后台 CRUD 借助 AI 辅助搭建。
开发过程中遇到的问题
- Pak Mount Point 不统一 → 统一挂载点注册 + 路径截取策略(见上文)
- 批量 Cook 资产丢失 → 排查打包流程,规范 Cook 路径与依赖
- 资产数量增长后加载慢 → 引入按需下载 + 并发队列 + 缩略图预拉取,UI 进度反馈(持续优化中)
- 引擎启动黑屏 → 添加 PreLoadingScreen 模块,覆盖启动阶段
可深入讨论的话题
以下是我认为适合深入交流的点:
- Pak Mount Point 不一致:如何排查、为何
RegisterMountPoint能统一路径、Editor 打包与 Runtime 加载的约定 - 动画-渲染时间同步:AnimManager 与 RenderManager 如何共享时间基准,保证预览与导出一致
- RuntimeTransformer 二次修改:
IFocusableObject接口设计、组件选取约束、与 UMG 主界面的协作方式 - Pak 并发下载架构:线程池 + GameThread 回调 +
TWeakObjectPtr弱引用防悬空
如需进一步了解某个模块的实现细节,欢迎面试时深入交流。我可以现场讲解任意一条链路的数据流与类设计。
总结
PreviewTool 是我将 UE5 引擎能力、工具链思维和业务需求结合的一次完整实践。客户端从 Actor 体系、C++ UMG 控件、动画时间轴、逐帧渲染到 Pak 运行时加载,以及自研 Editor 插件 PakTools,均由我独立设计与实现;资产后台则体现了从 API 契约定义到 UE 端联调的端到端交付能力。
演示与材料
演示视频:Previze 虚拟制片预演系统功能演示