Bloga Dön

Godot 4.7 Yeni Özellikleri Tanıtıldı: Dev3 ve Dev4 Performans Güncellemelerinin İçyüzü

Yayınlanma tarihi 14 Nisan 2026
Godot 4.7 Yeni Özellikleri Tanıtıldı: Dev3 ve Dev4 Performans Güncellemelerinin İçyüzü

Godot 4.7 Yeni Özellikleri Tanıtıldı: Dev3 ve Dev4 Performans Güncellemelerinin İçyüzü

Çok oyunculu bir oyun yürüten her bağımsız geliştirici, ağ kodlarının hayalet senkronizasyon kayıpları ve öngörülemeyen fizik takılmaları üretmeye başladığı o anı tam olarak bilir. Sıkı bir oynanış döngüsü oluşturmak için haftalar harcarsınız, ancak sarsıntılı bir bağlantı üzerinden durumu senkronize etmenin tamamen farklı bir mühendislik zihniyeti gerektirdiğini fark edersiniz. Dev3 ve Dev4 anlık görüntülerinin (snapshot) yakın zamanda yayınlanmasıyla, motorun çekirdek katkıda bulunanları sınırları zorluyor ve bu godot 4.7 yeni özelliklerini anlamak, üretim zaman çizelgelerini planlayan stüdyolar için kritik önem taşıyor.

Godot 4, devasa çekirdek yeniden yazımından bu yana amansız bir yürüyüş içinde. Kararlı sürümler üretimin temelini oluştururken, geliştirme anlık görüntüleri -özellikle Dev2'den yeni basılmış Dev3 ve Dev4'e geçiş- motorun mimari önceliklerinin nerede yattığına dair şeffaf bir pencere sunuyor. Teknik geliştiriciler için bu güncellemeler sadece yama notları değil; ağ oluşturma, işleme ve bellek yönetimi ardışık düzenlerinizi uyarlamanız için erken uyarılardır.

Bu derinlemesine incelemede, projenizi güncellemenin teknik gerçeklerini, sunucu yetkili çok oyunculu oyunlar için GDScript'ten nasıl yararlanılacağını ve motorun devam eden evriminin neden arka uç altyapısına daha akıllıca bir yaklaşım gerektirdiğini detaylıca ele alacağız.

Godot Sürüm Döngüsünü Çözmek: Geliştirici (Dev) Sürümleri Aslında Ne Anlama Geliyor?

Üretim aşamasındaki bir oyunu bir geliştirme sürümüne taşımak hesaplanmış bir risktir. Godot'un terminolojisinde bir "Dev" anlık görüntüsü, özellik dondurmanın (feature-freeze) henüz gerçekleşmediği anlamına gelir. API değişebilir, düğüm (node) davranışları değiştirilebilir ve belgelenmemiş gerilemeler (regressions) neredeyse garantidir.

Ancak, bu sürümleri görmezden gelmek, motorun gidişatını görmezden gelmek anlamına gelir. Godot 4.7'ye geçiş, büyük ölçüde 4.3'ten 4.6'ya kadar sunulan devasa eklemeleri stabilize etmeye odaklanıyor. Performans profillemeye, deterministik fizik davranışlarına ve akıcı çok oyunculu senkronizasyona doğru belirgin bir yönelim görüyoruz.

Tek bir geliştirici veya küçük bir ekip için asıl sıkıntılı nokta genellikle oyun mantığını yazmak değildir; yerel bir makinede 144 FPS'de çalışan bir sahnenin bir ağ üzerinden örneklendiğinde neden aniden 45 FPS'ye düştüğünü veya yoğun çatışma sahneleri sırasında çöp toplama (garbage collection) duraklamalarının neden mikro takılmalara neden olduğunu bulmaktır. Bu dev sürümlerinde ortaya çıkan güncellemeler, doğrudan düğüm ağacı geçişindeki ve dahili bellek ayırıcılarındaki darboğazları hedef alıyor.

Motor Yükseltmelerinin Gerçek Maliyeti

Geliştirme sürecinin ortasında bir motor sürümünü yükseltmek, bir ekibe genellikle iki ila üç haftalık özel bir yeniden düzenleme (refactoring) süresine mal olur. Düğümler kullanımdan kaldırılır, fizik katmanları yeniden tanımlanır ve gölgelendirici (shader) derleme iş akışları değişir.

