news 2026/10/2 10:24:38

零赘余开发:Liquid Swords 如何用 UE5 打造高效动作游戏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零赘余开发:Liquid Swords 如何用 UE5 打造高效动作游戏

1. 为什么一个“零赘余”的执念,让 Liquid Swords 押注 UE5

第一次看到 Liquid Swords 这个工作室名字,很多人会愣一下——它不像那些动辄“XX Interactive”“XX Studios”的常规命名,反倒带着点冷兵器的锋利感。这家由前《正当防卫》系列核心成员创立的工作室,在公布《Samson》这款游戏时,做了一个让不少人意外的决定:用虚幻引擎5(UE5)来做一个体量不算大的动作游戏。要知道,UE5 在大众认知里几乎等同于“3A 专用”“硬件杀手”“大团队才玩得转”,一个中小型团队选它,图什么?

答案就藏在标题里那四个字——零赘余。

这不是一句营销口号,而是贯穿他们整个开发流程的核心方法论。所谓“零赘余”,说白了就是:每一行代码、每一个资源、每一帧性能开销,都必须有它存在的理由,没有理由的东西一律砍掉。听起来像废话,但真正做过项目的人都知道,游戏开发里最容易失控的就是“顺手加一点”——顺手加个粒子特效、顺手多一层材质、顺手多开一个蓝图 Tick,最后项目臃肿到跑不动,优化阶段再回头砍,成本翻倍。

Liquid Swords 的做法是反过来的:从第一天起就把“赘余”当成敌人。而 UE5 之所以被选中,恰恰是因为它在“可控性”和“表现力”之间给了一个足够好的平衡点。这篇文章我就从从业者的角度,把这件事拆开讲透——他们为什么这么选、UE5 到底提供了什么、中小团队怎么借鉴这套思路,以及我在实际项目里踩过的那些坑。

如果你正在做游戏开发,尤其是用 UE5 或者正在纠结引擎选型,这篇内容应该能帮你省下不少试错时间。不管你是刚装完 UE5 的新手,还是已经写过几个蓝图的老手,我都会尽量把“为什么”讲清楚,而不是只丢结论。

2. 引擎选型背后的真实逻辑:UE5 到底解决了什么问题

2.1 中小团队选引擎,最怕的不是“功能少”而是“不可控”

先聊一个很多人容易忽略的点:引擎选型从来不是“哪个功能强选哪个”,而是“哪个的代价我付得起”。Unity、Godot、Cocos、UE5,每个都有自己的舒适区。免费商用引擎里,Godot 轻量、Cocos 适合小游戏和微信小程序生态、Unity 生态成熟,这些都是事实。但 Liquid Swords 做的是有明确动作表现诉求、有写实向美术方向、还要兼顾一定物理交互的项目,这时候 UE5 的几个特性就变得关键了。

我自己的经验是,选引擎要看三个维度:美术管线匹配度、性能可控粒度、团队既有技能栈。Liquid Swords 的核心成员来自做过大型开放世界动作游戏的项目,他们对 UE 的渲染管线和 C++ 层已经很熟,换引擎反而要重新学一套工具链,这本身就是“赘余”。所以选 UE5 对他们来说不是冒险,而是顺着肌肉记忆走。

但更重要的原因是 UE5 提供的可控粒度。什么叫可控粒度?就是当你想砍掉某个开销时,你能不能精确地砍。UE5 的渲染管线虽然复杂,但它把很多开关暴露给了开发者:Lumen 可以按项目关掉、Nanite 可以按资产粒度启用、蓝图可以编译成 C++、Tick 可以按需禁用。这种“能开也能关”的特性,对追求零赘余的团队来说,比“默认就很强”更有价值。

2.2 Nanite 和 Lumen:用得好是利器,用不好是灾难

说到 UE5,绕不开 Nanite 和 Lumen 这两个招牌功能。很多人一上来就全开,结果发现帧率崩了,然后骂 UE5 优化差。其实问题不在引擎,在于没理解它们的适用边界。

Nanite 的核心价值是让高面数模型不再需要手动做 LOD,它通过虚拟几何体技术自动处理细节层级。听起来很美好,但它对材质和顶点动画有要求——比如带顶点动画的植被、需要逐顶点变形的角色,Nanite 处理起来就不一定划算。Liquid Swords 在《Samson》里对 Nanite 的使用就是选择性的:静态场景资产用,动态角色和特效不用。这就是零赘余思维——不是“能用就用”,而是“用了有净收益才用”。

