GPUParticles2D/3D w Godot 4 — Kompletny przewodnik
1. Wprowadzenie
Godot 4 używa węzłów GPUParticles2D i GPUParticles3D jako domyślnych węzłów systemu cząsteczkowego. Działają one w całości na GPU, dzięki czemu są znacznie szybsze od swoich odpowiedników procesorowych przy dużej liczbie cząsteczek. Stary ParticlesMaterial z Godot 3 został zastąpiony przez ParticleProcessMaterial, który daje większą kontrolę nad zachowaniem cząsteczek.
CPUParticles2D i CPUParticles3D nadal istnieją jako węzły awaryjne dla urządzeń bez obsługi obliczeń na GPU lub gdy musisz uzyskać dostęp do danych poszczególnych cząsteczek z poziomu GDScript. W większości przypadków zalecanym wyborem są cząsteczki GPU.
2. GPUParticles2D vs CPUParticles2D
| Cecha | GPUParticles2D | CPUParticles2D |
|---|---|---|
| Przetwarzanie | GPU (compute shader) | CPU (wątek główny) |
| Maks. cząsteczek | 100 000+ wydajnie | ~1 000-5 000 praktyczny limit |
| Sub-emittery | Tak | Nie |
| Smugi (trails) | Tak | Nie |
| Dostęp do pojedynczej cząsteczki | Nie (tylko GPU) | Tak (z GDScript) |
| Tryb kompatybilności | Wymaga Vulkan/Metal/D3D12 | Działa wszędzie |
| Typ materiału | ParticleProcessMaterial | Wbudowane właściwości (bez materiału) |
GPUParticles2D. Przełącz się na CPUParticles2D tylko wtedy, gdy potrzebujesz obsługi renderera Compatibility, musisz odczytywać pozycje cząsteczek w GDScript lub kierujesz produkt na bardzo stary sprzęt.
3. Podstawowa konfiguracja
Aby stworzyć prosty efekt cząsteczkowy, dodaj do sceny węzeł GPUParticles2D i przypisz mu ParticleProcessMaterial. Oto minimalna konfiguracja w 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)
Kluczowe właściwości samego węzła GPUParticles2D:
amount— Liczba cząsteczek żywych w danej chwili (domyślnie: 8)lifetime— Jak długo żyje każda cząsteczka w sekundach (domyślnie: 1.0)one_shot— Emituj raz, potem zatrzymaj (domyślnie: false)explosiveness— 0.0 = ciągły strumień, 1.0 = wszystkie cząsteczki narazrandomness— Losowe przesunięcie czasu emisji (0.0-1.0)speed_scale— Mnożnik prędkości symulacjiemitting— Czy system aktualnie emituje
4. ParticleProcessMaterial w szczegółach
ParticleProcessMaterial steruje tym, jak poszczególne cząsteczki zachowują się przez cały swój czas życia. Wszystkie właściwości kierunkowe używają Vector3, nawet dla cząsteczek 2D (składowa Z jest po prostu ignorowana).
Kierunek i prędkość
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
Prędkość kątowa
Sprawia, że cząsteczki obracają się podczas ruchu. Przydatne dla odłamków, konfetti czy liści.
mat.angular_velocity_min = -180.0 # degrees per second mat.angular_velocity_max = 180.0
Skala w czasie życia
Użyj CurveTexture, aby zmieniać rozmiar cząsteczki w trakcie jej życia:
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
Tłumienie i atraktor
Tłumienie spowalnia cząsteczki w czasie, symulując opór powietrza. Atraktory (osobne węzły) przyciągają cząsteczki do wybranego punktu.
mat.damping_min = 5.0 mat.damping_max = 10.0
5. Gradienty kolorów
Właściwość color_ramp w ParticleProcessMaterial przyjmuje GradientTexture1D, aby płynnie zmieniać kolor cząsteczki w trakcie jej życia. Jest to niezbędne dla realistycznych efektów ognia, dymu i magii.
Przykład: gradient ognia
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
Dla cząsteczek o jednolitym kolorze zamiast gradientu możesz ustawić także płaską właściwość color:
mat.color = Color(0.2, 0.6, 1.0, 0.8) # Semi-transparent blue
6. Kształty emisji
Kształt emisji określa, gdzie powstają cząsteczki. Ustawia się go za pomocą emission_shape w ParticleProcessMaterial.
Point
Wszystkie cząsteczki powstają w punkcie początkowym węzła. Kształt domyślny.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT
Sphere / Sphere Surface
Cząsteczki powstają losowo wewnątrz sfery (lub tylko na jej powierzchni).
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
Cząsteczki powstają losowo wewnątrz prostopadłościennej objętości.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX mat.emission_box_extents = Vector3(100, 10, 0) # Wide and thin
Ring
Cząsteczki powstają w kształcie pierścienia (donutu), definiowanego przez promień wewnętrzny/zewnętrzny oraz wysokość.
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 z szerokim rozmiarem X i wąskim Y, aby tworzyć efekty przy podłożu, takie jak smugi kurzu czy cząsteczki kroków.
7. Praktyczne przepisy
Ogień
Pomarańczowo-czerwony gradient, prędkość skierowana w górę, niewielkie rozproszenie, malejąca skala w czasie życia.
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
Dym
Szary gradient, powolny ruch w górę, duże rozproszenie, niska wartość alpha dla mglistego wyglądu.
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
Deszcz
Niebiesko-białe smugi, silna grawitacja w dół, wąskie rozproszenie, duża liczba cząsteczek.
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
Iskry
Żółto-pomarańczowe, wybuchowy wyrzut, wysoka prędkość początkowa, krótki czas życia.
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
Śnieg
Białe cząsteczki, powolne, łagodne opadanie, szerokie rozproszenie, niewielki dryf poziomy.
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. Cząsteczki 3D (GPUParticles3D)
GPUParticles3D działa identycznie jak GPUParticles2D, ale operuje w przestrzeni 3D. Używany jest ten sam ParticleProcessMaterial. Najważniejsze różnice:
- Wszystkie 3 osie
Vector3są aktywne (X, Y, Z) - Kształty emisji działają w pełnym 3D (sfery są prawdziwymi sferami, boksy są objętościami)
- Możesz użyć
draw_pass_1zQuadMeshlub własną siatką dla cząsteczek typu billboard - Cząsteczki z siatką mogą używać
StandardMaterial3DlubORMMaterial3D
# 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 do draw_pass_1 i zastosuj na niej StandardMaterial3D. Każda cząsteczka zostanie wyrenderowana jako kopia tej siatki.
9. Sub-emittery
Godot 4 obsługuje sub-emittery dla efektów cząsteczka-na-cząsteczkę. Sub-emitter to kolejny węzeł GPUParticles2D/GPUParticles3D, który emituje cząsteczki w miejscu każdej cząsteczki nadrzędnej. Jest to idealne do:
- Iskier odlatujących od cząsteczek ognia
- Smug dymu za wybuchami fajerwerków
- Kropli rozprysku przy kolizji
- Wtórnych eksplozji
Aby skonfigurować sub-emittery:
# 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)
Tryby sub-emittera:
SUB_EMITTER_CONSTANT— Emituje w sposób ciągły z każdej cząsteczki nadrzędnejSUB_EMITTER_AT_END— Emituje, gdy cząsteczka nadrzędna umieraSUB_EMITTER_AT_COLLISION— Emituje, gdy cząsteczka nadrzędna zderza się
GPUParticles, a nie z CPUParticles. Każdy sub-emitter zwiększa obciążenie GPU, dlatego utrzymuj niską liczbę cząsteczek sub-emitterów (4-8 na cząsteczkę nadrzędną).
10. Wskazówki wydajnościowe
-
Kompromis między liczbą a czasem życia:
Łączna liczba widocznych cząsteczek =
amount. Jeśli zwiększyszlifetime, cząsteczki kumulują się dłużej. Zmniejszamount, aby to zrównoważyć, lub zwiększ go, by uzyskać gęstsze efekty. -
Używaj Visibility Range (3D):
Ustaw
visibility_range_endna GPUParticles3D, aby odległe systemy cząsteczkowe przestały być renderowane. To duży zysk w otwartych światach. -
Stałe FPS:
Ustaw
fixed_fpsna węźle cząsteczek (np. 30), aby ograniczyć aktualizacje symulacji. Cząsteczki nadal będą płynnie interpolowane, ale zużyją mniej czasu GPU. -
One-shot dla wyrzutów:
Dla efektów przypominających eksplozje użyj
one_shot = truewraz zexplosiveness = 1.0. Węzeł można wtedy zwolnić po zakończeniu czasu życia. -
Używaj LOD dla 3D:
Połącz
visibility_range_begin/endz wieloma węzłami cząsteczek na różnych poziomach szczegółowości, aby uzyskać efekty cząsteczkowe z poziomem detali (LOD). -
Unikaj overdraw:
Wiele nakładających się półprzezroczystych cząsteczek = kosztowny fill rate. Zmniejsz
amounti zamiast tego użyj większych cząsteczek o niższej wartości alpha.
11. Migracja z Godot 3 do 4
Jeśli migrujesz projekt z Godot 3 do Godot 4, oto najważniejsze zmiany dotyczące cząsteczek:
| Godot 3 | Godot 4 | Uwagi |
|---|---|---|
Particles2D |
GPUParticles2D |
Zmieniona nazwa |
Particles (3D) |
GPUParticles3D |
Zmieniona nazwa |
ParticlesMaterial |
ParticleProcessMaterial |
Zmieniona nazwa wraz z nowymi funkcjami |
CPUParticles2D |
CPUParticles2D |
Bez zmian |
CPUParticles |
CPUParticles3D |
Zmieniona nazwa dla jasności |
| No sub-emitters | sub_emitter_mode |
Nowość w Godot 4 |
| No trails | trail_enabled |
Nowość w Godot 4 |
flag_align_y |
particle_flag_align_y |
Zmieniona nazwa właściwości |
ParticlesMaterial w GDScript trzeba ręcznie zaktualizować na ParticleProcessMaterial.
Automatyzuj efekty cząsteczkowe z MCP Pro
Chcesz, aby AI tworzyła dla Ciebie efekty cząsteczkowe? Godot MCP Pro zawiera dedykowane narzędzia do cząsteczek z gotowymi ustawieniami dla ognia, dymu, deszczu, śniegu, iskier i innych. Pełna kontrola nad materiałami, gradientami i kształtami emisji w ramach jednej rozmowy.
- create_particles
- set_particle_material
- set_particle_color_gradient
- apply_particle_preset
- get_particle_info