全部文章
产品动态 · 8 min read

Unreal Engine 版 Numivo Water 抢先一览——以参考照片为准绳评判的电影级海洋、湖泊、水下与洞穴,基于物理的光照与泡沫,以及零配置就能让任何物体漂浮或下沉的 Drop-a-Mesh 浮力。

Illustration of a stylised sea with a floating crate and a sinking statue

简而言之: 我们正在为 Unreal Engine 打造一套水系统,带着两个承诺:看起来对的水——因为光、色与泡沫是物理计算的, 而不是逐场景手工调出来的——以及会行为的水:把任意网格丢到水面上,它就会零配置地正确漂浮、倾覆或下沉。它正在积极开发中。 本文解释它涵盖什么、我们如何用参考照片对自己负责、为何浮力是人人跳过的难点,以及它在工具箱其余部分旁的位置。

风暴巨浪拍碎在岩石海岸上 要超越的标准。留意是什么让它真实:由破碎的浪生出的泡沫、吞噬崖壁的雾霭、贯穿整片涌浪的白冠统计——无一手工放置,全是物理。 这就是我们设下的那道杠。

## 为什么又一套水系统?

大多数游戏水只在恰好一种光照条件下看着极好——商店截图里的那种。移动太阳、切到阴天、把相机放到水线以下一半, 它就散架了。

还有第二个更安静、同样要紧的失败:几乎每套水系统都把漂浮物体当作事后想法。你得到一个船模板、一页浮筒装配说明,以及一个 不言自明的假设——没人会往海里随手丢个箱子。玩家一直在往海里丢箱子。

我们想要两件目前不共存于同一个包里的东西:能熬过任何光照的电影级观感,以及无需任何配置的物理行为。二者都不是靠拧参数 拧到某张截图好看就能达成的——因为截图是单一太阳下的单帧,而只要其中之一改变,凭口味调出来的水就会露出接缝。所以这个项目的 根基不是一张功能清单,而是一场人类无法争辩的验收测试:一张照片。

## 以照片为准绳评判,而非以口味

开发被参考照片所门控,它们带着固定的相机与光照合约——物理光照单位、锁定的色调映射器,以及一套决定通过或不通过 的感知差异度量,而非美术总监当天的心情。

有两张参考照片是正典,它们被特意选为对立:

  • 一片清澈的湖,相机在水线里。 一半空气,一半水,一条起伏的边界,没有伪影带;一片绿色的近岸型水,其颜色随距离加深;岩石上 与上方水面相符的焦散;水下的原木在界面处正确弯折。这一张同时考验折射、水线穿越与水下颜色吸收。
  • 全阴天下的一段风暴海岸。 没有太阳,没有闪光带——大海必须靠柔和的天空反射、去饱和的灰绿、白冠统计以及崖上的雾霭来被读出。 一个浮标以可信的周期与倾角骑着涌浪;行为是验收的一部分,而不只是静止图像。

阴天参考被特意选为两者之一。阳光下的水讨好地球上每一个渲染器——高光闪烁掩盖了众多罪过。把太阳拿走,水就必须仅凭反射粗糙度、 颜色与运动来撑起整帧。那才是诚实的测试,也正是大多数系统悄悄回避的那一个。只在阳光下好看的海洋,是不会发售的。

相机一侧被指定得和水一侧同样严格,因为照片比较只有在相机无法作弊时才公平。这意味着真实的物理光照强度(正午太阳约 100,000 勒克斯, 而非任意的亮度滑块)、固定的曝光,以及每张参考各自固定的色调映射与泛光配置。改一改色调映射器,任何水都能被做得去匹配任何照片 ——这正是色调映射器要最先被钉死的原因。

## Drop-a-Mesh:不做功课也能漂

把任意网格拖到一处 Numivo 水体上,它立刻正确行为——系统自动构建一个物理代理,逐帧从真实波高计算排开体积,并从真实 密度推导漂浮还是下沉。

透过清澈蓝水看到的珊瑚礁 水下是一处地方,而非后期处理。颜色随深度吸收,光以光柱滤下,头顶的界面必须被干净地穿越——湖泊参考的存在,就是要把这三者一次性 都保持诚实。

一根原木漂浮并翻到它的长边。一个箱子起伏。一尊石像下沉。没有装配,没有浮筒摆放,没有脚本。引擎盖之下:

  • 碰撞形状被自动体素化——异步进行,并按资产缓存,所以只发生一次——以测量物体的真实体积;
  • 浮力每帧被物理计算:排开体积对着水的密度;淡水与盐水确有不同(盐水更密,所以同一个箱子在海里比在湖里骑得更高);
  • 漂浮还是下沉来自密度,质量除以代理体积——默认没有“这个该漂吗?”的勾选框,因为默认就是物理;
  • 稳定性会涌现:来自代理体积如何分布。头重的箱子倾覆,龙骨压重的船体自行扶正,一块木板平躺;
  • 漂浮物体回耦到水面——涟漪、尾迹、水线处的一圈泡沫,以及撞击时的溅水效果。

