Oyun döngüsü ve delta time: hareket neden FPS'e bağlı olmamalı?
Oyunun güçlü bilgisayarda hızlı, zayıf bilgisayarda yavaş mı oynanıyor? Karakter yüksek FPS'te daha hızlı mı koşuyor? Büyük ihtimalle hareketi kare (frame) başına hesaplıyorsun. Çözüm delta time.
Oyun döngüsü
Her oyun motorunun kalbinde sürekli dönen bir döngü vardır:
- Girdileri oku (klavye, fare, kumanda)
- Oyun durumunu güncelle (hareket, fizik, yapay zeka)
- Ekrana çiz
Bu döngü saniyede kaç kez dönerse FPS o kadardır. Bilgisayardan bilgisayara ve aynı bilgisayarda sahneden sahneye değişir.
Sorun
# Her karede 5 piksel sağa git
func _process(delta):
position.x += 5
60 FPS'te saniyede 300 piksel, 144 FPS'te 720 piksel ilerler. Oyunun hızı donanıma bağlı hâle gelir.
Çözüm: delta time
Delta time, son kareden bu yana geçen süredir (saniye cinsinden). Hızı "kare başına" değil "saniye başına" tanımlayıp delta ile çarparsın:
var hiz = 300.0 # piksel/saniye
func _process(delta):
position.x += hiz * delta
Unity'de aynı şey:
float hiz = 5f; // birim/saniye
void Update() {
transform.position += Vector3.right * hiz * Time.deltaTime;
}
Artık FPS kaç olursa olsun karakter saniyede aynı mesafeyi kat eder.
Fizik için sabit zaman adımı
Fizik hesaplarında değişken delta sorun çıkarabilir: çok uzun bir kare, hızlı giden bir nesnenin duvarın içinden geçmesine yol açabilir. Bu yüzden motorlar fizik için sabit adımlı ayrı bir güncelleme sunar:
- Godot:
_physics_process(delta)(varsayılan saniyede 60 kez) - Unity:
FixedUpdate()(varsayılan 0,02 sn, yani saniyede 50 kez)
Kural:
- Rigidbody'ye kuvvet uygulamak, fizik tabanlı hareket → sabit adımlı güncelleme
- Girdi okumak, kamera, animasyon, arayüz → normal güncelleme
Unity'de girdiyi Update içinde okuyup bir değişkene yazmak, fiziği FixedUpdate içinde uygulamak yaygın bir düzendir. Aksi hâlde kısa tuş basışları bazen kaçabilir.
Sık yapılan hatalar
- Delta'yı iki kez çarpmak: Bazı motor fonksiyonları (ör. Godot'da
move_and_slide) delta'yı zaten kendi içinde hesaba katar. Hızı ayrıca delta ile çarparsan hareket çok yavaşlar. - Zamanlayıcıları kare sayarak yapmak: "60 kare sonra ateş et" yerine geçen süreyi biriktir ya da motorun zamanlayıcısını kullan.
- Duraklatmada delta'yı unutmak: Oyun duraklatıldığında güncellenmeye devam eden şeyler olabilir. Motorun duraklatma ve zaman ölçeği (Unity'de
Time.timeScale) ayarlarını kullan.
Test
Geliştirirken FPS'i bilerek sınırla (ör. 30 ve 144) ve oyunu iki durumda da dene. Hız, zıplama yüksekliği ve zamanlamalar aynı kalmalı.