Metlivi Blog

Sanal Hayvan Oyun Döngüsünde Boşta ve Etkileşimli Durumlar Nasıl Ayrılır?

Bir sanal hayvan oyununda, otonom davranışları ve oyuncu eylemlerini ayrı güncelleme yollarında tutun, ardından her ikisinin de açık geçişler aracılığıyla paylaşılan tek bir hayvan durumunu değiştirmesine izin verin. Boşta (idle) davranışı geçen zamana göre ilerlemelidir; etkileşimli davranışı ise girdi olaylarına veya mevcut girdi durumuna yanıt vermelidir. Bu yaklaşım oyunu duraklatmayı, test etmeyi ve bir hayvan animasyonunun veya ihtiyaç zamanlayıcısının bir oyuncu komutuyla çakışmasını önlemeyi kolaylaştırır.

15 Ekim 20266 dk okuma süresiYazan: Metlivi Editorial Team
Bölüm 1

“Boşta” ve “etkileşimli” kavramlarının ne anlama geldiğini tanımlayın

Bunları mutlaka farklı sahneler veya ayrı döngüler olarak değil, davranış modları olarak ele alın. Boşta (idle) modunda hayvan kendi rutinini yürütür: küçük bir ortam eylemi seçer, bir zamanlayıcıyı ilerletir veya zorunlu olmayan bir animasyonu oynatır. Etkileşimli (interactive) modda ise oyun; dokunma, sürükleme veya seçilen bir komut gibi kasıtlı bir eylemi işler. Hayvan bir etkileşim sırasında da animasyon oynatabilir; buradaki fark, hangi sistemin karar almasına ve oynanış durumunu değiştirmesine izin verildiğidir.

Oyuncunun gerçekleştirebileceği eylemler ve hayvanın gerçekleştirebileceği otonom davranışlardan oluşan kısa bir listeyle başlayın. Her birinin hangi durum değişkenlerini değiştirebileceğini işaretleyin. Örneğin, ortamdaki bir göz kırpma yalnızca görsel sunumu etkileyebilirken, seçilen bir oyun eylemi hayvanın mevcut aktivitesini değiştirebilir ve bir zamanlayıcı başlatabilir. Bu basit sahiplik haritası, kod karmaşıklaşmadan önce çakışmaları ortaya çıkarmaya yardımcı olur.

Bölüm 2

Dış döngüyü hayvan davranışından bağımsız tutun

Oyun motorunun kare geri çağırma (frame callback) mekanizması, tüm hayvan kurallarını barındırmak yerine işleri koordine etmelidir. Kullanışlı bir sıralama şöyledir: girdiyi topla, geçerli komutları uygula, simülasyonu ilerlet, ardından en son durumu ekrana çiz (render). Girdi toplamayı simülasyondan ayrı tutun; böylece bir dokunma yanlışlıkla bir zamanlayıcı adımı gibi değerlendirilmez. Ayrıca görselleştirmeyi (rendering) oynanış değişikliklerinden uzak tutun. Game Programming Patterns, bu ayrımı tekrarlayan bir döngüde girdiyi işlemek, oyunu güncellemek ve ekrana çizmek olarak tanımlar; sabit adımlı güncellemeler, simülasyonun kararlı bir aralığa ihtiyaç duyduğu durumlarda faydalıdır. Game Loop, Game Programming Patterns

Bir web oyunu için requestAnimationFrame, yeniden çizimden önce işleri planlar ve geçen süreyi ölçmek için kullanabileceğiniz bir zaman damgası sağlar. Tarayıcılar genellikle gizli sekmelerde bu geri çağırmaları duraklatır, bu nedenle oyun arka plandayken bunların güvenilir bir duvar saati gibi çalışmaya devam ettiğini varsaymayın. Window.requestAnimationFrame(), MDN

Bölüm 3

Oyuncu girdilerini komutlar üzerinden yönlendirin

Ham girdiyi start_play, stop_play veya pet_tap gibi küçük bir komuta dönüştürün. Bir komut işleyici, eylemin mevcut mod için geçerli olup olmadığını kontrol eder, paylaşılan modeli bir kez günceller ve ortaya çıkan görsel sunum ipuçlarını tetikler. Bu, eylem mantığının aynı anda hem düğme geri çağırmalarına, hem animasyon geri çağırmalarına hem de boşta kalma rutinine dağıtılmasını önler.

Örneğin, hayvan zaten oyun oynarken oyuncu dokunursa, sonucu bilinçli olarak tanımlayın: dokunmayı yok sayın, farklı bir aktivite seçin veya aktiviteyi durdurun. Hem boşta kalma seçicisinin hem de dokunma işleyicisinin aynı güncelleme sırasında yeni bir aktivite atamasına izin vermekten kaçının. Olay yayılımı (event propagation) bulunan motorlarda, oynanış girdilerini uygun aşamada işleyin ve kullanıcı arayüzü tüketimine saygı gösterin; Godot'nun Node belgeleri, GUI kontrollerinin önceliğe ihtiyaç duyduğu durumlarda işlenmemiş girdilerin (unhandled input) genellikle oynanış için daha uygun olduğunu belirtir. Node class, Godot documentation

Bölüm 4

Boşta kalma süresini net bir saatle ilerletin

Görünür bir oturum sırasında sürekli ilerlemesi gereken davranışlar için, geçen simülasyon süresini biriktirin ve belirlenen aralığa ulaşıldığında bir boşta kalma kararı tetikleyin. Kareleri saymayın: kare hızı değişkendir. Godot'da _process(delta) bir önceki boşta kalma karesinden bu yana geçen süreyi alırken, _physics_process(delta) fizik adımlarını takip eder; belgeler ayrıca biriken delta süresinin bazı koşullar altında gerçek dünya saniyelerinden sapabileceğini de belirtmektedir. Node class, Godot documentation

