GPUParticles2D/3D di Godot 4 — Panduan Lengkap
1. Pendahuluan
Godot 4 menggunakan GPUParticles2D dan GPUParticles3D sebagai node sistem partikel default. Keduanya berjalan sepenuhnya di GPU, sehingga jauh lebih cepat daripada padanan CPU-nya untuk jumlah partikel yang besar. ParticlesMaterial lama dari Godot 3 telah digantikan oleh ParticleProcessMaterial, yang menawarkan kontrol lebih besar atas perilaku partikel.
CPUParticles2D dan CPUParticles3D masih ada sebagai node fallback untuk perangkat yang tidak mendukung GPU compute atau ketika kamu perlu mengakses data partikel individual dari GDScript. Untuk sebagian besar kasus, partikel GPU adalah pilihan yang direkomendasikan.
2. GPUParticles2D vs CPUParticles2D
| Fitur | GPUParticles2D | CPUParticles2D |
|---|---|---|
| Pemrosesan | GPU (compute shader) | CPU (thread utama) |
| Partikel maksimum | 100.000+ secara efisien | ~1.000-5.000 batas praktis |
| Sub-emitter | Ya | Tidak |
| Trail | Ya | Tidak |
| Akses per partikel | Tidak (hanya GPU) | Ya (dari GDScript) |
| Mode kompatibilitas | Membutuhkan Vulkan/Metal/D3D12 | Berfungsi di mana saja |
| Tipe material | ParticleProcessMaterial | Properti bawaan (tanpa material) |
GPUParticles2D secara default. Beralih ke CPUParticles2D hanya jika kamu membutuhkan dukungan renderer Compatibility, perlu membaca posisi partikel di GDScript, atau menargetkan perangkat keras yang sangat lawas.
3. Penyiapan Dasar
Untuk membuat efek partikel dasar, tambahkan sebuah node GPUParticles2D ke scene-mu dan tetapkan sebuah ParticleProcessMaterial padanya. Berikut penyiapan minimal dalam 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)
Properti penting pada node GPUParticles2D itu sendiri:
amount— Jumlah partikel yang hidup pada satu waktu (default: 8)lifetime— Berapa lama tiap partikel hidup dalam detik (default: 1.0)one_shot— Memancarkan sekali lalu berhenti (default: false)explosiveness— 0.0 = aliran kontinu, 1.0 = semua partikel sekaligusrandomness— Offset acak pada timing emisi (0.0-1.0)speed_scale— Pengali untuk kecepatan simulasiemitting— Apakah sistem sedang memancarkan saat ini
4. ParticleProcessMaterial Secara Mendalam
ParticleProcessMaterial mengendalikan bagaimana tiap partikel berperilaku sepanjang masa hidupnya. Semua properti arah menggunakan Vector3, bahkan untuk partikel 2D (komponen Z cukup diabaikan).
Arah & Kecepatan
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
Kecepatan Sudut
Membuat partikel berputar saat bergerak. Berguna untuk serpihan, konfeti, atau dedaunan.
mat.angular_velocity_min = -180.0 # degrees per second mat.angular_velocity_max = 180.0
Skala Sepanjang Masa Hidup
Gunakan sebuah CurveTexture untuk mengubah ukuran partikel sepanjang masa hidupnya:
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
Damping & Attractor
Damping memperlambat partikel seiring waktu, menyimulasikan hambatan udara. Attractor (node terpisah) menarik partikel menuju sebuah titik.
mat.damping_min = 5.0 mat.damping_max = 10.0
5. Gradien Warna
Properti color_ramp pada ParticleProcessMaterial menerima sebuah GradientTexture1D untuk mengubah warna partikel secara mulus sepanjang masa hidupnya. Ini penting untuk efek api, asap, dan sihir yang realistis.
Contoh Gradien Api
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
Untuk partikel berwarna seragam, kamu juga bisa mengatur properti color polos alih-alih gradien:
mat.color = Color(0.2, 0.6, 1.0, 0.8) # Semi-transparent blue
6. Bentuk Emisi
Bentuk emisi menentukan di mana partikel muncul. Diatur melalui emission_shape pada ParticleProcessMaterial.
Point
Semua partikel muncul di titik asal (origin) node. Bentuk default.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT
Sphere / Sphere Surface
Partikel muncul secara acak di dalam sebuah bola (atau hanya pada permukaannya).
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 muncul secara acak di dalam sebuah volume berbentuk persegi panjang.
mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX mat.emission_box_extents = Vector3(100, 10, 0) # Wide and thin
Ring
Partikel muncul dalam bentuk cincin (donat), didefinisikan oleh radius dalam/luar dan tinggi.
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 dengan rentang X yang lebar dan Y yang sempit untuk menciptakan efek setinggi tanah seperti jejak debu atau partikel langkah kaki.
7. Resep Praktis
Api
Gradien oranye-merah, kecepatan ke atas, sedikit sebaran, skala menurun sepanjang masa hidup.
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
Asap
Gradien abu-abu, gerakan naik lambat, sebaran besar, alpha rendah untuk tampilan tipis mengambang.
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
Hujan
Garis biru-putih, gravitasi ke bawah yang kuat, sebaran sempit, jumlah partikel tinggi.
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
Percikan
Kuning-oranye, ledakan eksplosif, kecepatan awal tinggi, masa hidup singkat.
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
Salju
Partikel putih, turun perlahan dan lembut, sebaran lebar, sedikit hanyut 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. Partikel 3D (GPUParticles3D)
GPUParticles3D bekerja identik dengan GPUParticles2D tetapi beroperasi di ruang 3D. ParticleProcessMaterial yang sama digunakan. Perbedaan utama:
- Ketiga sumbu
Vector3aktif (X, Y, Z) - Bentuk emisi bekerja dalam 3D penuh (bola adalah bola nyata, box adalah volume)
- Kamu bisa menggunakan
draw_pass_1dengan sebuahQuadMeshatau mesh kustom untuk partikel billboard - Partikel mesh bisa menggunakan
StandardMaterial3DatauORMMaterial3D
# 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 kustom ke draw_pass_1 dan terapkan sebuah StandardMaterial3D padanya. Setiap partikel akan dirender sebagai salinan mesh tersebut.
9. Sub-Emitter
Godot 4 mendukung sub-emitter untuk efek partikel-di-atas-partikel. Sebuah sub-emitter adalah node GPUParticles2D/GPUParticles3D lain yang memancarkan partikel pada posisi tiap partikel induk. Ini ideal untuk:
- Percikan yang beterbangan dari partikel api
- Jejak asap di belakang ledakan kembang api
- Tetesan cipratan saat tumbukan
- Ledakan sekunder
Cara menyiapkan sub-emitter:
# 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)
Mode sub-emitter:
SUB_EMITTER_CONSTANT— Memancar terus-menerus dari tiap partikel indukSUB_EMITTER_AT_END— Memancar ketika partikel induk matiSUB_EMITTER_AT_COLLISION— Memancar ketika partikel induk bertumbukan
GPUParticles, bukan CPUParticles. Setiap sub-emitter menambah beban GPU, jadi jaga jumlah partikel sub-emitter tetap rendah (4-8 per partikel induk).
10. Tips Performa
-
Tradeoff Amount vs Lifetime:
Total partikel terlihat =
amount. Jika kamu menaikkanlifetime, partikel menumpuk lebih lama. Kurangiamountuntuk mengimbangi, atau naikkan untuk efek yang lebih padat. -
Gunakan Visibility Range (3D):
Atur
visibility_range_endpada GPUParticles3D agar sistem partikel yang jauh berhenti dirender. Ini keuntungan besar untuk dunia terbuka. -
FPS Tetap:
Atur
fixed_fpspada node partikel (mis. 30) untuk membatasi pembaruan simulasi. Partikel tetap terinterpolasi mulus tetapi memakai lebih sedikit waktu GPU. -
One-shot untuk ledakan:
Untuk efek seperti ledakan, gunakan
one_shot = truedenganexplosiveness = 1.0. Node lalu bisa dibebaskan setelah masa hidupnya berakhir. -
Gunakan LOD untuk 3D:
Kombinasikan
visibility_range_begin/enddengan beberapa node partikel pada tingkat detail berbeda untuk efek partikel Level of Detail (LOD). -
Hindari overdraw:
Banyak partikel semi-transparan yang saling tumpang tindih = fill rate yang mahal. Kurangi
amountdan gunakan partikel yang lebih besar dengan alpha lebih rendah sebagai gantinya.
11. Migrasi dari Godot 3 ke 4
Jika kamu memigrasikan proyek dari Godot 3 ke Godot 4, berikut perubahan utama untuk partikel:
| Godot 3 | Godot 4 | Catatan |
|---|---|---|
Particles2D |
GPUParticles2D |
Diganti nama |
Particles (3D) |
GPUParticles3D |
Diganti nama |
ParticlesMaterial |
ParticleProcessMaterial |
Diganti nama dengan fitur baru |
CPUParticles2D |
CPUParticles2D |
Tidak berubah |
CPUParticles |
CPUParticles3D |
Diganti nama untuk kejelasan |
| No sub-emitters | sub_emitter_mode |
Baru di Godot 4 |
| No trails | trail_enabled |
Baru di Godot 4 |
flag_align_y |
particle_flag_align_y |
Properti diganti nama |
ParticlesMaterial di GDScript perlu diperbarui secara manual menjadi ParticleProcessMaterial.
Otomatiskan Efek Partikel dengan MCP Pro
Ingin AI membuatkan efek partikel untukmu? Godot MCP Pro menyertakan alat partikel khusus dengan preset untuk api, asap, hujan, salju, percikan, dan lainnya. Kontrol penuh atas material, gradien, dan bentuk emisi dari satu percakapan.
- create_particles
- set_particle_material
- set_particle_color_gradient
- apply_particle_preset
- get_particle_info