流体系统 用户手册
本文档介绍了本项目中实现的「流体模拟系统」的整体架构,以及各节点的用法和设置项。
使用本系统可以表现粒子无法呈现的无缝轨迹等效果。
示例项目
以下所有示例特效均已包含在示例项目中。
按 F5 运行 game_scene 后,
ZXCV ASDF QWE 键分别对应各种特效,您可以在 player.tscn 的 vs 中查看分配情况。
仅脚本
fluid_system_core.zip (68.0 KB)












- FluidBufferPool(Autoload):通过复用 GPU 缓冲区以维持性能的内部系统。无需直接放置在场景中。
- 流体着色器组(位于
shaders/fluid/内):在 GPU 上执行实际流体计算的着色器文件。无需编辑。
节点①:FluidSimulationController
作用
流体模拟整体的「核心」。它管理 GPU 缓冲区的分配、流体计算以及屏幕渲染等所有流程。请在场景中务必放置一个。
注意:如果在 1 个场景中放置多个,将会为每个实例分配缓冲区,从而占用大量 VRAM。
主要设置项
基本设置
| 项目 | 说明 | 默认值 |
|---|---|---|
auto_fit_to_window |
将模拟区域自动调整为窗口大小。开启后,窗口大小调整时会重新分配所有缓冲区,导致性能尖峰。 | OFF |
use_deferred_init |
将初始化推迟到下一帧。开启后,实例化后的第 1 帧不会渲染。即使在 _ready() 中引用纹理,也会为空。 |
ON |
texture_size |
当 auto_fit_to_window 为 OFF 时的固定分辨率。 |
768×512 |
sim_area_size |
当 auto_fit_to_window 为 OFF 时,流体覆盖的世界空间大小(像素)。设为 (0,0) 时与 texture_size 相同。如果未设置 texture_size 就修改它,FluidEffectNode 的 UV 位置将会错位。 |
(0, 0) |
性能 / 质量
| 项目 | 说明 | 默认值 |
|---|---|---|
simulation_scale |
分辨率比例。1.0 为最高质量,但开销最大。推荐值为 0.5。 | 0.5 |
pressure_iterations |
流体压力计算的精度。数值越高越精细,但 GPU 负载越高。10 左右为宜。 | 10 |
path_bake_resolution |
Path 模式效果节点的方向纹理分辨率(8〜64)。数值越小速度越快。 | 16 |
path_bake_sample_density |
Path 模式下每个曲线点的采样数(1〜8)。 | 4 |
运行设置
| 项目 | 说明 | 默认值 |
|---|---|---|
simulation_active |
设为 OFF 则完全停止计算。视觉效果保持不变。 | ON |
auto_sleep_enabled |
在墨水(Dye)和输入中断后,自动停止计算。有助于节省性能。 | ON |
视觉与发光
| 项目 | 说明 | 默认值 |
|---|---|---|
dye_brightness |
墨水整体的亮度倍率。 | 1.0 |
dye_glow_mode |
发光风格。有「标准发光」和「染料发光」两种。 | 标准发光 |
dye_glow_boost |
发光强度。数值越高看起来越亮。 | 0.0 |
dye_base_ink_opacity |
墨水的不透明度。设为 0 时仅显示发光成分。 | 1.0 |
dye_alpha_gain |
整体不透明度的放大倍率。希望墨水看起来更浓时使用。 | 1.0 |
dye_velocity_visibility_scale |
仅限「染料发光」模式。当 dye_base_ink_opacity 小于 1 时,提高流体高速区域墨水不透明度的强度。数值越大,微弱的移动也能使墨水清晰显现。 |
40.0 |
dye_color_variation_strength |
随时间推移色相波动的强度。0 为无效。 | 0.0 |
dye_color_variation_speed |
色相波动的变化速度。 | 1.3 |
dye_glow_pulse_strength |
发光脉冲式明灭的强度。0 为无效。 | 0.0 |
dye_glow_pulse_speed |
明灭的速度。 | 1.6 |
dye_alpha_cutoff |
低于此值的 Alpha 将被完全裁剪为透明。用于防止垃圾像素。 | 0.04 |
墨水消失设置
| 项目 | 说明 | 默认值 |
|---|---|---|
dye_evaporation |
墨水随时间逐渐变淡的速度。 | (依设定值而定) |
dye_hard_clear_threshold |
当墨水密度低于此值时立即清除。 | 0.06 |
decay_distance_factor |
根据移动距离加速消失的系数。使墨水从尖端迅速消失。0 为无效。 | 0.0 |
decay_velocity_factor |
根据速度加速消失的系数。使高速飞行的墨水散开。0 为无效。 | 0.0 |
流体物理设置
| 项目 | 说明 | 默认值 |
|---|---|---|
viscosity |
粘度。越高流体越粘稠。 | 0.18 |
curl_strength |
涡旋增强的强度。越高产生越复杂的漩涡。 | 28.0 |
curl_idle_scale |
无输入时维持涡旋的程度(0.0〜1.0)。 | 0.08 |
idle_velocity_damping |
无输入时流动的衰减率。1.0 为无衰减。 | 0.975 |
max_velocity |
流动速度的上限值。 | 2.4 |
velocity_floor |
低于此值的速度将被强制视为零。用于提高计算稳定性。 | 0.006 |
pressure_dissipation |
压力的衰减率。降低后反弹力减弱。 | 0.999 |
速度加成的详细控制
通常无需更改。仅在希望微调笔刷的跟随感或喷雾的冲击力时使用。
| 项目 | 说明 | 默认值 |
|---|---|---|
input_velocity_cap_scale |
笔刷移动时墨水速度的上限倍率。提高后笔刷跟随速度变快,但容易结块。 | 10.0 |
input_velocity_add_scale |
笔刷移动时墨水速度加成的基础倍率。 | 1.0 |
outflow_velocity_cap_scale |
喷雾/喷射时墨水速度的上限倍率。 | 2.5 |
outflow_velocity_add_scale |
喷雾/喷射时墨水速度加成的基础倍率。 | 0.8 |
节点②:FluidBrushNode
作用
向流体中注入「墨水」的节点。可设置位置、形状、颜色、强度等。请将其作为 FluidSimulationController 的兄弟节点(同一父节点下)放置。一个模拟中可以放置多个。
注意:放置在 FSC 的子节点或孙节点下无法识别。请务必放置在同一父节点下(作为兄弟节点)。
主要设置项
基本设置
| 项目 | 说明 | 默认值 |
|---|---|---|
emit_mode |
确定注入墨水的位置。Mouse: 鼠标指针位置 / NodeCenter: 本节点自身位置 / TargetNode: 跟随其他节点的位置 | Mouse |
emit_trigger |
注入的时机。Click: 仅点击时 / Always: 持续注入(静止时墨水也会不断流出) / Signal: 仅调用 emit_once() 时 |
Always |
emit_target_path |
TargetNode 模式下跟随的节点路径。 |
- |
笔刷形状
| 项目 | 说明 | 默认值 |
|---|---|---|
brush_shape |
笔刷的基本形状。Circle: 圆形 / Ellipse: 椭圆形 / Texture: 指定纹理的形状 / GlobalTexture: 将单独指定的整个 Viewport 图像作为笔刷 / NodeCapture: 复制指定其他节点的视觉内容作为笔刷 | Circle |
brush_texture |
在 Texture 或 Ellipse 模式下用作笔刷形状的纹理。 | - |
GlobalTexture 专用
| 项目 | 说明 |
|---|---|
global_texture_viewport_path |
捕获的 SubViewport 路径(游戏运行时自动解析)。 |
global_texture_include_hidden |
是否将隐藏节点包含在捕获中。 |
global_texture_use_content_motion |
是否将 Viewport 内的运动作为力传递给流体。 |
NodeCapture 专用
| 项目 | 说明 |
|---|---|
target_node_include_hidden |
即使目标节点隐藏,是否也捕获并反映到流体中。 |
target_node_respect_clip |
如果源节点的祖先设置了 clip_children,是否再现该裁剪边界。如果为 false,则捕获整个节点。 |
笔刷变形 / 角度
| 项目 | 说明 | 默认值 |
|---|---|---|
input_radius |
笔刷半径(相对于整个模拟分辨率的比率,0.0〜1.0)。 | 0.035 |
brush_texture_size_mode |
纹理笔刷分辨率的确定模式。Radius: 根据 input_radius 的比率确定大小 / OriginalPixels: 按原始纹理的像素尺寸直接绘制 |
Radius |
brush_texture_pixel_scale |
OriginalPixels 模式下的额外倍率(1.0 为原倍)。 |
1.0 |
brush_texture_rotation_degrees |
笔刷(纹理)的基本旋转角度(度)。 | 0.0 |
brush_rotation_source |
获取笔刷旋转角度基准的来源。Fixed: 仅使用上述基本旋转角 / ThisNode: 叠加本节点自身的 rotation / NodeCapture: 叠加跟随目标节点的 rotation / RotationNode: 从下方指定的节点叠加 rotation | Fixed |
brush_rotation_node_path |
RotationNode 模式下参考的旋转角度节点路径。 |
- |
pivot_follow_visual_center |
在 NodeCapture 模式下,是否以目标节点 Sprite 偏移等视觉中心为基准进行跟随。开启后旋转时 UV 会正确联动。 | OFF |
brush_flip_h |
水平翻转笔刷纹理。 | OFF |
brush_flip_v |
垂直翻转笔刷纹理。 | OFF |
笔刷蒙版
通过纹理信息过滤笔刷的哪些部分为「有效」。
| 项目 | 说明 | 默认值 |
|---|---|---|
brush_mask_source |
用于蒙版判断的信息类型。Alpha: Alpha 值 / Luminance: 亮度 / Color Range: 与指定颜色的接近程度 / Saturation: 饱和度 | Alpha |
mask_invert |
反转蒙版(黑白反转)。 | OFF |
mask_threshold |
低于此值的淡蒙版将被视为完全透明(所有模式通用)。 | 0.0 |
mask_softness |
蒙版边界的平滑度。0 为清晰,1 为平滑渐变(所有模式通用)。 | 0.1 |
mask_target_color |
Color Range 模式下的抠除基准色。 |
红色 |
mask_color_tolerance |
仅限 Color Range。允许偏离目标颜色的程度(数值越小越严格)。 |
0.3 |
颜色 / 印章
| 项目 | 说明 | 默认值 |
|---|---|---|
emit_dye |
是否注入染料(墨水图像)。设为 false 时,将变为仅产生「流体动力(Force)」的透明笔刷。 | ON |
inject_color_mode |
确定注入颜色的方法。Solid: 纯色(使用 input_color) / Gradient: 应用渐变纹理 / BrushTexture: 直接使用笔刷纹理的颜色 |
Solid |
input_color |
注入染料的基础颜色。 | 偏白的蓝色 |
inject_strength |
单次注入印章的「浓度」。越高颜色越清晰强烈。 | 1.0 |
uniform_paint |
忽略笔刷形状的 Alpha 渐变,使用 inject_strength 在笔刷内进行均匀涂抹。在 BrushTexture 模式下颜色也会变为均匀(白色)。 |
OFF |
inject_blend |
与现有染料的混合方式。0.0 为完全覆盖,1.0 为完全叠加(颜色变白)。 | 0.35 |
edge_hardness |
笔刷外部边缘的清晰度。数值越高边界越锐利。 | 1.25 |
ink_edge_bleed |
在现有墨水上叠加绘制时,新墨水边缘晕染的强度。0.0=无,1.0=最大。对没有现有墨水的地方无影响。 | 0.0 |
渐变专用(仅当 inject_color_mode 为 Gradient 时有效)
| 项目 | 说明 | 默认值 |
|---|---|---|
gradient_mode |
渐变的应用形状。Radial(径向)或 Linear(线性)。 | Radial |
gradient_texture |
用于渐变的纹理(如 ColorRamp 图像等)。 | - |
gradient_rotation_degrees |
渐变基准的旋转角度(度)。 | 0.0 |
gradient_rotation_source |
获取渐变旋转角度的来源(与 brush_rotation_source 选项相同)。 |
Fixed |
gradient_rotation_node_path |
选择 RotationNode 时参考的路径。 |
- |
移动 / 力
| 项目 | 说明 | 默认值 |
|---|---|---|
force_scale |
将笔刷移动量转换为驱动流体的力的倍率。越高移动笔刷时流体被牵引得越强。 | 85.0 |
spread_force_reference |
笔刷输入速度越强,墨水扩散的校正基准值。0 时基于 spray_force_limit 自动计算。 |
0.0 |
spread_force_to_advection_scale |
根据 Force 使染料对流(流动运动)更容易扩散的倍率。增大后快速挥笔时墨水散得更开。0.0 为无效。 | 1.0 |
spread_force_to_diffusion_scale |
根据 Force 增强染料扩散(晕染)的倍率。增大后快速挥笔时墨水更容易模糊。0.0 为无效。 | 0.0 |
喷射 / 喷雾
| 项目 | 说明 | 默认值 |
|---|---|---|
spray_direction_mode |
确定喷射方向的方法。Motion: 鼠标或节点的运动方向 / Fixed: 下方固定向量 / ToTarget: 朝向特定节点 / Velocity: 从节点移动速度计算的方向 | Motion |
spray_profile |
喷射的形状。Cone: 扇形扩散 / Parallel: 平行直线前进 | Cone |
spray_fixed_direction |
Fixed 模式下的固定向量。 |
向右 |
spray_target_path |
ToTarget 模式下朝向的目标节点路径。 |
- |
spray_spread_degrees |
Cone 模式下的扩散角度(度)。180 为全方位(圆形)。 | 85.0 |
spray_force |
喷射的基础强度。设为 0 时不会产生前进方向的喷雾效果(仅单纯跟随移动)。 | 0.0 |
spray_force_limit |
喷射力的上限值。防止流体崩溃。 | 0.25 |
spray_outflow_strength |
从笔刷中心向外辐射的力的强度。 | 0.0 |
spray_velocity_scale |
将节点自身的移动速度叠加到喷射力上的程度。1.0 为完全相乘。 | 0.0 |
spray_keep_last_direction_when_idle |
在 Motion 或 Velocity 模式下,即使移动停止,是否维持最后的喷射方向并继续喷雾。 | ON |
连续绘制
| 项目 | 说明 | 默认值 |
|---|---|---|
continuous_ink_mode |
快速移动鼠标或节点高速移动时,平滑插值绘制笔刷轨迹之间的空隙。关闭后轨迹将变为点状排列。 | ON |
continuous_ink_quality |
插值的质量(分割步数)。越高越平滑,但 GPU 负载增加。推荐 150〜200 左右。过大时高速移动会导致单帧内大量喷溅,造成 GPU 堵塞。 | 150 |
interpolate_rotation |
当 TargetNode 等的旋转角度或缩放比例发生变化时,是否也沿轨迹平滑插值这些变化。 | OFF |
spray_use_direction_sweep |
在连续绘制过程中,是否沿轨迹扫掠喷射方向。 | OFF |
物理 / 衰减
这些参数仅在此笔刷注入时覆盖 FluidSimulationController 的对应参数。用于希望每个笔刷有不同的消失方式时。
| 项目 | 说明 | 默认值 |
|---|---|---|
velocity_dissipation |
速度场(流动动力)的衰减帧率。1.0 为无衰减,越低水流停止得越快。 | 0.995 |
dye_dissipation |
染料(墨水图像)的淡出率。1.0 为无衰减,越低墨水变淡越快。 | 0.985 |
dye_evaporation |
每帧强制削减墨水浓度的值。用于表现水滴等迅速消失的效果。 | 0.12 |
dye_diffusion |
染料扩散(晕染)的强度。越高墨水轮廓像溶于水一样向周围模糊扩散。 | 0.06 |
节点③:FluidEffectNode
作用
向流体施加「力」的节点。可以在指定范围内实现吸入、喷射、涡旋等效果。请将其作为 FluidSimulationController 的兄弟节点放置。
范围设置方法: 在此节点的子节点中添加
CollisionShape2D,并设置 Circle / Rectangle / Capsule 的 Shape。在检查器的「Add Collision Shape」中勾选后,将自动创建半径为 50 的CircleShape2D。如果不存在CollisionShape2D(Path 模式和 Texture 模式除外),则效果不会生效。
主要设置项
力的设置
| 项目 | 说明 | 默认值 |
|---|---|---|
direction |
力的方向。-1.0: 向中心吸入 / 1.0: 从中心喷射 | -1.0(吸入) |
force_mode |
力的应用模式。Radial: 从中心放射状 / Direction: 指定单一方向 / Path: 沿 Path2D 流动 / Texture: 沿纹理梯度方向施力 | Radial |
direction_vector |
Direction 模式下的力的方向(方向向量)。 | 向上 |
path |
Path 模式下使用的 Path2D 路径。 | - |
强度
| 项目 | 说明 | 默认值 |
|---|---|---|
strength |
力的强度。 | 1.0 |
strength_gradient |
从中心到边缘的强度渐变。未设置时为均匀。 | - |
涡旋设置
| 项目 | 说明 | 默认值 |
|---|---|---|
vortex_strength |
涡旋的强度。0 为无效。 | 0.0 |
vortex_direction |
涡旋的旋转方向。1=逆时针,-1=顺时针。 | 1.0 |
pure_vortex |
开启后,将中心方向的力设为零,仅应用涡旋。 | OFF |
显示设置
| 项目 | 说明 | 默认值 |
|---|---|---|
enabled |
设为 OFF 则禁用此节点的效果。 | ON |
节点④:GroupNoiseCaptureViewport
作用
获取指定组内节点(如角色 Sprite 等)的「轮廓」,并生成经噪声削切的纹理。将生成的纹理传递给 FluidBrushNode 的 brush_texture,即可实现「沿角色形状注入墨水」的表现。
用于表现火焰沿身体形状燃烧等效果。
设置方法
-
在场景中放置
GroupNoiseCaptureViewport节点。 -
点击检查器中的「[Editor] 设置所有子节点」按钮。将自动生成所需的子节点。
-
在
target_group中输入要捕获的节点组名(例如:"fluid_capture")。 -
将捕获目标的 Sprite 节点添加到该组中。
-
将同一场景内
FluidBrushNode的brush_shape设置为 GlobalTexture,将global_texture_viewport_path设置为该节点的FinalLayer。即使指定MaskLayer,由于没有颜色信息,也会显示为纯白色。
主要设置项
捕获设置
| 项目 | 说明 | 默认值 |
|---|---|---|
target_group |
要捕获的节点组名。 | “fluid_capture” |
local_scene_only |
仅捕获同一场景(实例)内的节点。关闭后,可以跨场景捕获同组节点。用于希望给其他场景的 Sprite 添加效果时。 | ON |
update_mode |
更新时机。Always: 每帧更新 / Manual: 仅调用 refresh_capture() 时 |
Always |
capture_size |
捕获的大小(像素)。 | 自动(与流体模拟对齐) |
auto_align_to_fluid_simulation |
自动将相机和大小对齐到流体模拟区域。推荐开启。 | ON |
pool_subviewports |
对 SubViewport 进行池化以抑制再生成的尖峰。用于频繁生成/销毁的效果。对于常驻场景(如放置在舞台上的对象),开启此选项无意义。 | OFF |
噪声蒙版设置
| 项目 | 说明 | 默认值 |
|---|---|---|
noise_texture |
用于削切轮廓的噪声纹理。制作类似火焰的凹凸形状。 | - |
tint_color |
输出纹理的颜色乘数值。 | 白色 |
noise_threshold |
噪声阈值。比此值暗的部分将被削切。数值越大轮廓削切越多。 | 0.5 |
noise_edge_hardness |
边界的硬度。越接近 1.0 边界越清晰。 | 0.1 |
noise_scroll_speed |
滚动噪声的速度。制作火焰摇曳的运动。 | (0, -0.5) |
noise_scale |
噪声的 UV 缩放。数值越大图案越细腻。 | 1.0 |
关于性能优化
FluidBufferPool(Autoload)
机制
该系统大量使用 GPU 的 SubViewport。通常,每次生成节点时都分配 GPU 缓冲区会导致卡顿。
FluidBufferPool 作为 Autoload 常驻,通过以子节点形式保持已分配的 GPU 缓冲区并复用,将第二次及之后的生成成本降至零。即使特效场景从树中移除,缓冲区仍保留在 Pool 中。下次生成相同大小/迭代次数的特效时,将直接传递现有缓冲区。
一个 FluidSimulationController 所需的一组缓冲区称为 BufferSet。Pool 通过「使用中 / 空闲」标志管理 BufferSet。
-
acquire(): 如果有空闲 BufferSet 则返回。否则生成新的。
-
release(): 将 BufferSet 标记为「空闲」。不调用
queue_free()。 -
prewarm(): 预先将指定大小的 BufferSet 生成为空闲状态。
即使没有 Autoload 也能运行
如果 FluidBufferPool 不存在于 Autoload 中,各个 FluidSimulationController 和 GroupNoiseCaptureViewport 将切换到作为自身子节点生成 SubViewport 的 fallback 行为。性能会下降,但运行本身没有问题。
设置项
| 项目 | 说明 |
|---|---|
pool_enabled |
设为 false 则完全禁用池化。acquire() 每次都会生成新的,release() 会立即执行 queue_free()。用于在测量池化效果时的基线测量。 |
auto_scan_dirs |
启动时自动扫描的目录列表(res:// 相对路径)。默认为 ["res://effects/"]。递归扫描包含在此处的 .tscn 文件并自动执行 prewarm_from_scene()。 |
prewarm_scenes |
手动注册希望预先确保的特效场景(PackedScene)。 |
prewarm_count |
每个场景确保的套数。如果同时使用多个则增加。 |
Prewarm(预热)详情
prewarm_from_scene(scene, count)
解析 PackedScene,自动检测其中包含的 FluidSimulationController 和 GroupNoiseCaptureViewport 的设置,并预先生成所需的缓冲区。auto_fit_to_window 为 ON 的场景将从当前窗口大小计算。如果在窗口大小确定之前(如 _ready() 的早期阶段)调用,将无法以正确的尺寸确保缓冲区。
GroupNoiseCaptureViewport 的 pool_subviewports 为 OFF 的将被跳过扫描。auto_align_to_fluid_simulation 为 ON 的将自动对齐到前一个检测到的 FluidSimulationController 的大小。
prewarm_gncv(size, group, count)
预先为 GroupNoiseCaptureViewport 生成 SubViewport 对(MaskLayer 和 FinalLayer)。在 prewarm_from_scene 内自动调用。
池容量上限
| 常量 | 值 | 说明 |
|---|---|---|
MAX_FREE_PER_KEY |
8 | 同一大小/迭代次数的空闲 BufferSet 保持上限 |
MAX_FREE_TOTAL |
100 | 所有键合计的空闲 BufferSet 保持上限 |
超出上限的空闲 BufferSet 将被 queue_free()。