Saati davranışa göre seçin. Kozmetik hareketler genellikle kare başına geçen süreyi kullanabilir. Çarpışmayla ilgili hareketler motorun fizik güncellemesine aittir. Bir hayvanın "birkaç saniyede bir ortam eylemi seç" zamanlayıcısı bir simülasyon zamanlayıcısı kullanabilir, ancak uzun bir kareden veya duraklatmadan sonra ne olacağına karar verin: geçen süreyi sınırlayın, tek bir karar uygulayın veya sınırlı adımlarla telafi edin. Sınırsız telafi, oyun devam ettiğinde hayvanın birçok durum arasında aniden atlamasına neden olabilir.

Bölüm 5

Mod geçişlerini açık hale getirin

Daha fazla durum eklemeden önce küçük bir geçiş tablosu yazın. Örneğin, idle → playing oyuncunun seçtiği bir aktiviteyi başlatır; playing → idle bu aktivite bittiğinde veya oyuncu iptal ettiğinde gerçekleşir; idle → resting otonom rutin tarafından seçilebilir. Giriş ve çıkış etkilerini tek bir yerde tanımlayın; örneğin bir zamanlayıcıyı başlatmak veya sıfırlamak ve ilgili animasyonu seçmek gibi. Oynanış modunun değiştiğinin kanıtı olarak tek başına animasyonun tamamlanmasını kullanmayın: görsel oynatma kesintiye uğrayabilir veya atlanabilir.

Bir geçiş işlevi mevcut modu doğrulamalı, modeli güncellemeli ve işleyicinin (renderer) görüntüleyebileceği bir sonuç döndürmelidir. Bu, "hayvanın ne yaptığı" ile "bu eylemin nasıl çizildiği" mantığını birbirinden ayrı tutar. Ayrıca testler için net bir hedef sunar: bir komut gönderin, ortaya çıkan modu inceleyin ve ardından boşta kalma rutininin artık bu modun üzerine yazmadığını doğrulayın.

Bölüm 6

Arka plan süresinin nasıl davranacağına karar verin

Yaygın iki yaklaşım vardır ve doğru olanı oyun tasarımına bağlıdır. Yalnızca oturum bazlı çalışan bir hayvan, askıya alındığında simülasyonu durdurabilir ve önceki durumundan devam edebilir. Kapalıyken zamanlayıcıların ilerlemesini amaçlayan bir oyun ise bir zaman referansı kaydetmeli ve geri dönüldüğünde geçen süreyi uzlaştırmalıdır (reconcile). Kare döngüsünü arka planda çalıştırmaya çalışmak yerine bunu ayrı bir devam etme hesaplaması olarak ele alın; tarayıcı animasyon geri çağırmaları gizli sekmeler için duraklatılabilir. Window.requestAnimationFrame(), MDN

Basit bir hayvan için yalnızca gerçekten ilerlemesi gereken miktarları (belki tek bir aktivite zamanlayıcısı) uzlaştırın ve telafi için makul bir üst sınır koyun. Ardından kısa ve uzun bir aradan sonra kapatıp yeniden açmayı test edin. Saat seçimi, askıya alma davranışı ve telafi sınırı tasarım kararlarıdır; bir motorun kare geri çağırması bunları sizin yerinize belirlemez.

Bölüm 7

Çakışan güncellemeleri ve kaçırılan girdileri kontrol edin

Döngüyü tekrarlanabilir birkaç senaryoyla test edin: oyunu birkaç aralık boyunca boşta bırakın; tam bir boşta kalma kararından önce bir komut verin; bir girdiyi basılı tutun veya tekrarlayın; duraklatın ve devam ettirin; ve bir animasyon hâlâ oynatılırken yeni bir eylemi tetikleyin. Her komutun modeli yalnızca bir kez değiştirdiğini, boşta kalma mantığının oyuncu tarafından seçilen bir durumun yerine geçmediğini ve geçen süre davranışının seçilen duraklatma politikasıyla eşleştiğini doğrulayın.

Simülasyon için sabit bir güncelleme (fixed update) kullanıyorsanız, bunun çizilen kareler arasında sıfır, bir veya birden fazla kez çalışabileceğini unutmayın. Unity, FixedUpdate için bu davranışı belgeler ve bunu fizik hesaplamaları için önerir; girdi ve görsel güncellemelerin farklı zamanlama gereksinimleri vardır. FixedUpdate(), Unity documentation Unity'nin Input System'ı da cihaz olaylarını kuyruğa alır ve bunları yapılandırılmış güncelleme moduna göre işler; bu nedenle girdi işlemeyi, bu komutları tüketen döngüyle uyumlu hale getirin. Input event queue, Unity Input System

Bölüm 8

Korumaya değer pratik bir ayrım

Mimarinin kapsamını küçük tutun: paylaşılan tek bir hayvan modeli, tek bir girdiden komuta yolu, tek bir boşta kalma davranışı güncellemesi, tek bir açık geçiş işlevi ve modeli okuyan bir çizici (renderer). Sabit bir simülasyon adımını yalnızca zamanlamaya duyarlı davranışlar gerektirdiğinde ekleyin; her animasyonu veya ortam seçimini fizik adımlarına bağımlı hale getirmeyin. Bir hata ortaya çıktığında, modu en son kimin değiştirdiğini ve onu hangi saatin ilerlettiğini inceleyin. Bu yaklaşım, her güncellemeye net bir görev verir ve hayvan yeni eylemler kazandıkça boşta kalma ve etkileşimli davranışların öngörülebilir olmasını sağlar.

Bölüm 9

Kaynaklar

İlgili okumalar

Bu konuyu keşfetmeye devam et