Godot 4.7 yeni özelliklerini değerlendirirken, vaat edilen performans kazanımlarını bu yeniden düzenleme borcuna karşı ölçmelisiniz. Mevcut projeniz büyük ölçüde özel C++ modüllerine (GDExtension) dayanıyorsa, derleme zincirlerinizin güncellenmiş başlık dosyaları (headers) için hazır olduğundan emin olmalısınız. Tamamen GDScript kullanıyorsanız riskler daha düşüktür, ancak yine de RPC (Uzaktan Prosedür Çağrısı) bağlamalarınızı titizlikle test etmeniz gerekir.

Çok Oyunculu Senkronizasyon Kaybı (Desync) Kabusuyla Başa Çıkmak

Çok oyunculu oyun geliştirme, temel olarak gecikmeyi gizleme egzersizidir. Bir oyuncu zıplamak için bir düğmeye bastığında, yerel istemci bu zıplamayı anında tahmin etmeli ve aynı anda sunucudan izin istemelidir. Sunucu aynı fikirde değilse -belki de oyuncu saniyenin çok küçük bir bölümü kadar önce bir rakip tarafından sersemletildiği için- istemci oyuncunun konumunu zorla uzlaştırmalıdır, bu da rahatsız edici bir görsel "paket lastiği" (rubber-band) etkisine neden olur.

Godot 4, durum çoğaltması için gereken basmakalıp kodların çoğunu soyutlayan MultiplayerSynchronizer ve MultiplayerSpawner düğümlerini tanıttı. Ancak, kutudan çıktığı haliyle senkronizasyon, hızlı tempolu, rekabetçi oyunlar için nadiren yeterlidir. Hangi verilerin gönderileceği, ne sıklıkla gönderileceği ve güvenilir (reliable) veya güvenilmez (unreliable) taşıma kanalları gerektirip gerektirmediği konusunda ayrıntılı kontrole ihtiyacınız vardır.

Sunucu Yetkili Hareketin Uygulanması

Bağımsız geliştiricilerin yaptığı klasik bir hata istemciye güvenmektir. İstemciniz kendi konumunu sunucuya dikte ederse, kötü niyetli oyuncular harita üzerinde ışınlanmak için istemcilerini kolayca değiştireceklerdir. Sunucu nihai otorite olmalıdır.

İşte GDScript'te istemci tarafı tahmini ile sunucu yetkili hareketi uygulamak için pratik, üretime hazır bir yaklaşım. Bu model, temel hız hilelerini (speed hacks) önlerken hareketin duyarlı hissedilmesini sağlar.

extends CharacterBody3D

# Çok oyunculu kurulum
@export var player_id := 1

# Hareket sabitleri
const SPEED := 5.0
const JUMP_VELOCITY := 4.5

# Uzlaştırma için durum takibi
var unacknowledged_inputs := []
var latest_server_state := {}

func _ready() -> void:
    # Çok oyunculu yetkisini oyuncunun kimliğine ayarla
    set_multiplayer_authority(player_id)
    
    # Eğer sunucuysak, fiziği normal şekilde işleriz
    # Eğer istemciysek, sadece tahmin eder ve sunucunun geçersiz kılmalarını bekleriz
    if not is_multiplayer_authority() and not multiplayer.is_server():
        set_physics_process(false)

func _physics_process(delta: float) -> void:
    if is_multiplayer_authority():
        # Girdiyi yakala
        var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
        var input_state := {
            "tick": Engine.get_physics_frames(),
            "dir": input_dir,
            "jump": Input.is_action_just_pressed("ui_accept")
        }
        
        # Anında geri bildirim için yerel olarak uygula (Tahmin)
        _apply_movement(input_state, delta)
        
        # Daha sonra olası bir uzlaştırma için girdiyi sakla
        unacknowledged_inputs.append(input_state)
        
        # Doğrulama için sunucuya gönder
        rpc_id(1, "_receive_client_input", input_state)

# Ağ tıkanıklığını önlemek için güvenilmez (unreliable) RPC burada çok önemlidir.
# Düşen girdiler, sunucunun yetkili durum güncellemeleri tarafından düzeltilecektir.
@rpc("any_peer", "call_remote", "unreliable")
func _receive_client_input(input_state: Dictionary) -> void:
    # SADECE SUNUCU TARAFI
    if not multiplayer.is_server():
        return
        
    var sender_id = multiplayer.get_remote_sender_id()
    if sender_id != player_id:
        # Yetkisiz girdi sahtekarlığını reddet
        push_warning("Player %s attempted to spoof input for player %s" % [sender_id, player_id])
        return
        
    # Girdiyi sunucuda uygula
    _apply_movement(input_state, get_physics_process_delta_time())
    
    # Doğrulanmış durumu tüm istemcilere yayınla
    var new_state = {
        "tick": input_state.tick,
        "pos": global_position,
        "vel": velocity
    }
    rpc("_receive_server_state", new_state)

