GPUParticles2D/3D dans Godot 4 — Guide complet
1. Introduction
Godot 4 utilise GPUParticles2D et GPUParticles3D comme nœuds de système de particules par défaut. Ceux-ci s'exécutent entièrement sur le GPU, ce qui les rend nettement plus rapides que leurs équivalents CPU pour de grandes quantités de particules. L'ancien ParticlesMaterial de Godot 3 a été remplacé par ParticleProcessMaterial, qui offre davantage de contrôle sur le comportement des particules.
CPUParticles2D et CPUParticles3D existent toujours comme nœuds de repli pour les appareils dépourvus de prise en charge du calcul GPU, ou lorsque vous devez accéder aux données de particules individuelles depuis GDScript. Dans la plupart des cas, les particules GPU sont le choix recommandé.
2. GPUParticles2D vs CPUParticles2D
| Caractéristique | GPUParticles2D | CPUParticles2D |
|---|---|---|
| Traitement | GPU (compute shader) | CPU (thread principal) |
| Particules max. | 100 000+ efficacement | ~1 000-5 000 limite pratique |
| Sous-émetteurs | Oui | Non |
| Traînées | Oui | Non |
| Accès par particule | Non (GPU uniquement) | Oui (depuis GDScript) |
| Mode de compatibilité | Nécessite Vulkan/Metal/D3D12 | Fonctionne partout |
| Type de matériau | ParticleProcessMaterial | Propriétés intégrées (pas de matériau) |
GPUParticles2D par défaut. Ne passez à CPUParticles2D que si vous avez besoin de la prise en charge du moteur de rendu Compatibility, de lire les positions des particules en GDScript, ou si vous ciblez du matériel très ancien.
3. Configuration de base
Pour créer un effet de particules simple, ajoutez un nœud GPUParticles2D à votre scène et attribuez-lui un ParticleProcessMaterial. Voici une configuration minimale en 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)
Propriétés clés du nœud GPUParticles2D lui-même :
amount— Nombre de particules vivantes à un instant donné (par défaut : 8)lifetime— Durée de vie de chaque particule en secondes (par défaut : 1.0)one_shot— Émettre une fois puis s'arrêter (par défaut : false)explosiveness— 0.0 = flux continu, 1.0 = toutes les particules d'un couprandomness— Décalage aléatoire du timing d'émission (0.0-1.0)speed_scale— Multiplicateur de la vitesse de simulationemitting— Indique si le système émet actuellement
4. ParticleProcessMaterial en détail
ParticleProcessMaterial contrôle le comportement de chaque particule tout au long de sa durée de vie. Toutes les propriétés directionnelles utilisent Vector3, même pour les particules 2D (la composante Z est simplement ignorée).
Direction et vitesse
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
Vitesse angulaire
Fait tourner les particules pendant leur déplacement. Utile pour les débris, les confettis ou les feuilles.
mat.angular_velocity_min = -180.0 # degrees per second mat.angular_velocity_max = 180.0
Échelle sur la durée de vie
Utilisez une CurveTexture pour faire varier la taille des particules au cours de leur durée de vie :
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
Amortissement et attracteur
L'amortissement ralentit les particules avec le temps, simulant la résistance de l'air. Les attracteurs (nœuds distincts) attirent les particules vers un point.
mat.damping_min = 5.0 mat.damping_max = 10.0
5. Dégradés de couleur
La propriété color_ramp du ParticleProcessMaterial accepte une GradientTexture1D pour faire évoluer en douceur la couleur des particules au cours de leur durée de vie. C'est indispensable pour des effets réalistes de feu, de fumée et de magie.
Exemple : dégradé de feu
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
Pour des particules d'une couleur uniforme, vous pouvez aussi définir une propriété color unie au lieu d'un dégradé :
mat.color = Color(0.2, 0.6, 1.0, 0.8) # Semi-transparent blue
6. Formes d'émission
La forme d'émission détermine où apparaissent les particules. Elle se définit via emission_shape sur le ParticleProcessMaterial.
Point
Toutes les particules apparaissent à l'origine du nœud. Forme par défaut.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT
Sphere / Sphere Surface
Les particules apparaissent aléatoirement à l'intérieur d'une sphère (ou uniquement sur sa surface).
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
Les particules apparaissent aléatoirement à l'intérieur d'un volume rectangulaire.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX mat.emission_box_extents = Vector3(100, 10, 0) # Wide and thin
Ring
Les particules apparaissent en forme d'anneau (donut), défini par un rayon interne/externe et une hauteur.
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 avec une large étendue en X et une faible étendue en Y pour créer des effets au ras du sol, comme des traînées de poussière ou des particules de pas.
7. Recettes pratiques
Feu
Dégradé orange-rouge, vitesse vers le haut, léger éparpillement, échelle décroissante au cours de la durée de vie.
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
Fumée
Dégradé gris, mouvement ascendant lent, large éparpillement, faible alpha pour un aspect vaporeux.
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
Pluie
Traînées bleu-blanc, forte gravité vers le bas, éparpillement étroit, grand nombre de particules.
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
Étincelles
Jaune-orange, éclatement explosif, vitesse initiale élevée, courte durée de vie.
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
Neige
Particules blanches, descente lente et douce, large éparpillement, légère dérive horizontale.
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. Particules 3D (GPUParticles3D)
GPUParticles3D fonctionne à l'identique de GPUParticles2D, mais opère dans l'espace 3D. Le même ParticleProcessMaterial est utilisé. Différences principales :
- Les 3 axes de
Vector3sont actifs (X, Y, Z) - Les formes d'émission fonctionnent en 3D complète (les sphères sont de vraies sphères, les boîtes sont des volumes)
- Vous pouvez utiliser
draw_pass_1avec unQuadMeshou un mesh personnalisé pour des particules en billboard - Les particules de type mesh peuvent utiliser
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 personnalisé à draw_pass_1 et appliquez-lui un StandardMaterial3D. Chaque particule sera rendue comme une copie de ce mesh.
9. Sous-émetteurs
Godot 4 prend en charge les sous-émetteurs pour des effets de particules sur particules. Un sous-émetteur est un autre nœud GPUParticles2D/GPUParticles3D qui émet des particules à la position de chaque particule parente. C'est idéal pour :
- Des étincelles jaillissant des particules de feu
- Des traînées de fumée derrière les explosions de feux d'artifice
- Des gouttelettes d'éclaboussure lors d'une collision
- Des explosions secondaires
Pour configurer des sous-émetteurs :
# 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)
Modes de sous-émetteur :
SUB_EMITTER_CONSTANT— Émet en continu depuis chaque particule parenteSUB_EMITTER_AT_END— Émet lorsque la particule parente meurtSUB_EMITTER_AT_COLLISION— Émet lorsque la particule parente entre en collision
GPUParticles, pas avec CPUParticles. Chaque sous-émetteur augmente la charge GPU ; gardez donc le nombre de particules des sous-émetteurs bas (4-8 par particule parente).
10. Conseils de performance
-
Compromis quantité vs durée de vie :
Total de particules visibles =
amount. Si vous augmentezlifetime, les particules s'accumulent plus longtemps. Réduisezamountpour compenser, ou augmentez-le pour des effets plus denses. -
Utiliser la Visibility Range (3D) :
Définissez
visibility_range_endsur GPUParticles3D pour que les systèmes de particules éloignés cessent d'être rendus. C'est un gain considérable pour les mondes ouverts. -
FPS fixe :
Définissez
fixed_fpssur le nœud de particules (p. ex. 30) pour limiter les mises à jour de la simulation. Les particules continuent d'interpoler en douceur mais consomment moins de temps GPU. -
One-shot pour les éclats :
Pour les effets de type explosion, utilisez
one_shot = trueavecexplosiveness = 1.0. Le nœud peut ensuite être libéré une fois la durée de vie écoulée. -
Utiliser le LOD pour la 3D :
Combinez
visibility_range_begin/endavec plusieurs nœuds de particules à différents niveaux de détail pour des effets de particules à niveau de détail (LOD). -
Éviter le surtracé (overdraw) :
De nombreuses particules semi-transparentes qui se chevauchent = un fill rate coûteux. Réduisez
amountet utilisez plutôt des particules plus grandes avec un alpha plus faible.
11. Migration de Godot 3 vers 4
Si vous migrez un projet de Godot 3 vers Godot 4, voici les principaux changements concernant les particules :
| Godot 3 | Godot 4 | Remarques |
|---|---|---|
Particles2D |
GPUParticles2D |
Renommé |
Particles (3D) |
GPUParticles3D |
Renommé |
ParticlesMaterial |
ParticleProcessMaterial |
Renommé avec de nouvelles fonctionnalités |
CPUParticles2D |
CPUParticles2D |
Inchangé |
CPUParticles |
CPUParticles3D |
Renommé pour plus de clarté |
| No sub-emitters | sub_emitter_mode |
Nouveau dans Godot 4 |
| No trails | trail_enabled |
Nouveau dans Godot 4 |
flag_align_y |
particle_flag_align_y |
Propriété renommée |
ParticlesMaterial dans GDScript devra être mise à jour manuellement vers ParticleProcessMaterial.
Automatiser les effets de particules avec MCP Pro
Vous voulez que l'IA crée des effets de particules à votre place ? Godot MCP Pro inclut des outils de particules dédiés avec des préréglages pour le feu, la fumée, la pluie, la neige, les étincelles et plus encore. Contrôle total sur les matériaux, les dégradés et les formes d'émission depuis une seule conversation.
- create_particles
- set_particle_material
- set_particle_color_gradient
- apply_particle_preset
- get_particle_info