GPUParticles2D/3D in Godot 4 — Vollständiger Leitfaden
1. Einführung
Godot 4 verwendet GPUParticles2D und GPUParticles3D als standardmäßige Partikelsystem-Nodes. Diese laufen vollständig auf der GPU und sind daher bei großen Partikelmengen deutlich schneller als ihre CPU-Pendants. Das alte ParticlesMaterial aus Godot 3 wurde durch ParticleProcessMaterial ersetzt, das mehr Kontrolle über das Partikelverhalten bietet.
CPUParticles2D und CPUParticles3D existieren weiterhin als Fallback-Nodes für Geräte ohne GPU-Compute-Unterstützung oder wenn du aus GDScript auf einzelne Partikeldaten zugreifen musst. In den meisten Fällen sind GPU-Partikel die empfohlene Wahl.
2. GPUParticles2D vs. CPUParticles2D
| Merkmal | GPUParticles2D | CPUParticles2D |
|---|---|---|
| Verarbeitung | GPU (Compute Shader) | CPU (Haupt-Thread) |
| Max. Partikel | 100.000+ effizient | ~1.000-5.000 praktisches Limit |
| Sub-Emitter | Ja | Nein |
| Trails | Ja | Nein |
| Zugriff pro Partikel | Nein (nur GPU) | Ja (aus GDScript) |
| Kompatibilitätsmodus | Erfordert Vulkan/Metal/D3D12 | Funktioniert überall |
| Materialtyp | ParticleProcessMaterial | Integrierte Eigenschaften (kein Material) |
GPUParticles2D. Wechsle nur dann zu CPUParticles2D, wenn du Unterstützung für den Compatibility-Renderer benötigst, Partikelpositionen in GDScript auslesen musst oder sehr alte Hardware anvisierst.
3. Grundlegende Einrichtung
Um einen einfachen Partikeleffekt zu erstellen, füge deiner Szene einen GPUParticles2D-Node hinzu und weise ihm ein ParticleProcessMaterial zu. Hier ist eine minimale Einrichtung in 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)
Wichtige Eigenschaften des GPUParticles2D-Nodes selbst:
amount— Anzahl der gleichzeitig lebenden Partikel (Standard: 8)lifetime— Wie lange jedes Partikel in Sekunden lebt (Standard: 1.0)one_shot— Einmal emittieren, dann stoppen (Standard: false)explosiveness— 0.0 = kontinuierlicher Strom, 1.0 = alle Partikel auf einmalrandomness— Zufälliger Versatz beim Emissions-Timing (0.0-1.0)speed_scale— Multiplikator für die Simulationsgeschwindigkeitemitting— Ob das System aktuell emittiert
4. ParticleProcessMaterial im Detail
ParticleProcessMaterial steuert, wie sich einzelne Partikel über ihre Lebensdauer verhalten. Alle Richtungseigenschaften verwenden Vector3, selbst bei 2D-Partikeln (die Z-Komponente wird einfach ignoriert).
Richtung & Geschwindigkeit
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
Winkelgeschwindigkeit
Lässt Partikel während der Bewegung rotieren. Nützlich für Trümmer, Konfetti oder Blätter.
mat.angular_velocity_min = -180.0 # degrees per second mat.angular_velocity_max = 180.0
Skalierung über die Lebensdauer
Verwende eine CurveTexture, um die Partikelgröße über ihre Lebensdauer zu verändern:
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
Dämpfung & Attraktor
Dämpfung verlangsamt Partikel im Laufe der Zeit und simuliert Luftwiderstand. Attraktoren (separate Nodes) ziehen Partikel zu einem Punkt.
mat.damping_min = 5.0 mat.damping_max = 10.0
5. Farbverläufe
Die Eigenschaft color_ramp am ParticleProcessMaterial akzeptiert eine GradientTexture1D, um die Partikelfarbe über die Lebensdauer sanft zu verändern. Das ist unverzichtbar für realistische Feuer-, Rauch- und Magieeffekte.
Beispiel: Feuer-Verlauf
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
Für einfarbige Partikel kannst du statt eines Verlaufs auch eine flache color-Eigenschaft setzen:
mat.color = Color(0.2, 0.6, 1.0, 0.8) # Semi-transparent blue
6. Emissionsformen
Die Emissionsform bestimmt, wo Partikel entstehen. Sie wird über emission_shape am ParticleProcessMaterial festgelegt.
Point
Alle Partikel entstehen am Ursprung des Nodes. Standardform.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT
Sphere / Sphere Surface
Partikel entstehen zufällig innerhalb einer Kugel (oder nur auf ihrer Oberfläche).
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
Partikel entstehen zufällig innerhalb eines rechteckigen Volumens.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX mat.emission_box_extents = Vector3(100, 10, 0) # Wide and thin
Ring
Partikel entstehen in einer Ring- (Donut-)Form, definiert durch Innen-/Außenradius und Höhe.
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 mit einer breiten X-Ausdehnung und schmalem Y, um bodennahe Effekte wie Staubfahnen oder Schritt-Partikel zu erzeugen.
7. Praktische Rezepte
Feuer
Orange-roter Verlauf, Geschwindigkeit nach oben, leichte Streuung, über die Lebensdauer abnehmende Skalierung.
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
Rauch
Grauer Verlauf, langsame Aufwärtsbewegung, große Streuung, niedriger Alphawert für ein schleierhaftes Aussehen.
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
Regen
Blau-weiße Streifen, starke Abwärtsschwerkraft, schmale Streuung, hohe Partikelanzahl.
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
Funken
Gelb-orange, explosiver Ausbruch, hohe Anfangsgeschwindigkeit, kurze Lebensdauer.
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
Schnee
Weiße Partikel, langsames sanftes Herabsinken, breite Streuung, leichte horizontale Drift.
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. 3D-Partikel (GPUParticles3D)
GPUParticles3D funktioniert identisch zu GPUParticles2D, arbeitet aber im 3D-Raum. Es wird dasselbe ParticleProcessMaterial verwendet. Die wichtigsten Unterschiede:
- Alle 3 Achsen von
Vector3sind aktiv (X, Y, Z) - Emissionsformen funktionieren in vollem 3D (Kugeln sind echte Kugeln, Boxen sind Volumen)
- Du kannst
draw_pass_1mit einemQuadMeshoder einem eigenen Mesh für Billboard-Partikel verwenden - Mesh-Partikel können
StandardMaterial3DoderORMMaterial3Dverwenden
# 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)
draw_pass_1 ein eigenes .tres-Mesh zu und wende ein StandardMaterial3D darauf an. Jedes Partikel wird als Kopie dieses Meshes gerendert.
9. Sub-Emitter
Godot 4 unterstützt Sub-Emitter für Partikel-auf-Partikel-Effekte. Ein Sub-Emitter ist ein weiterer GPUParticles2D/GPUParticles3D-Node, der an der Position jedes Eltern-Partikels Partikel emittiert. Das ist ideal für:
- Funken, die von Feuerpartikeln wegfliegen
- Rauchfahnen hinter Feuerwerksexplosionen
- Spritzwassertropfen bei Kollision
- Sekundärexplosionen
So richtest du Sub-Emitter ein:
# 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)
Sub-Emitter-Modi:
SUB_EMITTER_CONSTANT— Emittiert kontinuierlich von jedem Eltern-PartikelSUB_EMITTER_AT_END— Emittiert, wenn das Eltern-Partikel stirbtSUB_EMITTER_AT_COLLISION— Emittiert, wenn das Eltern-Partikel kollidiert
GPUParticles, nicht mit CPUParticles. Jeder Sub-Emitter erhöht die GPU-Last, halte die Partikelanzahl von Sub-Emittern daher niedrig (4-8 pro Eltern-Partikel).
10. Performance-Tipps
-
Kompromiss Anzahl vs. Lebensdauer:
Sichtbare Partikel gesamt =
amount. Wenn dulifetimeerhöhst, sammeln sich Partikel länger an. Reduziereamountzum Ausgleich oder erhöhe es für dichtere Effekte. -
Visibility Range nutzen (3D):
Setze
visibility_range_endan GPUParticles3D, damit entfernte Partikelsysteme nicht mehr gerendert werden. Das ist ein großer Gewinn für offene Welten. -
Feste FPS:
Setze
fixed_fpsam Partikel-Node (z. B. 30), um Simulationsaktualisierungen zu begrenzen. Partikel interpolieren weiterhin flüssig, benötigen aber weniger GPU-Zeit. -
One-Shot für Ausbrüche:
Verwende für explosionsartige Effekte
one_shot = truemitexplosiveness = 1.0. Der Node kann dann nach Ablauf der Lebensdauer freigegeben werden. -
LOD für 3D verwenden:
Kombiniere
visibility_range_begin/endmit mehreren Partikel-Nodes auf unterschiedlichen Detailstufen für Level-of-Detail-(LOD-)Partikeleffekte. -
Overdraw vermeiden:
Viele einander überlappende halbtransparente Partikel = teure Fill-Rate. Reduziere
amountund verwende stattdessen größere Partikel mit niedrigerem Alphawert.
11. Migration von Godot 3 zu 4
Wenn du ein Projekt von Godot 3 zu Godot 4 migrierst, sind hier die wichtigsten Änderungen bei den Partikeln:
| Godot 3 | Godot 4 | Hinweise |
|---|---|---|
Particles2D |
GPUParticles2D |
Umbenannt |
Particles (3D) |
GPUParticles3D |
Umbenannt |
ParticlesMaterial |
ParticleProcessMaterial |
Umbenannt mit neuen Funktionen |
CPUParticles2D |
CPUParticles2D |
Unverändert |
CPUParticles |
CPUParticles3D |
Zur Klarheit umbenannt |
| No sub-emitters | sub_emitter_mode |
Neu in Godot 4 |
| No trails | trail_enabled |
Neu in Godot 4 |
flag_align_y |
particle_flag_align_y |
Eigenschaft umbenannt |
ParticlesMaterial-Referenzen in GDScript müssen jedoch manuell auf ParticleProcessMaterial aktualisiert werden.
Partikeleffekte mit MCP Pro automatisieren
Willst du, dass die KI Partikeleffekte für dich erstellt? Godot MCP Pro enthält dedizierte Partikel-Tools mit Presets für Feuer, Rauch, Regen, Schnee, Funken und mehr. Volle Kontrolle über Materialien, Verläufe und Emissionsformen aus einem einzigen Gespräch.
- create_particles
- set_particle_material
- set_particle_color_gradient
- apply_particle_preset
- get_particle_info