Lumen 同理。它提供动态全局光照,省去了烘焙光照的流程,对中小团队来说确实省事。但 Lumen 的性能开销和场景复杂度强相关,如果场景里有大量动态光源或者复杂反射,开销会迅速上升。我的建议是:先明确你的目标帧率和目标硬件,再决定 Lumen 的档位。UE5 提供了 Lumen 的质量分级,从“关闭”到“高”有好几档,中小团队完全可以用中低档配合一些手动的光照技巧来平衡。

这里插一句实操心得:很多人不知道 UE5 的r.Lumen.DiffuseIndirect.Allow和r.Lumen.Reflections.Allow可以分别控制漫反射间接光和反射的开关。如果你发现 Lumen 开销主要来自反射,可以单独关掉反射,保留漫反射 GI,视觉损失不大但性能提升明显。这种细粒度控制就是 UE5 相对其他引擎的优势所在。

2.3 蓝图与 C++ 的分工:别让蓝图变成性能黑洞

UE5 的蓝图系统是双刃剑。它让策划和美术也能参与逻辑搭建,降低了门槛,但滥用蓝图会导致性能问题——尤其是蓝图 Tick 和复杂的蓝图循环。热词里有人搜“ue5 蓝图入门 if 和循环”“ue5 蓝图实现开关门”,说明很多新手正在用蓝图做基础逻辑,这没问题,但要有边界意识。

Liquid Swords 这种有 C++ 背景的团队,通常会采用蓝图做原型、C++ 做落地的策略。蓝图负责快速验证玩法和做编辑器工具,核心逻辑和性能敏感部分用 C++ 实现。这样既保留了迭代速度,又保证了运行时效率。我见过太多项目,蓝图里塞了几百个节点做每帧计算,最后帧率掉到 30 以下才想起来重构,代价极大。

一个具体的判断标准:如果一个蓝图逻辑每帧都在跑,或者涉及大量对象遍历,就应该考虑下沉到 C++。开关门这种一次性触发的逻辑,蓝图完全够用;但如果是每帧检测玩家与上百个交互物的距离,那就该用 C++ 写个管理器。

3. “零赘余”在 UE5 里的落地:从资产规范到性能预算

3.1 先定性能预算,再谈美术表现

零赘余的第一步不是优化,而是定预算。这就像装修房子,你得先知道总共有多少钱,再决定每个房间花多少。游戏开发的性能预算通常包括:帧率目标(比如 60fps)、目标硬件(比如中端显卡)、Draw Call 上限、三角面数上限、内存上限、GPU 时间分配等。

Liquid Swords 在《Samson》的开发中,应该是先锁定了目标平台和帧率,然后倒推每个系统的开销上限。比如角色渲染占多少毫秒、场景占多少、特效占多少、UI 占多少。这个预算表一旦定下来,就成了所有美术和程序决策的依据。美术想加一个高面数道具?可以,但要从别的地方省出来。

我自己的项目里用过一张简单的预算表,分享出来供参考:

系统模块GPU 时间预算(ms)内存预算(MB)备注
角色渲染4.0300含骨骼动画和材质
场景静态物5.0800Nanite 资产为主
特效粒子3.0200含 Niagara
光照与阴影3.5150Lumen 中档
UI 与后期2.0100含 UMG 和后处理
预留余量2.5150应对峰值
合计20.01700对应 50fps 安全线

这张表的意义在于,当有人提出“加个酷炫特效”时,你可以直接问:从哪个模块扣预算?这种量化思维就是零赘余的核心。

3.2 资产规范:命名、目录、引用关系都要管

零赘余不只是运行时的事,更是资产管理的事。一个项目做久了,最怕的就是“不知道哪个资产还在用”“删了一个材质结果十个地方报错”。UE5 的资产引用系统很强大,但前提是你得规范使用。

我建议从项目第一天就定好目录结构和命名规范。比如:

  • /Game/Characters/放角色相关资产,子目录按角色名分
  • /Game/Environment/放场景资产,按区域或类型分
  • /Game/FX/放特效,按功能分
  • /Game/Core/放核心蓝图和 C++ 类
  • /Game/UI/放界面资产

