Godot 4'te GPUParticles2D/3D — Eksiksiz Rehber

1. Giriş

Godot 4, varsayılan parçacık sistemi node'ları olarak GPUParticles2D ve GPUParticles3D kullanır. Bunlar tamamen GPU üzerinde çalışır, bu da onları büyük parçacık sayılarında CPU karşılıklarına göre önemli ölçüde hızlı kılar. Godot 3'teki eski ParticlesMaterial, parçacık davranışı üzerinde daha fazla kontrol sunan ParticleProcessMaterial ile değiştirilmiştir.

CPUParticles2D ve CPUParticles3D, GPU compute desteği olmayan cihazlar için veya GDScript'ten tek tek parçacık verilerine erişmeniz gerektiğinde yedek node'lar olarak hâlâ mevcuttur. Çoğu kullanım durumunda GPU parçacıkları önerilen seçenektir.

2. GPUParticles2D ve CPUParticles2D

Özellik GPUParticles2D CPUParticles2D
İşleme GPU (compute shader) CPU (ana iş parçacığı)
Maks. parçacık 100.000+ verimli şekilde ~1.000-5.000 pratik sınır
Alt yayıcılar Evet Hayır
İzler (Trails) Evet Hayır
Parçacık başına erişim Hayır (yalnızca GPU) Evet (GDScript'ten)
Uyumluluk modu Vulkan/Metal/D3D12 gerektirir Her yerde çalışır
Materyal tipi ParticleProcessMaterial Yerleşik özellikler (materyal yok)
İpucu: Varsayılan olarak GPUParticles2D kullanın. Yalnızca Compatibility renderer desteğine ihtiyacınız varsa, parçacık konumlarını GDScript'te okumanız gerekiyorsa veya çok eski donanımı hedefliyorsanız CPUParticles2D'ye geçin.

3. Temel Kurulum

Temel bir parçacık efekti oluşturmak için sahnenize bir GPUParticles2D node'u ekleyin ve ona bir ParticleProcessMaterial atayın. İşte GDScript'te minimal bir kurulum:

# 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)

GPUParticles2D node'unun kendisindeki önemli özellikler:

  • amountHerhangi bir anda canlı olan parçacık sayısı (varsayılan: 8)
  • lifetimeHer parçacığın saniye cinsinden ne kadar yaşadığı (varsayılan: 1.0)
  • one_shotBir kez yay, sonra dur (varsayılan: false)
  • explosiveness0.0 = sürekli akış, 1.0 = tüm parçacıklar bir anda
  • randomnessEmisyon zamanlamasına rastgele kaydırma (0.0-1.0)
  • speed_scaleSimülasyon hızı için çarpan
  • emittingSistemin şu anda yayım yapıp yapmadığı

4. ParticleProcessMaterial'e Derinlemesine Bakış

ParticleProcessMaterial, tek tek parçacıkların yaşam süreleri boyunca nasıl davrandığını kontrol eder. Tüm yön özellikleri, 2D parçacıklarda bile Vector3 kullanır (Z bileşeni yalnızca yok sayılır).

Yön & Hız

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

Açısal Hız

Parçacıkları hareket ederken döndürür. Enkaz, konfeti veya yapraklar için kullanışlıdır.

mat.angular_velocity_min = -180.0  # degrees per second
mat.angular_velocity_max = 180.0

Yaşam Süresi Boyunca Ölçekleme

Parçacık boyutunu yaşam süresi boyunca değiştirmek için bir CurveTexture kullanın:

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

Sönümleme & Çekici (Attractor)

Sönümleme, parçacıkları zamanla yavaşlatarak hava direncini simüle eder. Çekiciler (ayrı node'lar) parçacıkları bir noktaya doğru çeker.

mat.damping_min = 5.0
mat.damping_max = 10.0

5. Renk Geçişleri

ParticleProcessMaterial üzerindeki color_ramp özelliği, parçacık rengini yaşam süresi boyunca yumuşakça değiştirmek için bir GradientTexture1D kabul eder. Bu, gerçekçi ateş, duman ve büyü efektleri için vazgeçilmezdir.

Örnek: Ateş Geçişi

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
İpucu: Parçacıkların aniden ortadan kaybolmak yerine yumuşakça kaybolması için geçişinizi her zaman alfa = 0 ile bitirin.

Tek renkli parçacıklar için bir geçiş yerine düz bir color özelliği de ayarlayabilirsiniz:

mat.color = Color(0.2, 0.6, 1.0, 0.8)  # Semi-transparent blue

6. Emisyon Şekilleri

Emisyon şekli, parçacıkların nerede oluşacağını belirler. ParticleProcessMaterial üzerindeki emission_shape ile ayarlanır.

Point

Tüm parçacıklar node'un başlangıç noktasında oluşur. Varsayılan şekil.

mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_POINT

Sphere / Sphere Surface

Parçacıklar bir kürenin içinde (veya yalnızca yüzeyinde) rastgele oluşur.

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

Parçacıklar dikdörtgen bir hacim içinde rastgele oluşur.

mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX
mat.emission_box_extents = Vector3(100, 10, 0)  # Wide and thin

Ring

Parçacıklar iç/dış yarıçap ve yükseklikle tanımlanan bir halka (simit) şeklinde oluşur.

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
İpucu: Toz izleri veya ayak sesi parçacıkları gibi zemin seviyesindeki efektleri oluşturmak için EMISSION_SHAPE_BOX'ı geniş X ve dar Y ölçüsüyle birleştirin.

7. Pratik Tarifler

Ateş

Turuncu-kırmızı geçiş, yukarı yönlü hız, hafif yayılma, yaşam süresi boyunca azalan ölçek.

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

Duman

Gri geçiş, yavaş yukarı hareket, geniş yayılma, tülümsü bir görünüm için düşük alfa.

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

Yağmur

Mavi-beyaz çizgiler, güçlü aşağı yönlü yer çekimi, dar yayılma, yüksek parçacık sayısı.

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

Kıvılcımlar

Sarı-turuncu, patlayıcı ani çıkış, yüksek başlangıç hızı, kısa yaşam süresi.

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

Kar

Beyaz parçacıklar, yavaş ve nazik iniş, geniş yayılma, hafif yatay sürüklenme.

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 Parçacıklar (GPUParticles3D)

GPUParticles3D, GPUParticles2D ile aynı şekilde çalışır ama 3D uzayda işlem yapar. Aynı ParticleProcessMaterial kullanılır. Önemli farklar:

  • Vector3'ün 3 ekseni de etkindir (X, Y, Z)
  • Emisyon şekilleri tam 3D'de çalışır (küreler gerçek küredir, kutular hacimdir)
  • Billboard parçacıkları için draw_pass_1'i bir QuadMesh veya özel bir mesh ile kullanabilirsiniz
  • Mesh parçacıkları StandardMaterial3D veya ORMMaterial3D kullanabilir
# 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)
İpucu: Mesh parçacıkları (enkaz, kovan, parçalar) için draw_pass_1'e özel bir .tres mesh atayın ve ona bir StandardMaterial3D uygulayın. Her parçacık, o mesh'in bir kopyası olarak render edilir.

9. Alt Yayıcılar

Godot 4, parçacık-üstüne-parçacık efektleri için alt yayıcıları destekler. Bir alt yayıcı, her ana parçacığın konumunda parçacık yayan başka bir GPUParticles2D/GPUParticles3D node'udur. Şunlar için idealdir:

  • Ateş parçacıklarından fırlayan kıvılcımlar
  • Havai fişek patlamalarının arkasındaki duman izleri
  • Çarpışmada sıçrayan damlacıklar
  • İkincil patlamalar

Alt yayıcıları kurmak için:

# 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)

Alt yayıcı modları:

  • SUB_EMITTER_CONSTANTHer ana parçacıktan sürekli olarak yayar
  • SUB_EMITTER_AT_ENDAna parçacık öldüğünde yayar
  • SUB_EMITTER_AT_COLLISIONAna parçacık çarpıştığında yayar
Uyarı: Alt yayıcılar yalnızca GPUParticles ile çalışır, CPUParticles ile değil. Her alt yayıcı GPU yükünü artırır, bu nedenle alt yayıcıların parçacık sayısını düşük tutun (ana parçacık başına 4-8).

10. Performans İpuçları

  • Miktar - Yaşam süresi dengesi: Toplam görünür parçacık = amount. lifetime'ı artırırsanız parçacıklar daha uzun süre birikir. Dengelemek için amount'u azaltın veya daha yoğun efektler için artırın.
  • Visibility Range kullanın (3D): GPUParticles3D üzerinde visibility_range_end ayarlayın, böylece uzaktaki parçacık sistemleri render edilmeyi durdurur. Bu, açık dünyalar için büyük bir kazançtır.
  • Sabit FPS: Simülasyon güncellemelerini sınırlamak için parçacık node'unda fixed_fps ayarlayın (ör. 30). Parçacıklar yine akıcı şekilde enterpolasyon yapar ama daha az GPU zamanı kullanır.
  • Patlamalar için One-shot: Patlama benzeri efektler için one_shot = true'yu explosiveness = 1.0 ile kullanın. Node, yaşam süresi bittikten sonra serbest bırakılabilir.
  • 3D için LOD kullanın: Ayrıntı Düzeyi (LOD) parçacık efektleri için visibility_range_begin/end'i farklı ayrıntı düzeylerindeki birden fazla parçacık node'uyla birleştirin.
  • Overdraw'dan kaçının: Birbiriyle örtüşen çok sayıda yarı saydam parçacık = pahalı dolgu hızı (fill rate). amount'u azaltın ve bunun yerine daha düşük alfaya sahip daha büyük parçacıklar kullanın.

11. Godot 3'ten 4'e Geçiş

Bir projeyi Godot 3'ten Godot 4'e taşıyorsanız, parçacıklarla ilgili önemli değişiklikler şunlardır:

Godot 3 Godot 4 Notlar
Particles2D GPUParticles2D Yeniden adlandırıldı
Particles (3D) GPUParticles3D Yeniden adlandırıldı
ParticlesMaterial ParticleProcessMaterial Yeni özelliklerle yeniden adlandırıldı
CPUParticles2D CPUParticles2D Değişmedi
CPUParticles CPUParticles3D Açıklık için yeniden adlandırıldı
No sub-emitters sub_emitter_mode Godot 4'te yeni
No trails trail_enabled Godot 4'te yeni
flag_align_y particle_flag_align_y Özellik yeniden adlandırıldı
İpucu: Godot'un proje dönüştürücüsü çoğu yeniden adlandırmayı otomatik olarak halleder. Ancak GDScript'teki tüm ParticlesMaterial referanslarının manuel olarak ParticleProcessMaterial'e güncellenmesi gerekir.

Parçacık Efektlerini MCP Pro ile Otomatikleştirin

Parçacık efektlerini yapay zekânın sizin için oluşturmasını mı istiyorsunuz? Godot MCP Pro; ateş, duman, yağmur, kar, kıvılcım ve daha fazlası için hazır ayarlarla birlikte özel parçacık araçları içerir. Materyaller, geçişler ve emisyon şekilleri üzerinde tek bir sohbetten tam kontrol.

  • create_particles
  • set_particle_material
  • set_particle_color_gradient
  • apply_particle_preset
  • get_particle_info
MCP Pro'yu Edinin — $15