@rpc("authority", "call_remote", "unreliable")
func _receive_server_state(server_state: Dictionary) -> void:
    # SADECE İSTEMCİ TARAFI
    if is_multiplayer_authority() or multiplayer.is_server():
        return
        
    # Sunucu konumuna yapış (Uzlaştırma)
    # Gerçek bir oyunda, bu yapışmayı gizlemek için bunu enterpole edersiniz
    global_position = server_state.pos
    velocity = server_state.vel
    
    # Onaylanmış girdileri kaldır
    unacknowledged_inputs = unacknowledged_inputs.filter(func(input): return input.tick > server_state.tick)

func _apply_movement(state: Dictionary, delta: float) -> void:
    # Belirli bir durum yüküne uygulanan standart Godot karakter kontrolcüsü mantığı
    if not is_on_floor():
        velocity.y -= 9.8 * delta

    if state.jump and is_on_floor():
        velocity.y = JUMP_VELOCITY

    var direction := (transform.basis * Vector3(state.dir.x, 0, state.dir.y)).normalized()
    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED
    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)

    move_and_slide()

Bu betik, yetkili hareketin temel sıkıntılı noktasını ele almaktadır. Konum ve girdi gibi sürekli veri akışları için unreliable (güvenilmez) RPC'leri kullanarak, altta yatan ağ kuyruğunun birikmesini ve feci gecikmelere neden olmasını önlüyoruz. Yeni motor güncellemeleri, bu dahili RPC kuyruklarının nasıl yönetildiğini iyileştirmeye devam ederek yüksek tickrate'li sunucuları önemli ölçüde daha uygulanabilir hale getiriyor.

Performans Profilleme: GDScript Darboğazından Kaçış

GDScript inanılmaz derecede üretken bir dildir, ancak dinamik doğası bir performans tavanı ile birlikte gelir. Bir _physics_process döngüsünde yüzlerce varlığı işlerken, varyant türlerinin ve dinamik yöntem aramalarının ek yükü kare hızınızı yarı yarıya düşürebilir.

Godot'taki en sinsi performans katillerinden biri çalışma zamanı bellek tahsisidir. Her karede yeni bir düğüm örneklemek veya yeni bir karmaşık sözlük oluşturmak, motorun bellek ayırıcısını tetikler. Zamanla bu, parçalanmaya ve çöp toplama sıçramalarına yol açar; bu da oyun sırasında fark edilebilir takılmalar olarak kendini gösterir.

Nesne Havuzu (Object Pooling): Zorunlu Bir Mimari

Bu ayırıcıları atlamak için Nesne Havuzu (Object Pooling) uygulamalısınız. Oyun sırasında queue_free() ve instantiate() çağırmak yerine, yükleme ekranları sırasında devasa bir nesne dizisini önceden tahsis eder ve sadece görünürlüklerini ve işleme durumlarını değiştirirsiniz.

Bir "bullet hell" (mermi cehennemi) nişancı oyunu düşünün. Bir patron saniyede 500 mermi ateşliyorsa, 500 Area2D düğümünü dinamik olarak örneklemek CPU'nuzu ezecektir.

GDScript'te sağlam bir nesne havuzunu şu şekilde oluşturabilirsiniz:

extends Node
class_name BulletPool

@export var bullet_scene: PackedScene
@export var pool_size: int = 1000

var _available_bullets: Array[Node] = []
var _active_bullets: Array[Node] = []

func _ready() -> void:
    # Oyun başlamadan önce tüm nesneleri önceden tahsis et
    for i in range(pool_size):
        var bullet = bullet_scene.instantiate()
        
        # Mermiyi tamamen devre dışı bırak
        bullet.process_mode = Node.PROCESS_MODE_DISABLED
        bullet.visible = false
        
        # Sahne ağacına ekle ama uykuda tut
        add_child(bullet)
        _available_bullets.append(bullet)

func spawn_bullet(spawn_position: Vector2, direction: Vector2) -> Node:
    if _available_bullets.is_empty():
        push_error("Bullet pool exhausted! Increase pool size.")
        return null
        
    var bullet = _available_bullets.pop_back()
    
    # Mermi durumunu yeniden başlat
    bullet.global_position = spawn_position
    if bullet.has_method("set_direction"):
        bullet.set_direction(direction)
        
    # Mermiyi uyandır
    bullet.visible = true
    bullet.process_mode = Node.PROCESS_MODE_INHERIT
    
    _active_bullets.append(bullet)
    return bullet

