GPUParticles2D/3D no Godot 4 — Guia Completo
1. Introdução
O Godot 4 usa GPUParticles2D e GPUParticles3D como os nós padrão do sistema de partículas. Eles são executados inteiramente na GPU, o que os torna significativamente mais rápidos do que seus equivalentes de CPU para grandes quantidades de partículas. O antigo ParticlesMaterial do Godot 3 foi substituído pelo ParticleProcessMaterial, que oferece mais controle sobre o comportamento das partículas.
CPUParticles2D e CPUParticles3D ainda existem como nós de fallback para dispositivos sem suporte a compute na GPU ou quando você precisa acessar dados de partículas individuais a partir do GDScript. Na maioria dos casos, as partículas de GPU são a escolha recomendada.
2. GPUParticles2D vs. CPUParticles2D
| Recurso | GPUParticles2D | CPUParticles2D |
|---|---|---|
| Processamento | GPU (compute shader) | CPU (thread principal) |
| Máximo de partículas | 100.000+ com eficiência | ~1.000-5.000 como limite prático |
| Sub-emissores | Sim | Não |
| Rastros (trails) | Sim | Não |
| Acesso por partícula | Não (apenas GPU) | Sim (a partir do GDScript) |
| Modo de compatibilidade | Requer Vulkan/Metal/D3D12 | Funciona em qualquer lugar |
| Tipo de material | ParticleProcessMaterial | Propriedades integradas (sem material) |
GPUParticles2D por padrão. Mude para CPUParticles2D apenas se precisar de suporte ao renderizador Compatibility, precisar ler posições de partículas no GDScript ou tiver como alvo hardware muito antigo.
3. Configuração básica
Para criar um efeito de partículas básico, adicione um nó GPUParticles2D à sua cena e atribua a ele um ParticleProcessMaterial. Veja uma configuração mínima em GDScript:
# Create a GPUParticles2D node via code var particles = GPUParticles2D.new() particles.amount = 50 particles.lifetime = 2.0 particles.explosiveness = 0.0 # 0 = continuous, 1 = all at once particles.randomness = 0.5 # Create and assign the material var mat = ParticleProcessMaterial.new() mat.direction = Vector3(0, -1, 0) # Note: uses Vector3 even in 2D mat.initial_velocity_min = 50.0 mat.initial_velocity_max = 100.0 mat.gravity = Vector3(0, 98, 0) particles.process_material = mat add_child(particles)
Propriedades importantes do próprio nó GPUParticles2D:
amount— Número de partículas vivas a qualquer momento (padrão: 8)lifetime— Por quanto tempo cada partícula vive, em segundos (padrão: 1.0)one_shot— Emite uma vez e depois para (padrão: false)explosiveness— 0.0 = fluxo contínuo, 1.0 = todas as partículas de uma vezrandomness— Deslocamento aleatório no tempo de emissão (0.0-1.0)speed_scale— Multiplicador da velocidade da simulaçãoemitting— Se o sistema está emitindo no momento
4. ParticleProcessMaterial em detalhes
O ParticleProcessMaterial controla como cada partícula se comporta ao longo de sua vida. Todas as propriedades direcionais usam Vector3, mesmo para partículas 2D (o componente Z é simplesmente ignorado).
Direção e velocidade
var mat = ParticleProcessMaterial.new() # Direction: normalized vector for initial particle heading mat.direction = Vector3(0, -1, 0) # Upward in 2D (Y is flipped) # Spread: cone angle in degrees (0 = straight line, 180 = hemisphere) mat.spread = 45.0 # Initial velocity: particles spawn with speed in this range mat.initial_velocity_min = 100.0 mat.initial_velocity_max = 200.0 # Gravity: constant acceleration applied every frame mat.gravity = Vector3(0, 98, 0) # Pulls downward in 2D
Velocidade angular
Faz as partículas girarem enquanto se movem. Útil para destroços, confetes ou folhas.
mat.angular_velocity_min = -180.0 # degrees per second mat.angular_velocity_max = 180.0
Escala ao longo da vida
Use uma CurveTexture para alterar o tamanho da partícula ao longo de sua vida:
var curve = Curve.new() curve.add_point(Vector2(0.0, 1.0)) # Full size at birth curve.add_point(Vector2(0.5, 1.2)) # Slightly larger at midlife curve.add_point(Vector2(1.0, 0.0)) # Shrink to nothing at death var curve_tex = CurveTexture.new() curve_tex.curve = curve mat.scale_curve = curve_tex
Amortecimento e atrator
O amortecimento (damping) desacelera as partículas com o tempo, simulando resistência do ar. Atratores (nós separados) puxam as partículas em direção a um ponto.
mat.damping_min = 5.0 mat.damping_max = 10.0
5. Gradientes de cor
A propriedade color_ramp do ParticleProcessMaterial aceita uma GradientTexture1D para alterar suavemente a cor da partícula ao longo de sua vida. Isso é essencial para efeitos realistas de fogo, fumaça e magia.
Exemplo: gradiente de fogo
var gradient = Gradient.new()
gradient.colors = PackedColorArray([
Color(1.0, 1.0, 1.0, 1.0), # White (hot core)
Color(1.0, 1.0, 0.2, 1.0), # Yellow
Color(1.0, 0.5, 0.0, 1.0), # Orange
Color(0.8, 0.1, 0.0, 0.8), # Red
Color(0.2, 0.0, 0.0, 0.0), # Dark red, transparent (fade out)
])
gradient.offsets = PackedFloat32Array([0.0, 0.15, 0.4, 0.7, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = gradient
mat.color_ramp = grad_tex
Você também pode definir uma propriedade color fixa em vez de um gradiente para partículas de cor uniforme:
mat.color = Color(0.2, 0.6, 1.0, 0.8) # Semi-transparent blue
6. Formas de emissão
A forma de emissão determina onde as partículas surgem. Ela é definida por emission_shape no ParticleProcessMaterial.
Point
Todas as partículas surgem na origem do nó. É a forma padrão.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT
Sphere / Sphere Surface
As partículas surgem aleatoriamente dentro de uma esfera (ou apenas em sua superfície).
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE mat.emission_sphere_radius = 50.0 # Surface only: mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE_SURFACE mat.emission_sphere_radius = 50.0
Box
As partículas surgem aleatoriamente dentro de um volume retangular.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX mat.emission_box_extents = Vector3(100, 10, 0) # Wide and thin
Ring
As partículas surgem em uma forma de anel (rosca), definida por raio interno/externo e altura.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_RING mat.emission_ring_radius = 80.0 # Outer radius mat.emission_ring_inner_radius = 60.0 # Inner radius (hole) mat.emission_ring_height = 0.0 # Flat ring mat.emission_ring_axis = Vector3(0, 0, 1) # Ring normal
EMISSION_SHAPE_BOX com uma extensão X larga e Y estreita para criar efeitos rentes ao chão, como trilhas de poeira ou partículas de passos.
7. Receitas práticas
Fogo
Gradiente laranja-avermelhado, velocidade para cima, leve dispersão, escala diminuindo ao longo da vida.
func create_fire() -> GPUParticles2D:
var p = GPUParticles2D.new()
p.amount = 40
p.lifetime = 0.8
p.randomness = 0.3
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, -1, 0)
mat.spread = 15.0
mat.initial_velocity_min = 40.0
mat.initial_velocity_max = 80.0
mat.gravity = Vector3(0, -20, 0) # Slight upward pull
mat.damping_min = 5.0
mat.damping_max = 10.0
# Color ramp: white -> yellow -> orange -> red -> transparent
var grad = Gradient.new()
grad.colors = PackedColorArray([
Color(1, 1, 1, 1), Color(1, 1, 0.2, 1),
Color(1, 0.4, 0, 0.9), Color(0.6, 0.1, 0, 0.4),
Color(0.2, 0, 0, 0)
])
grad.offsets = PackedFloat32Array([0.0, 0.1, 0.35, 0.7, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
mat.color_ramp = grad_tex
# Scale: shrink over time
var curve = Curve.new()
curve.add_point(Vector2(0, 0.8))
curve.add_point(Vector2(0.3, 1.0))
curve.add_point(Vector2(1, 0.0))
var curve_tex = CurveTexture.new()
curve_tex.curve = curve
mat.scale_curve = curve_tex
p.process_material = mat
return p
Fumaça
Gradiente cinza, movimento lento para cima, grande dispersão, alfa baixo para uma aparência esfumaçada.
func create_smoke() -> GPUParticles2D:
var p = GPUParticles2D.new()
p.amount = 25
p.lifetime = 3.0
p.randomness = 0.5
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, -1, 0)
mat.spread = 35.0
mat.initial_velocity_min = 10.0
mat.initial_velocity_max = 30.0
mat.gravity = Vector3(0, -5, 0)
mat.damping_min = 2.0
mat.damping_max = 5.0
mat.angular_velocity_min = -30.0
mat.angular_velocity_max = 30.0
var grad = Gradient.new()
grad.colors = PackedColorArray([
Color(0.6, 0.6, 0.6, 0.0), Color(0.5, 0.5, 0.5, 0.3),
Color(0.4, 0.4, 0.4, 0.2), Color(0.3, 0.3, 0.3, 0.0)
])
grad.offsets = PackedFloat32Array([0.0, 0.15, 0.6, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
mat.color_ramp = grad_tex
# Scale: grow over time (smoke expands)
var curve = Curve.new()
curve.add_point(Vector2(0, 0.3))
curve.add_point(Vector2(0.5, 1.0))
curve.add_point(Vector2(1, 1.5))
var curve_tex = CurveTexture.new()
curve_tex.curve = curve
mat.scale_curve = curve_tex
p.process_material = mat
return p
Chuva
Riscos branco-azulados, forte gravidade para baixo, dispersão estreita, alta contagem de partículas.
func create_rain() -> GPUParticles2D:
var p = GPUParticles2D.new()
p.amount = 200
p.lifetime = 1.0
# Use a box emission to cover the screen width
var mat = ParticleProcessMaterial.new()
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX
mat.emission_box_extents = Vector3(600, 0, 0)
mat.direction = Vector3(0.05, 1, 0) # Slightly angled
mat.spread = 3.0
mat.initial_velocity_min = 400.0
mat.initial_velocity_max = 500.0
mat.gravity = Vector3(0, 200, 0)
var grad = Gradient.new()
grad.colors = PackedColorArray([
Color(0.7, 0.8, 1.0, 0.6), Color(0.7, 0.85, 1.0, 0.4),
Color(0.7, 0.85, 1.0, 0.0)
])
grad.offsets = PackedFloat32Array([0.0, 0.8, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
mat.color_ramp = grad_tex
# Stretch particles to look like streaks
mat.scale_min = 0.5
mat.scale_max = 0.5
p.process_material = mat
return p
Faíscas
Amarelo-alaranjado, explosão repentina, alta velocidade inicial, vida curta.
func create_sparks() -> GPUParticles2D:
var p = GPUParticles2D.new()
p.amount = 30
p.lifetime = 0.5
p.one_shot = true
p.explosiveness = 1.0 # All at once
var mat = ParticleProcessMaterial.new()
mat.direction = Vector3(0, -1, 0)
mat.spread = 180.0 # Full sphere
mat.initial_velocity_min = 150.0
mat.initial_velocity_max = 300.0
mat.gravity = Vector3(0, 200, 0) # Fall quickly
mat.damping_min = 10.0
mat.damping_max = 20.0
var grad = Gradient.new()
grad.colors = PackedColorArray([
Color(1, 1, 0.8, 1), Color(1, 0.7, 0.1, 1),
Color(1, 0.3, 0, 0.5), Color(0.5, 0.1, 0, 0)
])
grad.offsets = PackedFloat32Array([0.0, 0.2, 0.6, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
mat.color_ramp = grad_tex
# Scale: start small, stay small
mat.scale_min = 0.3
mat.scale_max = 0.6
p.process_material = mat
return p
Neve
Partículas brancas, descida lenta e suave, ampla dispersão, leve deriva horizontal.
func create_snow() -> GPUParticles2D:
var p = GPUParticles2D.new()
p.amount = 100
p.lifetime = 5.0
p.randomness = 0.8
var mat = ParticleProcessMaterial.new()
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX
mat.emission_box_extents = Vector3(500, 0, 0)
mat.direction = Vector3(0.1, 1, 0)
mat.spread = 10.0
mat.initial_velocity_min = 20.0
mat.initial_velocity_max = 40.0
mat.gravity = Vector3(0, 10, 0)
mat.damping_min = 1.0
mat.damping_max = 3.0
mat.angular_velocity_min = -45.0
mat.angular_velocity_max = 45.0
var grad = Gradient.new()
grad.colors = PackedColorArray([
Color(1, 1, 1, 0), Color(1, 1, 1, 0.8),
Color(1, 1, 1, 0.7), Color(1, 1, 1, 0)
])
grad.offsets = PackedFloat32Array([0.0, 0.05, 0.8, 1.0])
var grad_tex = GradientTexture1D.new()
grad_tex.gradient = grad
mat.color_ramp = grad_tex
mat.scale_min = 0.3
mat.scale_max = 0.8
p.process_material = mat
return p
8. Partículas 3D (GPUParticles3D)
O GPUParticles3D funciona de forma idêntica ao GPUParticles2D, mas opera no espaço 3D. O mesmo ParticleProcessMaterial é usado. As principais diferenças:
- Todos os 3 eixos de
Vector3ficam ativos (X, Y, Z) - As formas de emissão funcionam em 3D completo (esferas são esferas reais, caixas são volumes)
- Você pode usar
draw_pass_1com umQuadMeshou uma malha personalizada para partículas em billboard - Partículas de malha podem usar
StandardMaterial3DouORMMaterial3D
# 3D fire torch example var particles_3d = GPUParticles3D.new() particles_3d.amount = 60 particles_3d.lifetime = 1.0 var mat = ParticleProcessMaterial.new() mat.direction = Vector3(0, 1, 0) # Upward in 3D mat.spread = 20.0 mat.initial_velocity_min = 1.0 mat.initial_velocity_max = 2.0 mat.gravity = Vector3(0, -0.5, 0) # Slight counter-gravity # Emission from a small sphere mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE mat.emission_sphere_radius = 0.2 particles_3d.process_material = mat # Use a QuadMesh as the particle shape var quad = QuadMesh.new() quad.size = Vector2(0.3, 0.3) particles_3d.draw_pass_1 = quad # Billboard mode: particles always face the camera mat.billboard_mode = BaseMaterial3D.BILLBOARD_ENABLED add_child(particles_3d)
.tres personalizada a draw_pass_1 e aplique um StandardMaterial3D a ela. Cada partícula será renderizada como uma cópia dessa malha.
9. Sub-emissores
O Godot 4 oferece suporte a sub-emissores para efeitos de partícula sobre partícula. Um sub-emissor é outro nó GPUParticles2D/GPUParticles3D que emite partículas na posição de cada partícula pai. Isso é ideal para:
- Faíscas saindo de partículas de fogo
- Rastros de fumaça atrás de explosões de fogos de artifício
- Gotículas de respingo na colisão
- Explosões secundárias
Para configurar sub-emissores:
# 1. Create the sub-emitter node (must be a sibling or child) var sub_sparks = GPUParticles2D.new() sub_sparks.amount = 4 sub_sparks.lifetime = 0.3 sub_sparks.explosiveness = 1.0 sub_sparks.emitting = false # Controlled by parent var sub_mat = ParticleProcessMaterial.new() sub_mat.direction = Vector3(0, -1, 0) sub_mat.spread = 180.0 sub_mat.initial_velocity_min = 50.0 sub_mat.initial_velocity_max = 100.0 sub_sparks.process_material = sub_mat add_child(sub_sparks) # 2. Reference it from the parent material var parent_mat: ParticleProcessMaterial = fire_particles.process_material parent_mat.sub_emitter_mode = ParticleProcessMaterial.SUB_EMITTER_AT_END # Also: SUB_EMITTER_AT_COLLISION, SUB_EMITTER_CONSTANT # 3. Set the sub_emitter property on the parent node fire_particles.sub_emitter = fire_particles.get_path_to(sub_sparks)
Modos de sub-emissor:
SUB_EMITTER_CONSTANT— Emite continuamente de cada partícula paiSUB_EMITTER_AT_END— Emite quando a partícula pai morreSUB_EMITTER_AT_COLLISION— Emite quando a partícula pai colide
GPUParticles, não com CPUParticles. Cada sub-emissor adiciona sobrecarga à GPU, então mantenha baixa a contagem de partículas dos sub-emissores (4-8 por partícula pai).
10. Dicas de desempenho
-
Compromisso entre quantidade e vida:
Total de partículas visíveis =
amount. Se você aumentarlifetime, as partículas se acumulam por mais tempo. Reduzaamountpara compensar, ou aumente-o para efeitos mais densos. -
Use o Visibility Range (3D):
Defina
visibility_range_endno GPUParticles3D para que sistemas de partículas distantes deixem de ser renderizados. Isso traz um grande ganho para mundos abertos. -
FPS fixo:
Defina
fixed_fpsno nó de partículas (por exemplo, 30) para limitar as atualizações da simulação. As partículas ainda interpolam suavemente, mas usam menos tempo de GPU. -
One-shot para rajadas:
Para efeitos do tipo explosão, use
one_shot = truecomexplosiveness = 1.0. O nó pode então ser liberado após o fim da vida. -
Use LOD para 3D:
Combine
visibility_range_begin/endcom vários nós de partículas em diferentes níveis de detalhe para efeitos de partículas com Level of Detail (LOD). -
Evite overdraw:
Muitas partículas semitransparentes sobrepostas = fill rate caro. Reduza
amounte use partículas maiores com alfa mais baixo no lugar.
11. Migração do Godot 3 para o 4
Se você está migrando um projeto do Godot 3 para o Godot 4, aqui estão as principais mudanças relativas às partículas:
| Godot 3 | Godot 4 | Observações |
|---|---|---|
Particles2D |
GPUParticles2D |
Renomeado |
Particles (3D) |
GPUParticles3D |
Renomeado |
ParticlesMaterial |
ParticleProcessMaterial |
Renomeado com novos recursos |
CPUParticles2D |
CPUParticles2D |
Inalterado |
CPUParticles |
CPUParticles3D |
Renomeado para maior clareza |
| No sub-emitters | sub_emitter_mode |
Novo no Godot 4 |
| No trails | trail_enabled |
Novo no Godot 4 |
flag_align_y |
particle_flag_align_y |
Propriedade renomeada |
ParticlesMaterial no GDScript precisarão ser atualizadas manualmente para ParticleProcessMaterial.
Automatize efeitos de partículas com o MCP Pro
Quer que a IA crie efeitos de partículas para você? O Godot MCP Pro inclui ferramentas dedicadas de partículas com presets para fogo, fumaça, chuva, neve, faíscas e muito mais. Controle total sobre materiais, gradientes e formas de emissão a partir de uma única conversa.
- create_particles
- set_particle_material
- set_particle_color_gradient
- apply_particle_preset
- get_particle_info