
1. 为什么要把 grandMA2onPC 和 UE4 接在一起前年冬天接了个虚拟演播厅的改造项目甲方手里有一台用惯了的 grandMA2 灯控台现场灯光师对推子、程序器、Cue 列表熟得闭着眼都能操作。但问题是舞台上只有一小半是实体灯另外一大半是 UE4 里搭的虚拟场景灯——演播厅要做虚实结合的镜头实体灯和虚拟灯必须同时出画。如果让灯光师左手控台、右手鼠标去 UE4 里单独再调一遍那基本等于把工作量翻倍而且两头的时间同步根本对不上。最后我们定的方案就是让 grandMA2onPC 当大脑UE4 只当听话的虚拟灯架。这套玩法听起来玄乎其实拆开就是一条很朴素的信号链控制台算好每一路 DMX 的值通过网线以 Art-Net 协议广播出去UE4 里接住这些数值再翻译成灯光的强度、颜色、位置、光束角度。核心关键词 grandMA2onPC 和 UE4 在这里的关系本质上是控制端和被控端的关系中间靠网络协议牵线。它能解决什么问题我总结下来是三类人最需要。第一类是虚拟制片和虚拟演播厅的团队现场有真实控制台、有虚拟场景需要一个统一的灯光控制入口。第二类是舞台预演和方案汇报先在 UE4 里把灯位、Cue 全部排好给导演看效果省掉进棚搭灯的成本。第三类是个人玩灯光可视化或者做 Demo手头只有一台电脑用 onPC 免费版也能跑起来。适合谁看只要你会基本的 UE4 蓝图连线、知道 DMX 是 512 个通道一组剩下的我都在下面拆开讲。哪怕你从来没碰过灯光控制台按着步骤走一遍也能通。我尽量把为什么要这么设讲透因为这类跨软件联调最容易卡住的地方恰恰不是操作本身而是你不知道对方在想什么。2. 整体方案设计与协议选型2.1 信号链路的三种走法怎么选从 grandMA2onPC 到 UE4能走的协议就那么几种我按实际用下来的感受排个序。第一种是Art-Net。这是灯光行业最通用的以太网 DMX 协议UDP 广播端口 6454包里装着 512 字节的通道数据。grandMA2 原生支持输出UE4 内置的 DMX 插件也原生支持接收两边都不用装第三方中转链路最短。我大部分项目都走这条。第二种是sACNE1.31。同样是 UDP 广播端口 5568是后来定的标准协议理论上网络管理更规范支持优先级和组播。但实际项目里非灯光的网络设备对组播支持参差不齐交换机配置不好容易丢包所以我一般在纯灯光网络里才用它。第三种是OSC 或者自研 UDP 转发。走这条路一般是因为你不想用 DMX 那套通道思维想让控制台直接发语义化的参数。但要额外写一个转发程序把控制台的输出翻译成 OSC链路长、故障点多除非有特殊需求我一般不推荐。选 Art-Net 的核心理由很直白两端零改装。grandMA2 里添加一行 Art-Net 输出就能发UE4 里启用 DMX 插件就能收中间不需要任何脚本、不需要任何硬件盒子。对一个要在现场三小时内调通的项目来说链路上每少一个环节都是救命的。2.2 为什么不让 UE4 自己算灯光有人会问UE4 里灯光本来就是引擎自己算的为什么非得让外面的控制台来算这个问题的答案藏在工作流程里。灯光设计本质上是一种时间艺术。一个 Cue 什么时候起、什么时候落、淡入多久、推子怎么推这些全是时间轴上的表演动作。grandMA2 这类控制台几十年的积累全在 Cue 列表、程序器、时间码这些东西上。灯光师按一个 GO 键几十路灯光在精确的时间曲线里同时变化这套东西让 UE4 从零做工作量巨大而且不专业。反过来UE4 擅长的是视觉表现。扫描光、体积雾、光线追踪、屏幕空间反射这些实时渲染的效果是控制台给不了的。所以最合理的分工就是控制台负责什么时候变、变成什么值UE4 负责把这个值渲染成一个好看的画面。这就是我一直在用的思路——UE4 不当大脑只当执行器。注意这个分工定下来之后UE4 里的灯光蓝图就不要自己再写自动动画了。见过有人一边收 DMX 一边又给灯光加了时间轴动画两边打架现场闪得跟迪厅一样。2.3 版本和插件的前置确认动手之前先把版本对齐。UE4 这边4.26 是一个分水岭从这一版开始引擎内置了完整的 DMX 相关插件DMX Engine、DMX Protocol、Art-Net、sACN、DMX Fixtures到了 UE5 这套东西还在而且更完善。如果你还在 4.2x 之前的版本要么升级要么退回去用第三方插件后者维护成本高很多。grandMA2 这边onPC 版本和完整控制台版本在参数规模和输出能力上有差别特别是 Art-Net 输出的路数限制和是否需要连接 MA 的硬件节点解锁。我第一次搭的时候就卡在这——软件里配了 Art-Net 输出UE4 死活收不到后来发现是输出许可的问题。所以动手前先确认自己的 onPC 版本能发多少 Universe这一点问一下相关技术支持比自己在论坛翻半天快。另外还有个隐藏前提两台机器必须在同一个网段。我把控制台机器设成 192.168.1.100UE4 机器设成 192.168.1.101子网掩码都是 255.255.255.0。别用自动获取 IP现场路由器一抽风地址变了能让你查一晚上。3. grandMA2onPC 侧的配置与配接3.1 Art-Net 输出怎么打开进 grandMA2onPC先按Setup找到Network里的MA Network Configuration。在 Art-Net 标签页里你需要添加至少一行输出配置指定起始 Universe 和输出的数量。这里有个细节MA 侧的 Universe 编号是从 1 开始数的而 Art-Net 协议本身的 Port-Address 是从 0 开始算的。也就是说 MA 里的 Universe 1对应到协议层的 Net 0、Subnet 0、Universe 0。这个差一位的坑我第一次踩得很难受——控制台明明有输出UE4 里怎么都黑着。后来在 UE4 那侧把接收的 Universe 调成 0画面立刻亮了。所以我的习惯是在 UE4 那边先把接收范围设宽一点比如 0 到 3 全部监听等你确认哪一路有信号再收紧。网络配置里还要确认Local Start和Amount这两个参数前者是你从哪一路开始发后者是发多少路。如果你只做三个灯的测试发 1 个 Universe 就够了别一次开 8 个广播包太大会让交换机喘。3.2 Universe 与地址规划配接之前先画表。这是我从做实体灯养成的习惯虚拟灯也一样。我通常这样分Universe 1 给主灯和面光Universe 2 给染色和氛围Universe 3 给效果灯和移动头。每个 Universe 512 个通道一个常规的三通道 RGB 灯占 3 个地址一个带 Pan/Tilt/Dimmer/RGB 的移动头大概占 12 到 20 个地址。算的时候留 20% 的余量因为后期加灯是必然的。举个实际的例子。第一台虚拟灯是 RGBW 四通道占地址 1.001 到 1.004第二台同样型号占 1.005 到 1.008。这样连续排下去UE4 那边配 Fixture Patch 的时候也是连续地址出错概率最低。提示千万不要把同一台虚拟灯的通道拆到两个 Universe 里。虽然技术上做得到但一旦出问题你要同时查两个地方排查时间翻倍收益为零。3.3 灯具配接与通道模板在 grandMA2 里按Setup进Patch Fixture Schedule新建一个 Fixture。关键在 Fixture Type 的选择。如果你用的是标准的三通道或四通道灯直接选 Generic 里的对应类型就行。但如果你想要更接近真实控制台的手感建议把 UE4 里虚拟灯的通道定义做成和实体灯一模一样的 Fixture Type。这里有个很实用的技巧用 GDTF 文件统一两边的定义。GDTF 是灯光行业通用的设备类型描述格式grandMA2 支持导入UE4 的 DMX 插件也支持导入。也就是说你在 UE4 里定义好一个虚拟灯的通道结构导出成 GDTF再导进 grandMA2两边的通道定义就完全一致了配接的时候不会再出现我以为是第 3 通道是蓝色结果是红色这种低级错误。如果你的项目不大懒得搞 GDTF那就老老实实拿纸把通道表画出来贴在显示器边上这个笨办法我用了好几年比什么都可靠。3.4 用推子快速验证输出配接完成后不要急着去开 UE4。先在 grandMA2 里做个最简单的测试选中这台虚拟灯把它的 Dimmer 通道推到 100%然后看控制台的 DMX 输出窗口DMX Output 或者 Channels 视图确认对应的通道值确实是 255。这个步骤看着多余实际上能帮你砍掉一半的排查工作量。因为一旦 UE4 那边没反应你可以立刻判断问题出在网络传输还是 UE4 接收而不是从零开始两头猜。我现在的流程固定是先验证控制台有输出再验证 UE4 有接收最后调映射。三步分开查每一段都独立可测。4. UE4 端接收与灯光绑定4.1 插件启用与项目设置打开 UE4进Edit → Plugins搜索 DMX把DMX Engine、DMX Protocol、Art-Net、DMX Fixtures这几个启用然后重启编辑器。重启是必须的这几个插件是加载期初始化的不重启不生效我见过太多人卡在这一步。重启后进Project Settings → Plugins → DMX找到 Communication Settings。这里配置的是接收端的参数Art-Net 的监听端口默认 6454不用改要配的是接收的 Universe 范围。前面说过先设宽一点比如 0 到 3等确认信号进来了再收窄。配好之后打开Window → Developer Tools → Output Log你会在日志里看到 DMX 插件打印的接收状态。如果控制台在发日志里能看到每个 Universe 的更新频率。这一步是判断到底有没有收到包最直接的方式比在蓝图上瞎连快得多。4.2 DMX Library 与 Fixture Type 的定义UE4 的 DMX 体系里DMX Library是核心资产它里面装着 Fixture Type灯具类型定义和 Fixture Patch配接信息。在内容浏览器右键选DMX → DMX Library新建一个。进去之后先定义 Fixture Type。你可以手动添加属性也可以用前面提到的 GDTF 导入。属性名称建议用行业通用的叫法Dimmer、ColorAdd_R、ColorAdd_G、ColorAdd_B、Pan、Tilt、Zoom这样蓝图里调起来和你脑子里想的完全一致不用再记一套自定义名字。Fixture Patch 就是把 Fixture Type 和具体的 DMX 地址绑起来。前面算好的 1.001 到 1.004在这里一条条建。建完之后你在 UE4 里就有了一个虚拟灯架每一台虚拟灯的每一个属性都能按地址索引到。4.3 蓝图里把通道值翻译成灯光参数接下来是关键一步怎么把 DMX 的 0 到 255 变成 UE4 灯光能用的值。做法是给灯光 Actor 加一个DMX Component在组件详情里选好刚才建的 DMX Library 和对应的 Fixture Patch。加完之后这个 Actor 就能在蓝图里读到它自己对应的那一路 DMX 属性了。不同版本里节点命名有差异我这边用的是从 DMX Component 上取属性值的那类节点取出来的是归一化后的浮点数0 到 1也有直接给 0 到 255 原始值的看你版本。拿到值之后就是翻译。我一般的分组是这样的DMX 属性UE4 目标参数映射方式DimmerLight Intensity乘法放大按灯型定倍率ColorAdd_R/G/BLight Color三通道归一化后合成线性 RGBPanActor 或灯的 Yaw 旋转线性映射到角度范围TiltPitch 旋转线性映射到角度范围ZoomSpot Light 的 Cone Angle反向映射值越大角度越小Dimmer 的映射要注意DMX 的 0 到 1 直接乘到灯光强度上出来的曲线不对。人眼对亮度的感知是非线性的中间值会显得太亮。我的做法是加一条Curve 资产把直线映射改成 S 型或者幂函数曲线出来的淡入淡出才符合视觉习惯。这个细节第一次做的人基本都会忽略做出来的淡入就跟开关一样生硬。4.4 RGB 的线性空间问题颜色这块有个必须讲清楚的坑。DMX 里的 RGB 值通常是按 sRGB 编码的而 UE4 的灯光颜色是线性空间。如果你直接把 0 到 255 除以 255 丢进灯光颜色红蓝会显得特别冲过渡也不对。正确做法是把归一化后的值做一次 sRGB 到线性的转换再赋值给灯光颜色。UE4 里蓝图上有现成的节点可以做这个转换。转换之后你会发现同一个 DMX 值出来的颜色比不转换的时候柔和、准确很多。这个调整做完之后控制台那边的颜色推子和 UE4 里的观感基本能对上灯光师才愿意用。5. ue4 外接设备映射的两种思路5.1 什么是外接设备映射所谓 ue4 外接设备映射说白了就是把外部设备的输入值绑定到引擎里的某个参数上。这个概念在游戏里常见的是手柄、方向盘、MIDI 键盘的输入映射在灯光场景里外部设备就是 DMX 控制台映射的目标就是灯光参数。UE4 内置的 DMX 体系已经把这层映射做成了资产化的流程Fixture Type 定义有哪些属性Fixture Patch 定义从哪个地址读DMX Component 定义这个 Actor 用哪一路配接。三层拆开之后改地址不用改蓝图改蓝图不用动地址这是我特别喜欢这套设计的地方。如果你的项目不用内置 DMX 插件还有另一条路自己写 UDP 接收。Art-Net 包的结构并不复杂前面是固定头部后面跟 512 字节的通道数据。用 C 或者 Python 起一个 UDP 监听收到包解析出来再通过某种方式把值喂给 UE4。这条路灵活性最高但维护成本也最高版本一升级可能就要重写我建议只在有明确需求时才走。5.2 8bit 与 16bit 的精度陷阱映射里最容易翻车的地方是位宽。常规 DMX 一个属性占 8 bit也就是 0 到 255 共 256 级。这对颜色和亮度够用但对Pan 和 Tilt 这种位置控制就不够。一个移动头水平转 540 度8 bit 分下来每一级差不多 2 度推子慢慢推的时候你能明显看到跳灯是一格一格挪的。解决办法是用16 bit 精度也就是两个通道合起来表示一个属性高字节加低字节分辨率变成 65536 级跳变就看不出来了。grandMA2 侧配接的时候要把 Pan 设为 16 bit占两个通道UE4 侧的 Fixture Type 里也要把对应属性的位宽设成 16 bit否则它只读高字节低字节那一路的数据就白发了。注意一旦改成 16 bit通道表要重排后面的所有灯地址都要往后挪。这种改动我一般放在方案定稿之前做中途改会牵连一大片。5.3 反向映射与状态回传还有一种进阶玩法是反向映射把 UE4 里的状态回传给控制台。举个场景虚拟场景里有个道具被人推动了你希望控制台上对应的那路灯跟着变化让灯光师看到哦那边有动静。这时候需要 UE4 侧发 Art-Net 出去grandMA2 侧再开一路 Art-Net 输入接收。两边都开收发的时候一定要注意不要把端口和 Universe 配冲突最好收发用不同的 Universe 段比如 0 到 3 收100 以上发中间隔开一大截不容易搞混。我自己项目里反向映射用得不多主要是同步状态指示这类小需求。如果你的项目就是要做双向联动那就把收发两套配置写在文档里贴墙上别靠记忆。6. ue4查询和物理模拟器的区别与灯光联动6.1 查询和物理模拟到底差在哪这个热词放在灯光联动的语境里特别有价值因为很多人做灯光跟随的时候第一反应是用物理结果性能崩了。查询Query指的是射线检测、形状扫描、重叠检测这一类操作。UE4 里的 Line Trace、Sphere Overlap、Sweep走的都是场景查询系统。它的特点是只读——问一句这个方向上有东西吗拿到一个 Hit Result世界状态一点没变。它依赖的是碰撞体所以碰撞预设配得好不好直接决定查询命中不命中。物理模拟Simulate Physics是完全不同的一件事。物体开了 Simulate Physics就有了质量、速度、惯性会受重力、会被撞飞、会推动别的物体。它是由物理解算器4.2x 之后是 Chaos每帧算出来的你有子步Substep设置有求解迭代次数开销跟模拟体的数量和碰撞复杂度正相关。一句话概括查询是问问题物理是演世界。问问题很便宜演世界很贵。6.2 性能和精度的对比维度查询Trace/Overlap物理模拟Simulate Physics对世界的影响只读不改状态读写会改变位置和速度性能开销低可以每帧多次高与模拟体数量强相关精度依赖碰撞体形状和碰撞预设解算频率、子步、CCD 设置典型用途瞄准、跟随、可见性判断掉落、碰撞、绳索、机械运动常见坑碰撞通道设错查不到高速穿模、抖动、性能雪崩做灯光跟随的时候我的选择非常明确目标物体的位置用查询拿不用物理。演员在虚拟场景里走动我用射线从上方打下去找到脚下的地面位置或者直接读 Actor 的 Transform把坐标映射成 DMX 的 Pan/Tilt 值发出去。这条链路轻量、稳定、每帧都能跑。什么时候才需要物理舞台机械、悬挂吊杆、飞行器这类真的会动的装置。这时候用物理模拟让它们动起来然后再用查询去读它们的位置把位置转成灯光参数。注意读位置这一步仍然是查询物理只负责动。6.3 用查询驱动虚拟追光的实操说个具体做法。虚拟舞台中间有个主持人我要让一盏虚拟追光跟着他。第一步在主持人 Actor 上挂一个碰撞体设成自定义的碰撞通道比如叫 Talent只对这个通道响应。第二步在追光 Actor 的蓝图里每帧从追光的位置朝主持人方向打一条射线通道设成 Talent。命中之后用命中位置减去追光位置算出方向向量。第三步把方向向量拆成水平角和垂直角水平角乘以映射系数变成 Pan 的 DMX 值垂直角同理变成 Tilt。这两个值直接写进对外的 DMX 属性上。第四步在 grandMA2 侧接收这两个值就当是操作了一台真实追光。灯光师还能在控制台上手动做微调两边不冲突。整套下来没有一处用到物理模拟帧率稳得很。我实测过一百来个 Actor 同时做射线查询在常规配置的机器上性能影响可以忽略但如果换成让这一百个物体全都开物理帧率立刻掉一大截。提示射线查询要设好最大距离别设成 0无限远。无限距离的射线会扫过整个场景开销比你想象的大得多尤其是在大关卡里。7. 常见问题排查与实操心得7.1 收不到信号的排查顺序我把排查顺序固定成四步按这个走基本十分钟能定位。第一步看控制台有没有输出。grandMA2 的 DMX 输出视图里对应通道值要动起来。不动就是配接或程序器的问题跟网络无关。第二步看网络通不通。两台机器互相 ping 一下能通再说。不通先查网段和防火墙Windows 的防火墙默认会拦 UDP 广播我是直接把私网防火墙关掉或者给 UE4 加白名单。第三步看 UE4 的 Output Log。DMX 插件会打印接收状态有包进来就有日志。没有的话八成是 Universe 编号差一位或者端口被占用。第四步看蓝图绑定。前面都通了但灯不亮那就是 DMX Component 没选对 Library 和 Patch或者属性名字写错了。这个顺序的好处是每一步都只依赖上一步的结果不会出现我改了三个地方现在不知道是哪个生效了的情况。7.2 灯光抖动和跳变的成因抖动一般来自三个地方。一是帧率不同步。控制台发 Art-Net 的频率和 UE4 的帧率不是一回事如果蓝图里在 Event Tick 里直接读 DMX 值帧率波动的时候读出来的值会有节奏地跳。解决办法是把 DMX 值的更新放到 DMX 组件自己的更新事件里而不是每帧去轮询。二是网络丢包。UDP 广播不保证送达交换机负载高的时候丢包值就会有瞬间的跳变。可以给关键属性加一个简单的平滑插值把突变抹掉一部分。代价是响应会慢一点点这个取舍在追光这种场景里要谨慎。三是8 bit 精度不够前面讲过了位置类属性一定要上 16 bit。7.3 时间码和同步的注意点如果项目里要跟时间码走grandMA2 侧用时间码触发 CueUE4 侧其实是被动接收的——控制台算好什么时间发什么值UE4 只管收。这种情况下两边的时钟不需要严格同步因为触发逻辑全在控制台那边。但如果你要做的是UE4 里的镜头动画和灯光 Cue 严格对齐那就得让两边共用同一个时间源。常见的做法是用外部时间码设备统一发两边都作为从设备接收。这块我踩过的坑是帧率基准不一致控制台按 30 帧算UE4 里序列按 25 帧播走个十几分钟就明显错位了。动手前把帧率基准统一确认一遍能省掉大量后期对轴的时间。7.4 我踩过的那几个坑第一个坑是DMX Component 挂错 Actor。我一开始把 DMX Component 挂在灯光的父级蓝图里结果每个子实例都去读同一路配接所有灯一起变。后来改成每台灯单独挂、单独配 Patch才对上。第二个坑是灯光强度倍率拍脑袋定。Dimmer 推到 100% 的时候虚拟灯要么过曝要么没感觉。后来我固定流程先在场景里手动把灯光调到理想亮度记下强度值再反推倍率写进蓝图。这样出来的效果和美术预期一致不会现场吵架。第三个坑是Art-Net 广播把网络打满。测试阶段我一次开了 8 个 Universe 全量发送交换机直接顶不住控制台和 UE4 都卡。后来改成只发用到的 Universe问题立刻消失。广播包虽然单个不大但频率高量堆起来很吓人。7.5 还能往下扩展的方向这套架子搭起来之后能接的东西比想象中多。比如把 UE4 里的虚拟摄像机位也做成 DMX 控制用控制台的推子控制虚拟摇臂或者把投影、LED 屏幕的内容切换也纳入同一套 Cue 列表做到一个 GO 键全场变化。再远一点可以做多机同步——几台 UE4 机器同时接收同一个 Art-Net 流各自渲染不同视角在虚拟制片里这个需求非常常见。我个人的习惯是每做完一个项目就把这次的 Universe 分配表、Fixture Patch 表、蓝图映射表整理成一份文档存下来。下一个项目直接改数字就能复用比重新摸索快太多了。灯光这类活儿经验最大的价值就是让你在出问题的时候能在十分钟内知道该看哪里而不是从头开始怀疑人生。