func return_bullet(bullet: Node) -> void:
    if not bullet in _active_bullets:
        return
        
    # Mermiyi tekrar uyut
    bullet.process_mode = Node.PROCESS_MODE_DISABLED
    bullet.visible = false
    
    _active_bullets.erase(bullet)
    _available_bullets.append(bullet)

Hesaplama yükünü değişken oynanış döngüsünden statik yükleme aşamasına kaydırarak, düz ve öngörülebilir bir bellek profilini garanti edersiniz. Godot editöründe oyununuzun profilini çıkarırken, bellek kullanımınızın sürekli tırmanıp düşmek yerine sabitlendiğini (plato çizdiğini) görmelisiniz. Sadece bu teknik bile mermi yoğunluklu oyunlarda kare süresi (frame time) varyansını ~15ms'den kaya gibi sağlam bir ~2ms'ye düşürebilir.

İşleme (Rendering) İş Akışları ve Sahne Optimizasyonu

Arka uç ve mantık performansı kritik olsa da, işleme (rendering) görsel olarak en belirgin darboğaz olmaya devam etmektedir. Godot 4'ün Vulkan işleyicisi güçlüdür, ancak bilinçli bir optimizasyon gerektirir. Yaygın bir hata, görünmez geometriyi sihirli bir şekilde ayıklaması (cull) için motora güvenmektir. Godot mükemmel bir görüş alanı ayıklamasına (frustum culling) sahip olsa da, ham köşe (vertex) verilerini GPU'ya itmek hala CPU tarafında hazırlık (çizim çağrıları - draw calls) gerektirir.

Bunu hafifletmek için geliştiriciler çimen, ağaç veya kalabalık sistemleri gibi tekrarlanan geometriler için agresif bir şekilde MultiMeshInstance3D kullanmalıdır. Standart bir MeshInstance3D, her nesne için benzersiz bir çizim çağrısı gerektirir. 5.000 ağaçlı bir ormanınız varsa, bu 5.000 çizim çağrısı demektir; bu da orta sınıf bir GPU'yu felç etmeye yeter.

Bu 5.000 ayrı düğümü tek bir MultiMeshInstance3D'ye dönüştürmek, çizim çağrılarını 5.000'den tam olarak 1'e düşürür. GPU, aynı ağı (mesh) binlerce kez çizme konusunda inanılmaz derecede verimlidir; darboğaza neden olan şey CPU'nun bunu yapma talimatıdır. Godot 4.x yaşam döngüsü boyunca geliştikçe, bu yığınları (batches) yönetme ardışık düzeni giderek daha akıcı hale geliyor, ancak mimari sorumluluk geliştiricide kalıyor.

Arka Uç Altyapısı İkilemi

Gelin odadaki fili (görmezden gelinen asıl sorunu) konuşalım. Nesne havuzlarınızı optimize ettiniz, temiz, sunucu yetkili GDScript yazdınız ve çok oyunculu oyununuz localhost üzerinde test ederken kusursuz çalışıyor.

Şimdi piyasaya sürmek istiyorsunuz.

Aniden, artık bir oyun geliştiricisi değilsiniz; bir DevOps mühendisisiniz. Linux sunucuları tedarik etmeniz gerekiyor. Oyuncuları ping ve becerilerine göre gruplandıran bir eşleştirici (matchmaker) yazmanız gerekiyor. Oyuncu talebine göre dinamik olarak özel sunucu örnekleri (dedicated server instances) oluşturacak ve oyuncu sayısı düştüğünde tasarruf etmek için bunları kapatacak otomatik bir sisteme ihtiyacınız var. Oyuncu envanterleri ve liderlik tabloları için, tümü SSL sertifikaları ve DDOS azaltma katmanlarının arkasında korunan güvenli veritabanlarına ihtiyacınız var.

Bunu kendiniz oluşturmak; Kubernetes kümeleri, yük dengeleyiciler (load balancers), veritabanı parçalama (sharding) ve gerçek zamanlı soket yöneticileri kurmayı gerektirir; bu da oyununuzu eğlenceli hale getirmekle kesinlikle hiçbir ilgisi olmayan, kolayca 4 ila 6 aylık yorucu bir altyapı çalışması demektir.

