Godot 4 GDScript 教程 / 粒子系统(GPUParticles)
粒子系统(GPUParticles)
概述
Godot 4 使用 GPU 加速粒子系统 GPUParticles3D/2D 替代了 Godot 3 中的 CPUParticles,性能大幅提升。粒子通过 ParticleProcessMaterial 配置行为,支持碰撞、吸引子和自定义着色器。
| 节点 | 说明 |
|---|
GPUParticles3D | 3D GPU 粒子 |
GPUParticles2D | 2D GPU 粒子 |
CPUParticles3D | 3D CPU 粒子(兼容设备) |
CPUParticles2D | 2D CPU 粒子(兼容设备) |
⚠️ 注意:GPUParticles 需要支持 Vulkan/OpenGL 3.3+ 的显卡。如果目标平台性能较差,考虑使用 CPUParticles。
GPUParticles3D 基础
基本设置
extends GPUParticles3D
func _ready():
# 粒子数量
amount = 100
# 粒子生命周期(秒)
lifetime = 2.0
# 一次性发射(不循环)
one_shot = false
# 发射速度预热
preprocess = 0.5
# 爆发式发射
explosiveness = 0.0 # 0 = 持续发射,1 = 同时发射
# 随机化
randomness = 0.5
# 是否发射
emitting = true
# 固定 FPS
fixed_fps = 30
ParticleProcessMaterial
粒子材质控制粒子的所有行为参数。
代码创建粒子材质
extends GPUParticles3D
func _ready():
var mat = ParticleProcessMaterial.new()
# 发射方向
mat.direction = Vector3(0, 1, 0)
mat.spread = 45.0 # 扩散角度
# 初始速度
mat.initial_velocity_min = 2.0
mat.initial_velocity_max = 5.0
# 重力
mat.gravity = Vector3(0, -9.8, 0)
# 缩放
mat.scale_min = 0.1
mat.scale_max = 0.3
# 颜色渐变
var gradient = Gradient.new()
gradient.set_color(0, Color(1, 0.8, 0.2, 1)) # 起始:橙色
gradient.set_color(1, Color(1, 0.2, 0, 0)) # 结束:透明红
mat.color_ramp = gradient
# 角速度
mat.angular_velocity_min = -180.0
mat.angular_velocity_max = 180.0
# 阻尼(减速)
mat.damping_min = 1.0
mat.damping_max = 3.0
process_material = mat
amount = 200
lifetime = 3.0
材质参数速查表
| 参数 | 说明 |
|---|
direction | 发射方向 |
spread | 扩散角度(度) |
initial_velocity_min/max | 初始速度范围 |
gravity | 重力向量 |
scale_min/max | 缩放范围 |
color | 颜色 |
color_ramp | 颜色渐变曲线 |
alpha_curve | 透明度曲线 |
damping_min/max | 阻尼(减速) |
angular_velocity_min/max | 角速度 |
linear_accel_min/max | 线性加速度 |
radial_accel_min/max | 径向加速度 |
tangential_accel_min/max | 切线加速度 |
orbit_min/max | 轨道运动 |
发射形状
extends GPUParticles3D
func _ready():
var mat = ParticleProcessMaterial.new()
# 发射形状
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE
mat.emission_sphere_radius = 1.0
# 其他形状选项
# EMISSION_SHAPE_POINT — 点发射
# EMISSION_SHAPE_SPHERE — 球体表面
# EMISSION_SHAPE_SPHERE_VOLUME — 球体体积
# EMISSION_SHAPE_BOX — 盒子
# EMISSION_SHAPE_RING — 环形
# EMISSION_SHAPE_DIRECTED_POINTS — 指向性点阵
process_material = mat
| 形状 | 适用场景 |
|---|
POINT | 集中一点发射(火焰) |
SPHERE | 球形扩散(爆炸) |
BOX | 区域内随机(灰尘、雨) |
RING | 环形发射(光环) |
DIRECTED_POINTS | 沿表面法线发射(毛发) |
粒子碰撞
extends GPUParticles3D
func _ready():
# 启用粒子碰撞
collision_mode = GPUParticles3D.COLLISION_RIGID
# 碰撞弹力
# 通过 ParticleProcessMaterial 的 collision 实现
碰撞高度场
# 添加 GPUParticlesCollisionHeightField3D 节点到场景
# 它会将场景渲染为高度场供粒子碰撞
# 代码中设置
var height_field = GPUParticlesCollisionHeightField3D.new()
height_field.size = Vector3(50, 20, 50)
add_child(height_field)
吸引子 Attractor3D
# GPUParticlesAttractorBox3D — 盒形吸引子
# GPUParticlesAttractorSphere3D — 球形吸引子
# GPUParticlesAttractorVectorField3D — 向量场吸引子
extends GPUParticlesAttractorSphere3D
func _ready():
# 吸引力强度(负值 = 排斥)
strength = 10.0
# 影响半径
# 通过 size 或 radius 设置
# 衰减
attenuation = 2.0 # 距离衰减指数
粒子动画
使用纹理帧动画
extends GPUParticles3D
func _ready():
var mat = ParticleProcessMaterial.new()
# 粒子动画:精灵表(Spritesheet)
# 在 ParticleProcessMaterial 中设置
# 或在着色器中处理 UV 动画
process_material = mat
# 设置 Draw Pass 的 QuadMesh 纹理
var mesh = QuadMesh.new()
mesh.size = Vector2(0.5, 0.5)
draw_pass_1 = mesh
火焰效果实战
extends GPUParticles3D
func _ready():
amount = 150
lifetime = 1.5
explosiveness = 0.0
amount_ratio = 1.0
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, 1, 0)
mat.spread = 15.0
mat.initial_velocity_min = 3.0
mat.initial_velocity_max = 5.0
mat.gravity = Vector3(0, 0.5, 0) # 热气上升
mat.scale_min = 0.3
mat.scale_max = 0.8
mat.damping_min = 2.0
mat.damping_max = 4.0
# 颜色:黄 → 橙 → 红 → 透明
var gradient = Gradient.new()
gradient.set_color(0, Color(1, 1, 0.5, 1))
gradient.set_color(0.3, Color(1, 0.6, 0.1, 0.8))
gradient.set_color(0.7, Color(0.8, 0.2, 0, 0.4))
gradient.set_color(1, Color(0.3, 0.1, 0, 0))
mat.color_ramp = gradient
# 发射形状
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE
mat.emission_sphere_radius = 0.2
process_material = mat
烟雾效果实战
extends GPUParticles3D
func _ready():
amount = 80
lifetime = 4.0
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, 1, 0)
mat.spread = 30.0
mat.initial_velocity_min = 1.0
mat.initial_velocity_max = 2.5
mat.gravity = Vector3(0, 1.5, 0) # 烟雾上升
mat.scale_min = 0.5
mat.scale_max = 1.5
mat.damping_min = 0.5
mat.damping_max = 1.0
# 横向漂移
mat.linear_accel_min = -0.5
mat.linear_accel_max = 0.5
# 灰色渐变
var gradient = Gradient.new()
gradient.set_color(0, Color(0.4, 0.4, 0.4, 0.3))
gradient.set_color(1, Color(0.2, 0.2, 0.2, 0))
mat.color_ramp = gradient
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE
mat.emission_sphere_radius = 0.3
process_material = mat
爆炸效果实战
extends Node3D
@onready var particles: GPUParticles3D = $GPUParticles3D
@onready var debris: GPUParticles3D = $DebrisParticles
func explode():
# 火焰爆发
particles.amount = 300
particles.lifetime = 1.0
particles.explosiveness = 1.0 # 瞬间全部发射
particles.one_shot = true
particles.restart()
# 碎片飞溅
debris.amount = 50
debris.lifetime = 2.0
debris.explosiveness = 1.0
debris.one_shot = true
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, 1, 0)
mat.spread = 180.0
mat.initial_velocity_min = 5.0
mat.initial_velocity_max = 15.0
mat.gravity = Vector3(0, -15, 0)
mat.damping_min = 0.5
mat.damping_max = 1.5
debris.process_material = mat
debris.restart()
# 延迟销毁
await get_tree().create_timer(3.0).timeout
queue_free()
粒子性能优化
| 策略 | 说明 |
|---|
| 减少粒子数量 | 能用 50 个就不用 100 个 |
| 使用 LOD | 远处减少/禁用粒子 |
| 降低 fixed_fps | 设为 15~30 足够 |
| 使用 visibility_aabb | 不可见时停止计算 |
| 合理设置 lifetime | 短生命周期减少同时存在数 |
| 用 CPUParticles 兜底 | 低端设备兼容 |
extends GPUParticles3D
func _ready():
# 设置可见性 AABB(剔除区域)
visibility_aabb = AABB(Vector3(-5, -5, -5), Vector3(10, 10, 10))
# 超出视锥时不计算
💡 提示:如果粒子效果不明显,尝试增大粒子尺寸或调整颜色对比度,而非盲目增加数量。
自定义粒子着色器
# 使用 ShaderMaterial 替代 ParticleProcessMaterial
extends GPUParticles3D
func _ready():
var shader_mat = ShaderMaterial.new()
shader_mat.shader = preload("res://shaders/custom_particle.gdshader")
process_material = shader_mat
// custom_particle.gdshader — 粒子着色器
shader_type particles;
uniform float speed_mult = 1.0;
void start() {
// 初始化粒子
VELOCITY = (EMISSION_TRANSFORM * vec4(0.0, 1.0, 0.0, 0.0)).xyz * speed_mult;
CUSTOM.x = 0.0; // 自定义数据
}
void process() {
// 每帧更新
CUSTOM.x += DELTA / LIFETIME; // 0~1 生命周期进度
VELOCITY.y -= 9.8 * DELTA; // 自定义重力
if (CUSTOM.x >= 1.0) {
ACTIVE = false; // 粒子死亡
}
}
2D 粒子
extends GPUParticles2D
func _ready():
amount = 100
lifetime = 2.0
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, -1, 0) # 向上
mat.spread = 30.0
mat.initial_velocity_min = 50.0
mat.initial_velocity_max = 100.0
mat.gravity = Vector3(0, 200, 0) # 2D 向下重力
mat.scale_min = 0.5
mat.scale_max = 1.5
var gradient = Gradient.new()
gradient.set_color(0, Color(1, 1, 1, 1))
gradient.set_color(1, Color(1, 1, 1, 0))
mat.color_ramp = gradient
process_material = mat
游戏开发场景
| 场景 | 粒子类型 | 参数要点 |
|---|
| 火把火焰 | GPUParticles3D | 黄→红渐变,上升方向 |
| 爆炸 | GPUParticles3D | 爆发式,180° 扩散 |
| 烟雾 | GPUParticles3D | 缓慢上升,大尺寸 |
| 下雨 | GPUParticles2D | Box 发射,高速下落 |
| 魔法特效 | GPUParticles3D | 自定义着色器 + 发光 |
| 落叶 | GPUParticles2D | 随机漂移,旋转 |
| 粒尘/脚印 | GPUParticles3D | 小尺寸,短生命周期 |
⚠️ 常见陷阱
- GPUParticles 需要 Vulkan/OpenGL 3.3+,低端设备用 CPUParticles
one_shot = true 后需要 restart() 重新发射explosiveness = 1.0 表示一次性发射所有粒子,不是瞬间完成- 粒子材质的重力方向是 Vector3,2D 也用 Vector3(忽略 z)
- 大量粒子会严重影响性能,注意监控 FPS
扩展阅读