1. 从一次地形雕刻翻车说起:Modeling Mode 到底解决什么问题
去年帮一个独立团队做开放世界原型,美术在 Landscape 上刷完地形后想加几块悬崖岩壁,结果传统流程是导出到外部建模软件、雕完再导回来、对位、烘焙法线,一套下来半小时没了,改一版重来一遍。后来我让他们切到 UE5 的 Modeling Mode,直接在引擎里用 Dynamic Mesh 拉了个岩壁,配合 Geometry Script 写了几行脚本批量撒石头,整个过程压缩到五分钟以内。这就是 Modeling Tools 这套东西存在的意义——把"建模"这件事从外部 DCC 拉回引擎内部,让迭代循环从"导出-修改-导入"变成"就地改、实时看"。
Modeling Mode 是 UE5 内置的一套网格编辑工具集,挂在编辑器模式切换栏里(和 Select、Landscape、Foliage 并列)。它底层依赖的是Dynamic Mesh(UDynamicMesh)这套运行时可变的数据结构,而不是传统的 UStaticMesh 静态描述。理解这一点非常关键:StaticMesh 是"烘焙好的成品",改一个顶点都要重新构建渲染资源;Dynamic Mesh 是"可随时揉捏的橡皮泥",顶点、三角面、属性都能在编辑期甚至运行期动态增删。Modeling Mode 里的每一个工具,本质上都是对 Dynamic Mesh 做一次几何运算,算完再决定是写回 StaticMesh 资产还是保留为动态对象。
这套工具集适合谁?三类人最该吃透它。第一类是关卡/环境美术,天天和地形、建筑模块、道具摆放打交道,需要快速做 blockout 和细节调整;第二类是技术美术和工具向程序,想用 Geometry Script 把重复性建模工作自动化,比如程序化生成围栏、楼梯、管道;第三类是独立开发者,团队里没有专职建模,需要在一个引擎里搞定从白模到成品的全流程。如果你只是偶尔改改模型,那外部 DCC 可能更顺手;但只要你的工作流里出现"反复微调""批量生成""和场景强关联"这几个词,Modeling Mode 就值得花时间啃下来。
需要先明确一个边界:Modeling Mode 不是要取代 Maya、Blender 这类专业建模软件。它在高精度曲面、复杂拓扑、UV 精细排布上依然打不过专业工具。它的强项是中等精度、强场景关联、高频迭代的资产。认清这个定位,你就不会拿它去雕一个人物头像然后骂它难用——那不是它的战场。
2. Dynamic Mesh 与 StaticMesh 的底层差异:为什么改起来这么快
2.1 两种网格表示的本质区别
要理解 Modeling Mode 为什么能做到"实时编辑",得先搞清楚 Dynamic Mesh 和 StaticMesh 在内存里长什么样。StaticMesh 的顶点数据在构建后就基本固定,渲染线程和游戏线程各自持有一份优化过的副本,包含预计算的法线、切线、UV、LOD 链、碰撞体等。你改一个顶点,等于要重新走一遍构建管线,代价高,所以传统上编辑期和运行期是割裂的。
Dynamic Mesh 则把网格表示成一组可变的顶点数组、三角索引数组和属性数组(法线、UV、颜色、材质 ID 等),所有编辑操作都是对这些数组做增删改。它没有预烘焙的 LOD,没有复杂的渲染优化,换来的是任意时刻都能改。Modeling Mode 的工具执行时,先把 StaticMesh 转成 Dynamic Mesh,在动态表示上做运算,运算完再转回 StaticMesh 写回资产。这个"转换-运算-回写"的流程,就是你在 Modeling Mode 里点一下工具后背后发生的事。
| 对比维度 | StaticMesh | Dynamic Mesh |
|---|---|---|
| 数据可变性 | 构建后基本固定 | 任意时刻可增删改 |
| 渲染优化 | 预计算 LOD、法线、切线 | 无预烘焙,实时计算 |
| 编辑代价 | 高,需重建资源 | 低,直接改数组 |
| 典型用途 | 最终成品资产 | 编辑期中间态、程序化生成 |
| 碰撞体 | 预烘焙 | 需手动生成或运行时构建 |
2.2 转换过程中的性能陷阱
很多人第一次用 Modeling Mode 会踩一个坑:对一个几十万面的高模点开某个工具,编辑器直接卡死几十秒。原因就是"转换-运算-回写"这条链路里,Dynamic Mesh 的构建和三角化是 CPU 密集操作,面数越大越慢。我的经验是,单个 Dynamic Mesh 编辑对象控制在 5 万面以内体验最顺,超过 20 万面就要考虑先减面或者拆分处理。
还有一个隐蔽的坑:UV 和材质 ID 在转换过程中可能丢失或错位。Dynamic Mesh 虽然支持 UV 属性,但很多几何运算(比如布尔、简化)会重新生成拓扑,原有的 UV 接缝就对不上了。所以正确的工作顺序是:先用 Modeling Mode 把形状调到位,最后再处理 UV。反过来先展好 UV 再大改几何,等于白做。
2.3 什么时候该保留为 Dynamic Mesh
不是所有编辑完的网格都要转回 StaticMesh。如果你的对象需要在运行期继续变化——比如可破坏的场景道具、程序化生成的地牢房间、玩家可以实时雕刻的沙地——那就应该保留为 Dynamic Mesh 组件(UDynamicMeshComponent),在运行时用 Geometry Script 继续操作。代价是渲染开销比 StaticMesh 高,且没有自动 LOD,需要你自己控制面数和性能预算。
判断标准很简单:这个网格在游戏跑起来之后还会不会变?会变就留 Dynamic,不变就转 Static。我见过有人把所有场景道具都做成 Dynamic Mesh,结果帧率掉了一半,这就是没分清编辑期和运行期的区别。
3. Modeling Mode 工具集的分组逻辑与高频工具实战
3.1 工具分组不是随便排的
打开 Modeling Mode,左侧工具栏那一堆图标看着眼花,其实它们按"操作对象"和"操作意图"分了组。理解分组逻辑,比死记每个工具名字有用得多。
- Create(创建类):从无到有生成几何体,比如 Box、Sphere、Cylinder、PolyExtrude、Draw Polygon。这类工具的输出是全新的 Dynamic Mesh。
- PolyModel(多边形建模类):对已有网格做拓扑级编辑,比如 PolyEdit(点线面编辑)、PolyExtrude、PolyGroupEdit。这是最接近传统建模软件的部分。
- Deform(形变类):不改拓扑只改形状,比如 Smooth、Displace、Offset、Sculpt(是的,Modeling Mode 里有个简易雕刻)。
- Transform(变换类):整体或局部的移动旋转缩放,比如 Transform、Align、Mirror。
- MeshOps(网格运算类):布尔、简化、重网格、切割,比如 Boolean、Remesh、Simplify、Cut。
- Attribute(属性类):处理 UV、法线、材质、顶点色,比如 UV Editor、Normals、Paint Vertex Colors。
- Voxel(体素类):基于体素的运算,比如 Voxel Merge、Voxel Blend,适合做有机融合。
- Utility(工具类):辅助功能,比如 Generate Collision、LOD Manager、Bake Transform。
3.2 三个我每天都在用的工具
PolyExtrude是我用得最多的工具,没有之一。选中一组面,拉出厚度,配合 Shift 可以沿法线挤出,配合 Ctrl 可以保持原始面。做建筑外墙、机械零件、地形台阶全靠它。一个实战技巧:挤出前先用 PolyGroupEdit 把要挤出的面归到一个 Group,这样挤出后新生成的面会自动继承 Group,后续选中和赋材质都方便。
Boolean是双刃剑。做硬表面开洞、合并模块非常爽,但布尔运算对拓扑的破坏很大,容易产生细长的三角面和退化面。我的做法是:布尔完立刻接一个 Remesh 或者 Simplify,把拓扑清理一遍,否则后续 UV 和法线都会出问题。另外布尔的两个操作数最好都是封闭流形(Manifold),开放网格做布尔结果不可预测。
Smooth看着简单,但参数很讲究。Iterations 控制迭代次数,太高会把细节抹平;Alpha 控制每次迭代的平滑强度;还有一个容易被忽略的选项是"是否保持边界"。做有机形状时我一般 Iterations 设 2-3,Alpha 设 0.5 左右,边平滑边观察,别一次性拉满。
3.3 工具组合的实战套路
单个工具解决单个问题,真正的效率来自工具组合。分享几个我常用的组合拳:
做一块破损的墙:先用 Box 创建基础墙体,用 PolyExtrude 拉出砖块凸起,用 Displace 加噪声做表面粗糙,最后用 Boolean 挖几个弹孔。整个过程不离开引擎,五分钟出效果。
做一段管道:用 Draw Polygon 画出管道截面路径,用 PolyExtrude 沿路径挤出,用 Smooth 处理弯角,用 Remesh 统一拓扑密度。比在外部软件里做 spline 建模快得多,而且改路径直接改多边形就行。
做程序化楼梯:这个用 Geometry Script 更合适,后面单独讲。手动做的话就是 Box 阵列加 Boolean 合并,但一旦要改踏步数量就得重来,不如脚本。
4. Geometry Script 联动:把重复劳动交给代码
4.1 Geometry Script 是什么,为什么它和 Modeling Mode 是绝配
Geometry Script 是一套 Blueprint 和 Python 都能调用的 API,让你用代码操作 Dynamic Mesh。它和 Modeling Mode 的关系,就像"手动挡"和"自动挡"——Modeling Mode 是手动点工具,Geometry Script 是把这些工具的操作写成脚本批量执行。Modeling Mode 里很多工具本身底层就是 Geometry Script 函数封装的,所以两者能力高度重合,区别只在交互方式。
为什么说它是绝配?因为 Modeling Mode 解决的是"单次编辑"的效率,Geometry Script 解决的是"批量生成"和"参数化"的效率。你手动做一个楼梯要五分钟,写个脚本之后改踏步数、宽度、高度都是改一个参数的事,一秒重生成。对于需要大量变体的场景——围栏、管道、书架、程序化建筑——脚本的投入产出比极高。
4.2 一个能直接抄的程序化楼梯脚本
下面这段是 Blueprint 里 Geometry Script 节点的逻辑等价 Python 版本,思路是循环生成踏步并合并。实际在 Blueprint 里用节点连线,逻辑一样。
# 伪代码示意:程序化生成楼梯 # 输入参数:踏步数 steps、踏步宽 width、踏步高 rise、踏步深 depth def generate_stair(steps, width, rise, depth): result_mesh = create_empty_dynamic_mesh() for i in range(steps): # 每个踏步是一个 Box step = create_box(width, depth, rise) # 沿高度和深度方向偏移 translate(step, x=0, y=i * depth, z=i * rise) # 合并到结果网格 result_mesh = mesh_boolean_union(result_mesh, step) # 统一重网格,清理布尔产生的碎面 result_mesh = remesh_uniform(result_mesh, target_edge_length=5.0) return result_mesh关键点在于最后那步 Remesh。布尔合并几十个 Box 之后,拓扑会非常乱,接缝处全是细碎三角面。用 Remesh 统一一下边长,网格立刻干净,后续展 UV 和做碰撞都省心。这个"布尔后必 Remesh"的习惯,是我踩了无数次坑才养成的。
4.3 Geometry Script 的性能红线
脚本跑得爽,但有几个性能红线必须知道。第一,不要在 Tick 里跑重几何运算。Dynamic Mesh 的布尔、Remesh 都是毫秒到秒级的操作,放 Tick 里必卡。要跑就放事件触发或者异步任务。第二,批量生成时控制单次合并的对象数量。一次布尔合并几百个 Box,内存和耗时都会爆炸,正确做法是分批合并,每批几十个,最后再合并批次结果。第三,生成的网格面数要有预算。程序化生成很容易失控,一个脚本跑出几百万面,游戏直接跪。养成在脚本末尾加一个 Simplify 或者面数检查的习惯。
4.4 用 Geometry Script 做碰撞体
Modeling Mode 里有个 Generate Collision 工具,但程序化生成的网格往往需要脚本自动生成碰撞。Geometry Script 提供了生成简单碰撞(盒体、凸包、球体)和复杂碰撞的接口。我的经验是:程序化生成的静态道具,优先用凸包碰撞(Convex Hull),性能好且够用;需要精确碰撞的才用复杂碰撞,但一定要控制面数,否则物理开销吃不消。
5. 动态网格编辑在运行期的应用与性能账
5.1 运行期编辑的典型场景
编辑期用 Modeling Mode 是常规操作,但 Dynamic Mesh 真正的差异化价值在运行期。几个典型场景:玩家可以破坏的墙体(打哪缺哪)、可实时雕刻的沙地或雪地、程序化生成的地牢(每次进游戏布局不同)、建造类游戏里玩家自己搭的建筑。这些场景的共同点是网格必须在游戏跑起来之后继续变化,StaticMesh 做不到,Dynamic Mesh 可以。
实现方式是在 Actor 上挂 UDynamicMeshComponent,然后在 Blueprint 或 C++ 里调用 Geometry Script 函数修改网格。比如玩家开枪打墙,你用射线检测命中点,在命中位置生成一个球体,和墙体网格做布尔差集,墙体就出现一个洞。整个过程实时完成,不需要预烘焙破坏效果。
5.2 性能账要算清楚
运行期编辑的代价必须提前算账。Dynamic Mesh 的渲染没有 StaticMesh 那套优化,面数一高帧率就崩。我的经验数据是:单个 Dynamic Mesh 组件在主流配置上控制在 1-2 万面以内比较安全,多个组件加起来别超过 10 万面。超过这个量级,要么减面,要么把不常变的部分转成 StaticMesh。
还有一个容易被忽略的开销:每次几何运算都会触发渲染资源重建。玩家连续破坏墙体,每打一枪就重建一次网格渲染数据,频繁触发会卡顿。优化思路是攒批——把短时间内的多次修改合并成一次运算,或者用异步方式在后台线程算,算完再切到游戏线程更新。
5.3 碰撞与物理的同步问题
运行期改了网格,碰撞体必须同步更新,否则玩家会撞到"看不见的墙"或者穿过"看得见的墙"。Dynamic Mesh Component 支持自动重建碰撞,但重建有开销。我的做法是:破坏类场景用简单碰撞近似(比如破坏后用一个略小的盒体碰撞),不追求逐面精确;需要精确碰撞的场景,控制修改频率,别每帧都改。
6. 踩过的坑与排查链路:从现象到根因
6.1 工具点了没反应,网格纹丝不动
这是新手最常见的问题。排查链路是这样的:先看选中的对象是不是 StaticMesh Actor 而不是 Dynamic Mesh——Modeling Mode 的工具只能作用于 Dynamic Mesh,如果对象还是 StaticMesh,需要先转换。转换按钮在工具栏的 Mode 切换或者右键菜单里。再看是不是没选中任何面/顶点——很多工具(比如 PolyExtrude)需要先选中子元素才能操作,直接点工具是没反应的。最后看是不是对象被锁定了,或者在一个不可编辑的层级里。
6.2 布尔运算后模型变黑或者法线翻转
布尔是重灾区。现象是运算完模型表面发黑、光照不对。根因通常是布尔产生了翻转的法线或者非流形几何。解决办法:布尔后立刻用 Normals 工具重算法线,再用 Remesh 清理拓扑。如果还不行,检查两个操作数是不是都是封闭流形,开放网格做布尔基本必出问题。预防措施是布尔前先确保两个网格都是 Manifold,可以用工具里的检查功能验证。
6.3 UV 在编辑后错乱
前面提过,几何运算会重建拓扑,UV 接缝对不上。现象是贴图拉伸、错位、接缝处出现明显断裂。根因是 Dynamic Mesh 的 UV 属性在拓扑变化后没有正确传递。解决办法是调整工作顺序:先几何后 UV。如果已经展好 UV 又必须改几何,那就改完重新展。UE5 的 UV Editor 支持在 Modeling Mode 里直接展 UV,配合 Auto Unwrap 能快速重做,比外部软件来回导快。
6.4 Geometry Script 跑完网格消失
脚本执行后网格不见了,通常是两个原因。一是布尔运算的操作数有一个是空的或者无效的,导致结果为空。排查方法是逐步打印中间结果的面数,看哪一步变成 0 了。二是坐标变换出了问题,网格被移到了很远的地方或者缩放到 0。检查 translate 和 scale 的参数,尤其是循环里的累积偏移,很容易越算越离谱。
6.5 运行期编辑导致内存持续增长
长时间运行后内存越来越高,最后崩溃。根因通常是每次编辑都创建了新的 Dynamic Mesh 而没有释放旧的。Geometry Script 的很多函数会返回新网格,旧网格如果没被 GC 回收就会泄漏。解决办法是复用网格对象,用 in-place 修改的接口而不是每次创建新的;确实要创建新的,确保旧对象没有引用残留。这个坑在长时间运行的建造类游戏里特别致命。
7. 把 Modeling Mode 嵌进日常工作流的几点心得
我现在的习惯是,任何场景相关的资产,第一版一定在 Modeling Mode 里做 blockout。原因很简单:快,而且和场景比例、光照、相机直接对照着调,比在外部软件里盲做准得多。等形状定稿了,再决定是继续在引擎里细化还是导出到专业软件做高模。这个"引擎内起稿"的习惯,帮我省掉了大量来回导入导出的时间。
Geometry Script 我一般用在两类地方:一是明确的重复性任务,比如沿曲线撒石头、按网格生成书架、程序化围栏;二是需要参数化的资产,比如可调尺寸的楼梯、可调层数的建筑。写脚本的投入,在第三次复用的时候就回本了。但别为了脚本而脚本,一次性做三个的资产,手动做比写脚本快。
最后说一个心态问题。Modeling Mode 的工具很多,别想着一次全学会。挑三五个高频工具(我的选择是 PolyExtrude、Boolean、Smooth、Remesh、Transform)练熟,覆盖 80% 的日常需求。剩下的工具用到再查,工具面板里每个工具都有悬停提示和文档链接。真正拉开差距的不是会多少工具,而是知道什么场景该用什么工具组合,以及踩过足够多的坑之后形成的肌肉记忆。