演示视频Previze 虚拟制片预演系统功能演示

image.png


系统介绍:基于 UE5 的影视/舞台三维预演工具,覆盖场景搭建、灯光机位、动画时间轴到逐帧渲染的全流程;我独立完成了客户端主体开发、自研 Editor 插件,并设计了与云端资产系统的对接方案。


项目背景

在影视制作、舞台演出和虚拟拍摄场景中,导演、摄影和灯光团队往往需要在实拍前反复验证场景布局、灯光方案和机位调度。传统流程依赖多个软件切换,沟通成本高、试错代价大。

PreviewTool(虚拟预演系统) 是我从 2024 年起持续开发的 ToB 端产品:

  • 预演系统(主体):面向导演、摄影、灯光师的实时三维预演工作台(本人独立设计与实现
  • Editor工具插件:Pak 资产的 Cook、打包与上传工具(本人独立设计与实现
  • Pak 资产管理后台:资产上传、分类与版本管理(需求与 API 契约由本人定义,CRUD 实现借助 AI 辅助开发)

项目目前处于可演示、可实际使用的阶段,已在内部预演流程中验证核心链路。


系统架构

PreviewTool 系统架构图


技术栈

客户端开发(核心)

类别 技术
主语言 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 实现与时间轴联动的离线帧序列导出:

1
2
3
计算总帧数 → StartRenderingSequence → Timer 驱动 RenderNextFrame
→ 同步 AnimManager 时间 → ExportFrameImage(PNG/JPEG)
→ 完成后触发 DE_OnRenderCompleted

渲染参数由 FRenderOptionData 定义:分辨率、帧率、画质、输出格式、起止时间等。这是预演方案汇报的核心输出能力。

4. Pak 资产云端同步(客户端侧)

这是我投入较多精力的模块,解决了「资产与程序分离、按需更新、离线可用」的需求。

核心类

职责
FCPT_AssetManifestUtils 加载/保存本地清单,远端与本地 diff
FCPT_AssetSyncService 异步拉取远端资产列表
FCPT_AssetDownloadService 并发下载队列(最多 3 路),进度回调到 UI
PakLoader 集成 运行时 MountPak、RegisterMountPoint、加载 Blueprint Actor

同步流程

1
2
登录获取 JWT → GET /api/v1/asset/assets/ → DiffRemoteAndLocal
→ 增量下载新/更新 Pak → 更新 manifest_cache.json → MountPak → 资产库可用

下载侧采用线程池执行 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,将可撤销操作封装为 IUndoableCommandDo() / 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 辅助搭建。


开发过程中遇到的问题

  1. Pak Mount Point 不统一 → 统一挂载点注册 + 路径截取策略(见上文)
  2. 批量 Cook 资产丢失 → 排查打包流程,规范 Cook 路径与依赖
  3. 资产数量增长后加载慢 → 引入按需下载 + 并发队列 + 缩略图预拉取,UI 进度反馈(持续优化中)
  4. 引擎启动黑屏 → 添加 PreLoadingScreen 模块,覆盖启动阶段

可深入讨论的话题

以下是我认为适合深入交流的点:

  1. Pak Mount Point 不一致:如何排查、为何 RegisterMountPoint 能统一路径、Editor 打包与 Runtime 加载的约定
  2. 动画-渲染时间同步:AnimManager 与 RenderManager 如何共享时间基准,保证预览与导出一致
  3. RuntimeTransformer 二次修改IFocusableObject 接口设计、组件选取约束、与 UMG 主界面的协作方式
  4. Pak 并发下载架构:线程池 + GameThread 回调 + TWeakObjectPtr 弱引用防悬空

如需进一步了解某个模块的实现细节,欢迎面试时深入交流。我可以现场讲解任意一条链路的数据流与类设计。


总结

PreviewTool 是我将 UE5 引擎能力、工具链思维和业务需求结合的一次完整实践。客户端从 Actor 体系、C++ UMG 控件、动画时间轴、逐帧渲染到 Pak 运行时加载,以及自研 Editor 插件 PakTools,均由我独立设计与实现;资产后台则体现了从 API 契约定义到 UE 端联调的端到端交付能力。


演示与材料

演示视频Previze 虚拟制片预演系统功能演示

image.png

image.png image.png