前言
大家好!我是乔兰?惠伊斯克斯,一名专注技术方案的场景美术。我刚以优异成绩毕业于布雷达应用科学大学,我的作品可以在 ArtStation 主页查看:https://www.artstation.com/jolanpiep。我很享受技术挑战,因此在本次场景项目中,我选择深耕技术方向。这个同人项目旨在探索:如何借助场景美术工具制作游戏大规模关卡,同时给到关卡美术最大限度的操控权限。项目重点围绕工具开发、画面构图与美术指导展开。本文将讲解我为这个同人项目开发各类工具的思路与实现方式,工具清单如下:
本项目所有内容均由我独立制作,与我的本职工作无关。
工具设计理念
程序化方案无疑功能强大,在项目制作中应用广泛,但也常常让美术师感到头疼。我曾经用过一款虚幻引擎内的 Houdini 工具,只要点击下一个资产,它竟会直接删掉你做好的内容!本项目的目标,是开发一套我自己作为场景美术也愿意上手使用的工具。结合过往项目经验,我定下几条设计原则:如果工具操作复杂、不符合直觉,美术就会拒绝使用,最终产出的场景容易出现性能问题,甚至产生不可逆的破坏。如果工具要等待 5 分钟才能出结果,美术可能早就忘记刚才做了哪些调整。这会增加使用难度,甚至被迫接受质量不佳的结果。3A 项目中,每个细节都至关重要。美术会收到来自策划、组长、总监极其细致的修改意见。如果工具缺少足够的手动调节能力,就无法满足需求。
Blender 破碎生成工具
想要实现我设想的这套破碎系统,首先要给模块化资产生成破碎碎片,同时不能破坏模型的模块化属性。无缝建筑结构让这件事难度更高:立柱上下端面一旦出现破碎缝或者边缘破损,就会暴露模块拼接的接缝。离线模型破碎通常在 Houdini 中完成,常用节点如 RBD Material Fracture。Houdini 无疑是功能最强、最通用的方案,但和我前面定下的设计原则相冲突:使用 Houdini 意味着要额外开启一套软件,增加美术的使用成本;解决办法是什么?直接在 Blender 内实现破碎功能,做到快速、无额外负担的产出。一开始我尝试了 Blender 自带的 Cell Fracture 插件,但这个 Python 插件版本老旧且逻辑复杂,很难按我的需求自定义。举个例子,没法简单地做细分并叠加噪点,来生成更复杂的破碎裂纹。于是我决定使用几何节点(Geometry Nodes)开发一套专属破碎系统。几何节点本身功能已经十分强大,并且还在持续迭代新增功能(Blender 5.2 版本新增了物理模块、几何集、列表,还有大家期待已久的几何节点相关能力等等)。我的这套系统参考了 CGMatters 破碎系统作为起点。但这套基础方案存在不少问题:会生成极薄的碎片、碎块尺寸过小,而且无法沿着物体自然断裂位置做切割。参考多方资料并经过多轮迭代,我搭建出一套稳定性更强、效果更真实的算法。下面是该系统的简化原理介绍(基础破碎对每一个模型孤岛循环执行 X 次: 沿模型最长轴向生成一个平面 使用 3D 噪点对平面做位移变形 用该平面执行布尔运算,将模型孤岛切为两半内部细节通过
3D 噪点对破碎后的模型内部做位移扰动
边缘破损
这套基础破碎系统和 CGMatter 教程里的方案大体相似,但做了几项关键优化: 第一,仅对大面积模型孤岛执行切割,让碎块尺寸更加均匀稳定; 第二,使用矩阵奇异值分解(Matrix SVD)沿模型最长轴向进行切割(见图),得到更符合真实物理逻辑的断裂位置; 其余还有一些小幅调整,用于提升稳定性与性能表现。
内部细节
通过位移破碎面内部区域来实现。当前版本使用三平面投影贴图。 最后的边缘破损部分参考了 Cartesian Caramel 的思路:先对模型重新网格化,叠加噪点,再与原始模型做布尔相减运算。在开发过程中我发现,易用的调试工具非常有价值。我增加了移除、分离破碎块以查看模型内部的功能,实践证明这些功能十分好用。我非常建议大家在开发工具时配套做好调试功能!几何节点效果处理完成后,通过我编写的自定义插件对模型做导出预处理。最终成品是一套在 Blender 内部实现的非破坏性破碎工具。它操作简单、经过性能优化,不需要依赖任何外部软件,后续如有需要也可以随时调整参数。该工具即将免费对外发布。我目前正在优化工具的界面与交互体验,移除全部外部依赖,同时提升自定义扩展能力。我还构思了后续迭代方向,例如手动单一切割功能,允许用户精准控制切割的位置与角度。
虚幻引擎阵列工具
为搭建同人项目里连续、纵向且重复排布的建筑结构,阵列工具自然是首选方案。目标是依托模块化资产套件,以非破坏性方式搭建超大尺度的重复建筑。这套系统开发起来很快,原理简单。借助 For 循环,就能沿单行批量放置模型;再嵌套一层 For 循环,即可实现二维阵列排布。添加实例化静态网格组件(Instanced Static Mesh Component)3.1.1 在【变换信息 2】的位置生成静态网格实例这款工具虽然原理简单,但操控直观,使用体验很好。记得在变换参数里开启显示 3D 控件(Show 3D Widget),这样就可以在 3D 视口中直接拖动蓝色 gizmo 操纵器进行调整。我是通过蓝图中的组件脚本(Component Script)搭建这套系统的。好在网上有大量相关学习资料。开发时最大难点是增加随机化功能(模型随机翻转),这个问题我并没有完全解决,或许其他人可以在此基础上继续优化!本工具另一处明显局限:每新建一个蓝图,就会生成一个全新的实例化静态网格组件。你可以尝试将关卡内所有实例合并批量处理,以此优化这套系统。如果项目开启了世界分区(World Partition),可以研究下 ISMCellTransformer(该技巧来自 ArtStation 艺术家 kaymanv)。考虑到这些局限,我推荐大家可以尝试用虚幻引擎 PCG 来实现同类工具,能获得更好的性能优化,还可以和其他 PCG 系统联动。
虚幻引擎破碎工具
破碎系统的下一环节是引擎内工具:供关卡美术使用,能够以非破坏性方式破坏建筑。市面上已有现成方案,大多是引擎内运行的 Houdini HDA 资产。但我选择在 Blender 中预先做好模型破碎,这样就能在虚幻引擎里得到响应迅速的工具,不再依赖与其他软件的互联。整体思路很清晰:用大量碎块重新组合成完整模型,再根据球体碰撞来删除或隐藏碎块。构思这套方案时,我意识到有一个核心难题需要解决:在 Blender 中破碎后的模型都是相互分离的独立碎片在虚幻引擎中,建筑模型必须依靠这些碎片重新拼装还原核心问题:系统如何确定破碎发生的位置?破碎位置信息要如何保存、导出,并在蓝图中调用?每一块破碎模型都需要存储一个位置向量。我构思了几种备选方案:在导出文件中写入自定义数据:FBX 能否支持这种方式?是否必须使用 GLTF?听起来复杂度很高。将数据列表保存为 JSON:不受软件限制,也是值得学习的技术,但实现难度不小。Blender 该如何把这类数据导出成 JSON?在每个模型的目标位置放置一个隐藏顶点:蓝图里要怎样读取这个顶点的坐标?最终方案:插槽(Sockets)插槽是虚幻引擎自带功能,是保存在静态网格上的特殊变换信息,用于挂载其他模型(例如将门挂载到门框,或是把剑绑定到角色手上)。我决定利用这个功能来存储位置数据。在 Blender 中,如果将空物体命名格式设为SOCKET_{插槽名称},虚幻引擎就能自动识别为插槽。于是我编写了 Blender 插件,在导出每一块破碎模型时,同步在目标位置生成对应的空物体。之后就可以在虚幻蓝图中读取该插槽的位置。我借助虚幻引擎的构造脚本(Construction Script)搭建了这套工具的逻辑。系统简化工作流程如下:破碎球体蓝图(Fracture Sphere BP)检测附近的模型蓝图:1.2.2 将碎片移动到插槽(Socket)存储的坐标位置1.2.3 检测碎片是否与附近其他破碎球体产生重叠重叠检测使用蓝图节点Component Overlap Actors和Sphere Overlap Components。插槽的位置信息通过Find Socket节点获取。成品是我用过体验最好的工具之一。它响应迅速、上手简单,完全由美术自主控制。但该工具也存在短板。第一,我没有将它和前面的阵列工具做集成。如果时间更充裕,我会尝试合并两套逻辑。这件事理论上可行,但会耗费大量时间。
第二,当破碎球体数量很多(超过 150 个)时,会出现轻微性能问题。我暂时还没有找到优化方案,如果你有优化思路,欢迎告诉我!
可由美术自主调控的虚幻 PCG 散布工具
在绝大多数场景项目中,散落残骸、植被这类资产的散布是常规操作。PCG 近些年已经成为该场景下的热门方案,但同样存在一些难题。和手动摆放、植被笔刷绘制不同,PCG 默认状态下给到美术的可控性偏弱。而对于高质量的游戏场景,手动调控至关重要:用于把控画面构图、规划玩家通行路径,以及完成环境叙事。即便如此,PCG 性能优秀、灵活性强,还能和虚幻其他系统良好联动。我给自己定下目标,打造一套兼具程序化生成能力与美术可控性的 PCG 系统。其中一个很实用的核心技巧是搭配Actor Data(Actor 数据节点),结合「全部关卡 Actor、按标签筛选、获取单点」功能使用。这可以让 PCG 图表更好地感知整个关卡信息。我用这个功能在破损建筑周边自动散布碎石残骸,当然大家也可以拓展出更多创意用法。我创建了Actor 数组变量来实现手动控制。把它接入 Actor Data 节点,美术就可以手动挑选关卡内的 Actor。既可以在这些 Actor 周围生成更多模型,也可以反过来,清除该区域内生成的模型。Select(选择)节点很适合在同一张 PCG 图表内承载多种生成逻辑。举个例子:碎石残骸仅在带标签的模型附近生成,而草地则在全域生成。整合以上思路,我制作出这套程序化工具,用来配合破损建筑资产一起使用。这套方案主要依靠标签(Tags)与拾取器(Picker)实现,不过你也可以尝试其他方案!比如可以改用地形数据或者蓝图 Actor 来驱动生成逻辑。想要学好虚幻引擎 PCG,我强烈推荐这两个 YouTube 频道:https://www.youtube.com/@adrien_logut/videoshttps://www.youtube.com/@Procedural_Minds/videos希望本文能够对你有所启发!开发工具时,请务必保证工具响应迅速、上手简单,并且把控制权交到美术手中。
文章转载自Thelopy