命名上,材质用M_前缀,材质实例用MI_,蓝图用BP_,静态网格用SM_,骨骼网格用SK_。这些是 UE 社区的通用惯例,遵守它们能让团队协作顺畅很多。

更重要的是定期清理未引用资产。UE5 有“Reference Viewer”和“Size Map”工具,可以查看资产的引用关系和磁盘占用。我习惯每两周跑一次 Size Map,看看哪些资产占了大头,有没有可以压缩的纹理、有没有重复的材质。这个习惯帮我省下过好几个 G 的包体。

3.3 材质与着色器:少一个变体就少一份开销

UE5 的材质系统非常灵活,但灵活意味着容易失控。每个材质变体(Material Variant)都会增加着色器编译时间和运行时切换开销。零赘余的做法是:能用材质实例解决的,绝不新建材质;能用参数控制的,绝不写死。

具体来说,一个角色如果有十套皮肤,应该用一个母材质加十个材质实例,而不是十个独立材质。母材质里把颜色、粗糙度、金属度等做成参数,实例里只改参数值。这样着色器只编译一次,运行时切换也快。

还有一个容易被忽略的点是材质里的静态开关。UE5 材质支持 Static Switch 参数,可以在编译期决定走哪个分支。如果你有一个材质要同时用于不透明和半透明物体,用 Static Switch 比用两个材质更高效,因为编译后会生成两个专门的着色器变体,运行时没有分支判断开销。

我踩过的一个坑是:早期为了省事,给每个道具都建了独立材质,结果项目里几百个材质,每次改一个公共参数都要手动改几百次。后来重构成母材质加实例,改一次参数全项目生效,效率提升巨大。这个教训值得每个新手记住。

4. 实操流程:从零搭建一个零赘余的 UE5 项目框架

4.1 项目初始化与插件管理

装完 UE5 之后,第一步不是急着建场景,而是规划项目设置。打开 UE5 新建项目时,模板选择很重要。如果你做的是第一人称或第三人称动作游戏,可以用对应的模板起步,但记得把模板里用不到的内容删掉——模板自带的示例资产、演示关卡、多余输入映射,都是赘余。

插件管理是另一个关键点。UE5 默认开启了不少插件,比如 Paper2D、Android 相关、VR 相关等。如果你的项目用不到,就在 Plugins 面板里关掉。每关一个插件,编辑器启动会快一点,打包体积会小一点。我通常只保留:Enhanced Input(输入系统)、Niagara(特效)、Modeling Tools(建模辅助)、Geometry Script(如果需要程序化生成)。其他按需开启。

项目设置里还有几个必调项:

  • 默认 RHI:Windows 平台用 DX12,因为 Nanite 和 Lumen 需要 DX12。
  • 着色器编译:开启“共享着色器代码”可以减少编译时间。
  • 打包设置:在 Packaging 里勾选“使用 Pak 文件”和“压缩 Pak 文件”,减小包体。

这些设置看起来琐碎,但都是零赘余的基础设施。

4.2 用蓝图搭一个可复用的交互框架

热词里有人问“ue5 蓝图实现开关门”,我就以这个为例,讲一个零赘余的交互框架怎么搭。很多人做开关门是直接在门蓝图里写逻辑:玩家靠近、按键、播放动画、切换碰撞。这样每扇门都要复制一遍逻辑,改起来痛苦。

更好的做法是做一个交互接口(Interaction Interface)加一个交互管理器。接口定义Interact()和CanInteract()两个函数,门、箱子、开关都实现这个接口。管理器负责检测玩家附近的可交互物,并在 UI 上提示。这样新增交互物只需要实现接口,不用改管理器。

具体步骤:

  1. 在 C++ 或蓝图里创建BPI_Interactable接口,定义两个函数。
  2. 创建BP_InteractionManager,在 Tick 里用球形检测找附近实现接口的 Actor,缓存最近的一个。
  3. 玩家按交互键时,管理器调用缓存 Actor 的Interact()。
  4. 门蓝图实现接口,Interact()里播放开门动画、切换碰撞通道。

这个框架的好处是逻辑集中、扩展方便、性能可控。管理器只在玩家移动时做检测,不需要每个可交互物自己 Tick。这就是零赘余——用架构设计消除重复开销。

4.3 网络同步的取舍:不是所有游戏都需要