Actor 上有一个用于覆盖的小面板——强制漂浮、强制下沉、一个阻尼滑块、尾迹与溅水开关——但覆盖是缩放物理,而非替换它。强制让一块 巨石漂浮,它仍以正确的周期起伏、留下正确的尾迹;它只是表现得仿佛更轻。这个区别很关键:忽略求解器的强制结果看起来就像粘在平面上 的道具,玩家一眼就会注意到。

设计目标很直白,而且是一场我们想要能现场演示的 demo:有人把二十个随机道具拖到海里,一切就那样行为起来——之前不打开哪怕一个 设置窗口。若那场 demo 需要教程,这个功能就失败了。

## 它涵盖什么

近岸水、开阔海洋、水下与洞穴水潭全都是一等公民——基于谱的波,涌浪与交叉浪分离,来自真正破碎的浪的泡沫,驱动水下光柱 的焦散,以及在电影级效果下的稳定性。

若你在乎水,那些要紧的细节:

  • 波来自海洋学谱(与描述真实海洋所用的相同统计模型),带方向性扩散与可独立控制的涌浪。海况变成一个天气决定——“正在酝酿的 风暴,来自西方的长涌”——而非三十个互不相干、你一直推到看着像风暴为止的滑块。
  • 泡沫不是一张画上去的遮罩。 它诞生于浪真正破碎之处,随时间老化,并在风下拉出条纹。画上去的泡沫是假水最常见的破绽,因为它 不随它本该表示的物理一起运动。
  • 水下是一处真实的地方。 按深度正确的颜色吸收(红先走,然后绿,留下人人从潜水影像里认得的深蓝)、由照亮水底的同一焦散场 推导出的光柱,以及水线处一次没有经典硬伪影带的穿越。
  • 洞穴水潭得到自己的处理——静止或几乎不动的水、滴水的扰动、近乎黑暗中的反射——因为一处平静的室内水潭暴露的失败与开阔海洋 不同。
  • 过场是验收标准,而非事后想法。 表面必须在景深、运动模糊与胶片颗粒之下保持稳定——没有只在加了颗粒后才出现的高光萤火,没有 被慢速相机变成频闪的微光。

## 为什么浮力是人人跳过的部分

观感可以用一个好着色器伪造,但行为不能——令人信服的漂浮与下沉需要一个实时体积估计和一个稳定的求解器,这实实在在地难, 所以大多数系统发一个船预制体就收手。

不那么舒服的工程真相是:漂亮的水着色器是个已解决的问题,而一个通用的浮力求解器不是。伪造一道波的观感是纹理与法线的问题;让一个 任意的、前所未见的网格正确地坐在那道波里,则是一个必须以帧率运行、熬过快速时间步、并且当一块千三角形的岩石遇上风暴涌浪时不炸掉的 物理问题。正是这道鸿沟,让“水”在大多数引擎里意味着“一块你没法交互的漂亮平面”,也让那个可交互的部分——当它存在时——是一艘手工做的船。

弥合这道鸿沟——让行为像观感一样自动——就是这个项目存在的原因,也是它需要参考照片的纪律外加一个真正的求解器、而非一个周末的着色器 活儿的原因。

## 你什么时候能用上?

它作为 Unreal Engine 扩展在开发中,分阶段推出——一个运动学的漂浮预览会先于完整的物理求解器落地,好让场景能被提早填充。 我们不公布日期;参考图像来决定何时算完成。

分阶段是刻意的。一个运动学预览(物体跟随波面而不做完整的力模拟)先到,好让美术能在沉重的求解器仍在加固时丢下网格、填满一片海—— 你远在物理定稿之前就能感受到结果。完整的求解器、自动代理与完整面板随后而来。进展与里程碑出现在公开路线图上,而不是在 发布当天的惊喜里。

它将随之一同发售的工具箱——散布、网格混合、Grids、测量——今天就免费可试。若你想在一个公开水构建出现的那一刻就得到通知,站点上链接的 Discord 就是它会最先被宣布的地方,也是参考图像的通过/不通过对比在发生时被张贴的地方。

## 迷你 FAQ

它会要求 Numivo 的其他工具吗? 不会——它是同一家族里的一个扩展,被设计成独立成立。不过它共享同一条原则:结果在物理上可能之处 一律烘焙成引擎原生数据,好让你拥有你所做的东西。

哪些引擎版本? 当前的 Unreal Engine 5 版本。具体细节会随着扩展接近一个公开构建而落到路线图上,而不是现在承诺、以后修改。

这与引擎内置的水有何不同? 内置水系统强在观感、弱在通用交互——浮力通常是一个独立的、手工调过的组件。这里的全部要点是,观感与 行为都来自单一的、有物理根基的系统,而参考照片这道门在各种光照下把观感保持诚实。

为什么在发布前就宣布? 因为参考照片这套方法本身就是要点。我们宁愿把那道杠公开亮出来、被它衡量,也不愿揭晓一个没人能审视的成品。 这篇文章就是那道杠,白纸黑字——请拿它来要求我们。