Hizmet Olarak Arka Uç'un (Backend-as-a-Service - BaaS) var olmasının tam nedeni budur. horizOn ile bu karmaşık arka uç hizmetleri, oyun geliştiricileri için özel olarak önceden yapılandırılmış olarak gelir. Özel eşleştirme mantığı yazmak ve AWS EC2 örnekleri tedarik etmek yerine, bir SDK entegre edersiniz ve platformun sunucu orkestrasyonunu, oyuncu kimlik doğrulamasını ve veri kalıcılığını halletmesine izin verirsiniz. Altyapı yığınınız yerine asıl oyununuzu piyasaya sürmenize olanak tanır.

Sunucu yönetimini oyunlar için oluşturulmuş bir platforma devrederek, oynanış döngünüzü cilalamak ve hataları düzeltmek için gereken yüzlerce saati geri kazanırsınız.

Godot 4.7 Dev Sürümlerine Geçiş İçin 5 En İyi Uygulama

Bir geliştirme anlık görüntüsüne yükseltme yapmak doğası gereği tehlikelidir. Mevcut projenizde godot 4.7 yeni özelliklerini test etmeye kararlıysanız, proje dosyalarınızı bozmaktan kaçınmak için katı bir dağıtım hijyeni izlemelisiniz.

  1. Zorunlu Dallanma (Branching): Birincil proje klasörünüzü asla bir Dev sürümünde açmayın. Yükseltmeyi test etmek için özel olarak ayrılmış bir dal (branch) oluşturmak üzere Git'i kullanın. Proje bozulursa, dalı silip güvenliğe geri dönebilirsiniz.
  2. Profilleme Temellerini Belirleyin: Yükseltmeden önce oyununuzu Godot 4.3/4.6'da çalıştırın ve en ağır sahnenizdeki ortalama FPS'yi, çizim çağrılarını ve bellek kullanımını kaydedin. Yeni sürümde tam olarak bu metrikleri karşılaştırın. Performans düşerse, motor geliştiricilerine bildirebileceğiniz bir gerileme (regression) bulmuşsunuz demektir.
  3. RPC Yapılandırmalarınızı Denetleyin: Ağ kodu genellikle motor güncellemeleri sırasında ilk bozulan şeydir. Her @rpc ek açıklamasını (annotation) denetleyin. Güvenilir ve güvenilmez (reliable/unreliable) bayraklarınızın simüle edilmiş ağ gecikmesi altında hala beklendiği gibi davrandığından emin olun.
  4. Özel Dışa Aktarma Şablonları Derleyin: Özel bir sunucu (dedicated server) oluşturuyorsanız, standart dışa aktarma şablonlarına güvenmeyin. Ses ve işleme modüllerini çıkarmak için Godot kaynak kodundan özel başsız (headless) şablonlar derleyin, bu da sunucunuzun RAM ayak izini büyük ölçüde azaltır.
  5. Otomatik Testler Uygulayın: Matematik ve durum mantığınız için otomatik testler yazmak üzere GUT (Godot Unit Test) gibi bir çerçeve kullanın. Motoru yükselttiğinizde, bu testleri çalıştırmak dahili bir motor hesaplamasının değişip değişmediğini anında işaretleyecektir.

İleriye Bakış: Kararlı Sürüme Giden Yol

Godot motoru tamamen topluluk odaklıdır, yani geliştirme hızı doğrudan bu erken anlık görüntüleri test eden ve sorunları bildiren geliştiricilere bağlıdır. Dev3 ve Dev4 birer atlama taşı olsalar da, açık kaynaklı oyun geliştirmenin en ileri noktasını temsil ederler. Teknik yönetmenlere ve bağımsız geliştiricilere, kararlı sürüm çıkmadan aylar önce mimarilerini planlamak için gereken öngörüyü sağlarlar.

Sunucu yetkili mimaride ustalaşarak, nesnelerinizi agresif bir şekilde havuzlayarak ve işleme ardışık düzenini anlayarak, oyununuzun motor sürümünden bağımsız olarak ölçekleneceğini garanti edersiniz. Ve bu yoğun şekilde optimize edilmiş çok oyunculu oyunu küresel bir kitleye sunmaya hazır olduğunuzda, arka ucunuzun istemci kodunuz kadar sağlam olduğundan emin olun.

Sunucu yönetiminde boğulmadan çok oyunculu oyununuzu ölçeklendirmeye hazır mısınız? horizOn'u ücretsiz deneyin ve en iyi yaptığınız şeye odaklanın: inanılmaz oyunlar yapmak.


Kaynak: Godot 4.7 Dev3 ve Dev4 Yayınlandı