热词里有“ue5 网络同步”,说明有人在做多人游戏。但我要泼盆冷水:如果你的游戏是单机或者异步交互,不要碰网络同步。网络同步会带来大量额外开销——属性复制、RPC 调用、客户端预测、回滚处理,每一项都是复杂度。

Liquid Swords 的《Samson》从目前信息看应该是单机动作游戏,所以他们大概率没有在网络同步上花精力。这是明智的。零赘余的一个体现就是砍掉不需要的功能。多人游戏很酷,但如果你的核心玩法不需要,加进去只会拖慢开发。

如果确实需要网络同步,UE5 的Replication系统提供了属性复制和 RPC 两种机制。原则是:能少同步就少同步,能低频就低频。比如玩家位置可以高频同步,但血量变化只需要在变化时同步。用Replicated标记属性,用RepNotify处理变化回调,避免每帧轮询。

4.4 打包与性能验证:用数据说话

项目做到一定阶段,一定要做真机性能验证。UE5 编辑器里的帧率不代表打包后的帧率,因为编辑器有很多额外开销。用Unreal Insights或者stat命令可以抓取运行时数据。

我常用的命令:

  • stat unit:看 Game、Draw、GPU 三线程耗时,快速定位瓶颈。
  • stat gpu:看 GPU 各阶段耗时,定位渲染瓶颈。
  • stat memory:看内存占用。
  • Unreal Insights:更详细的性能分析,可以看每帧的调用栈。

打包后如果发现帧率不达标,先看stat unit。如果 Game 线程高,说明逻辑或蓝图有问题;如果 Draw 线程高,说明 Draw Call 太多;如果 GPU 高,说明渲染开销大。对症下药,不要盲目优化。

我自己的经验是,大部分性能问题来自 Game 线程,尤其是蓝图 Tick 和复杂的 Actor 遍历。把这些问题解决掉,帧率往往能提升 30% 以上。

5. 常见问题与排查技巧实录

5.1 UE5 启动慢、编译慢怎么办

这是新手最常问的问题。UE5 启动慢通常是因为着色器编译和资产加载。解决办法:

  • 关闭不用的插件,减少启动时加载的模块。
  • 在项目设置里开启“共享着色器代码”,减少重复编译。
  • 定期清理DerivedDataCache目录,但注意清理后第一次启动会更慢。
  • 如果团队协作,可以用共享的 DDC 服务器,避免每个人重复编译。

编译慢主要是 C++ 项目的问题。开启“Live Coding”可以在编辑器运行时编译 C++ 改动,不用重启。另外,把不常改的代码放到独立的模块里,可以减少增量编译的范围。

5.2 蓝图 Tick 导致帧率下降怎么排查

蓝图 Tick 是性能杀手,但很多人不知道怎么找。UE5 有一个“Blueprint Debugger”和“Stat Blueprints”工具,可以看每个蓝图的执行耗时。更简单的方法是在stat unit里看 Game 线程,如果高,再用stat game看具体是哪些 Actor 在跑 Tick。

我的建议是:默认禁用 Tick,需要时再开。在 Actor 的构造函数里把PrimaryActorTick.bCanEverTick设为 false,然后在需要的时候用SetActorTickEnabled(true)开启。这样能避免大量无意义的 Tick 开销。

5.3 材质变体过多导致打包失败

UE5 打包时如果材质变体太多,可能会编译超时或内存不足。解决办法:

  • 减少 Static Switch 的使用,因为每个 Switch 都会产生变体。
  • 用材质实例代替独立材质。
  • 在项目设置里限制着色器变体数量。
  • 如果某些变体确实不需要,可以在材质里用Quality Level控制。

我遇到过一次打包失败,原因是某个母材质有 5 个 Static Switch,产生了 32 个变体,乘以材质实例数量后爆炸。后来把其中 3 个 Switch 改成运行时参数,变体降到 4 个,打包顺利通过。

5.4 常见问题速查表

问题现象可能原因排查方法解决方向
帧率突然下降蓝图 Tick 过多stat game看耗时禁用不必要 Tick
打包体积过大纹理未压缩Size Map 查看压缩纹理、删未引用资产
着色器编译卡顿变体过多看编译日志减少 Static Switch
内存泄漏对象未释放stat memory观察检查引用和 GC
光照异常Lumen 设置不当看 Lumen 调试视图调整 Lumen 档位
打包失败变体超限看打包日志限制变体数量

5.5 几个我踩过的坑

第一个坑是过早优化。项目初期就纠结每一帧开销,结果玩法还没定型,优化了也白优化。正确做法是:原型阶段放开手脚,玩法确定后再按预算优化。

第二个坑是忽视资产命名规范。早期随便命名,后期找资产靠搜索,效率极低。规范命名是长期收益。

第三个坑是蓝图和 C++ 混用不当。有些逻辑在蓝图里写了一半,又想在 C++ 里改,结果两边不同步。建议明确分工:蓝图做表现和原型,C++ 做核心逻辑,边界清晰。

第四个坑是不重视版本控制。UE5 项目用 Git 需要配置.gitignore和 Git LFS,否则二进制资产会把仓库撑爆。我见过有人把整个Content目录提交到普通 Git,仓库几个 G,克隆一次半小时。用 Perforce 或者配好 LFS 的 Git 才是正解。

6. 从《Samson》看中小团队的 UE5 生存策略

Liquid Swords 用 UE5 做《Samson》,本质上是在“表现力”和“可控性”之间找平衡。他们没有盲目追求 3A 级画面,而是用零赘余的思路,把每一份性能花在刀刃上。这对中小团队来说,比任何技术教程都更有参考价值。

我个人的体会是,UE5 确实强大,但它的强大是“工具箱式”的——工具很多,你得会挑。新手容易犯的错是“什么都想用”,结果项目臃肿。老手的做法是“按需取用”,先明确目标,再选工具。

如果你正在用 UE5 做项目,我建议你从今天开始做三件事:第一,定一份性能预算表,贴在工位上;第二,每周跑一次 Size Map,清理未引用资产;第三,把每帧都在跑的蓝图逻辑检查一遍,能下沉到 C++ 的就下沉。这三件事做完,你的项目会健康很多。

最后分享一个小技巧:UE5 的stat startfile和stat stopfile可以录制性能数据,然后用 Unreal Insights 打开分析。这比凭感觉优化靠谱得多。数据不会骗人,零赘余的前提是知道赘余在哪里。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 10:24:04

Markdown跨平台渲染避坑指南:换行、解析器与工具链实践

我写文档写了快十年,Markdown 语法在我这儿属于“十分钟入门、十年里反复踩坑”的东西。上周又翻了一次车:同一份 md 文件,在 Typora 里排版得干干净净,推到 GitLab 上却整段黏在一起,两个小时没人发现,直到…

作者头像 李华
网站建设 2026/10/2 10:23:54

C++装饰器模式三种落地变体:继承、模板与函数式

聊到 C 里的装饰器模式,我先说结论:它从未从 C 身上离开,只是常常不叫这个名字。很多项目里常见的日志钩子、鉴权包装、请求重试,都是把装饰器模式改头换面后在用。我见过有人为了一段重试逻辑改动核心服务类的构造函数&#xff0…

作者头像 李华
网站建设 2026/10/2 10:22:51

Runtime加载系统架构设计:从分层到热加载的工程实践

1. Runtime加载系统架构到底在解决什么问题第一次看到“Runtime加载系统架构”这个标题,很多人脑子里冒出来的可能是JVM的类加载器、Node.js的模块解析、或者Python的import机制。这些理解都没错,但都只摸到了象腿。Runtime加载系统架构真正要解决的&…

作者头像 李华
网站建设 2026/10/2 10:18:03

从单Agent到AI开发团队:Codex Team Runtime七期复盘

Codex Team Runtime 07,这是我用 Codex 组队开发这个系列的第七篇记录。前六篇文章我分别聊过安装、聊过把单个 Codex 从“会写代码的对话窗口”变成“能持续交付的小团队”,也记录过不少 Runtime 环境的报错和排查过程。到了这一篇,我想把所…

作者头像 李华
网站建设 2026/10/2 10:17:41

MindSpore Transformers实战:LLM预训练全流程指南

做LLM训练最怕什么?不是模型跑不起来,而是同样的模型在PyTorch上能轻松跑到80%的算力利用率,换个框架直接掉到40%。我们团队在Ascend NPU上折腾了大半年,最后把方案定在了MindSpore Transformers上——这个项目现在叫mindformers&…

作者头像 李华