Oyunda network kodunu istediğim olgunluğa getirmek çok zamanımı aldı. İçime sinene kadar, türlü türlü denemeler yapmam gerekti, yıllar geçti. Saldırı ve koşma animasyonlarını, Unity ve multiplayer belgeleri ve videolarında görmediğim bir şekilde, görsel açıdan büyük fark yaratacağını düşündüğüm bir yöntemle yapma hedefi koydum kendime, bu hem tahmin ettiğim kadar fark yaratmadı, hem de gereğinden fazla vakit harcamama sebep oldu.
Neyse ki, network tarafındaki işim, sunucu işlerinin bir kısmını Golang ile yeniden yazacağım döneme kadar bitti. API ile içerik üretme, oyun içi market tasarlama gibi işler için Unity'yi meşgul etmek yerine Golang ile yazacağım minik servisler kullanacağım.
Mümkün olduğunca hızlı ilerlemek, Steam'e iyi kötü çalışır bir sürüm koymak ve dışarıdan destek almaya başlamak için en az tasarıma ayırdığım kadar bir zamanı planlamaya ayıracağım. Burada, yapmak istediklerimden kısa kısa bahsetmek istiyorum. Aklıma yattıkça, bunları bir Trello sayfasına koyup paylaşmaya başlayacağım.
Çok büyük oyun projelerinde dahi, sürekli olarak sunucuları ayakta tutmak zor gördüğüm kadarıyla. Milyonlarca dolar yatırıma sahip oyunlar bunu yapamazken, oyun tahminimden kat ve kat fazla kullanıcıya, mesela 350 kişiye ulaşırsa ne yağacağım?
Oyunun, network olmadan da çalışır halde. Baştan beri istediğim bir özellik. Tek kullanıcılı bölümler planladığımdan değil, tamamen tüm testleri tek ekranda yapabilme lüksü verdiği için. Oyun, kendi üzerindeki sunucuya bağlanabiliyor; yerel ağda oyunlar oynamak da mümkün, tek kişi takılmak da, oyunu internete açmak da. Bana faydası, tek bilgisayarda hızlıca geliştirme imkanı vermesi.
Birden Fazla Sunucu
İyi bir bilgisayarla yaptığım testlerde, genellikle sunucunun kullanıcı limitine takılmadan çok daha önce, oyunun oynandığı bilgisayarın kaynakları tükenmiş oluyor. 30fps altında kış boyu hasretini çektiğim yemyeşil kırlar bile iyi görünmüyor, karakter animasyonları göz yoruyor.
İstemci optimizasyonu, işi bilen arkadaşlarla netcode'a göre nispeten kısa bir sürede çözülebilir bir problem gibi geliyor. Daha dikkatli hazırlanmış modeller kullanma, mesafe ya da açı yüzünden görünmeyen detayların temizlenmesi, desen kalitesinin fazla yakın plan çekim olmaması sebebiyle düşürülmesi gibi hemen akla gelen optimizasyonlarla bir haftasonu ve bolca kahve ile sunucu limitine yakın noktaya gelebiliriz.
Sonrası için haritada kaç canavar, satıcı ve karakter olduğunda Unity3D ve C# ile yazılmış sunucumuz artık teklemeye başlayacak bakmak ve haritayı ne şekilde ikiye, üçe, sonra yüze bölmek gerekecek düşünmek gerekiyor.
Burada ufak denemelerim oldu, ama sonraya bırakabileceğim bir iş olarak gördüğünden fazla kafa yormadım. Planlardan biri, dünyayı Unity sunucularında oluşturmak ve Golang sunucularına bağlanan N oyuncuya bu bilgileri "broadcast" etmekti, ancak bazı hesapları Unity tarafında yapmak teorik olarak çok daha hızlı olduğundan, oyun ile ilgili işlerde Golang'a bulaşmamaya karar verdim, kesin kararım olmamakla birlikte.
Bölümler arası geçişlerde yükleme ekranı kullanılmasını sevmeyen bir oyuncu olarak, Blizzard'ın bile Shadowlands eklentisiyle yükleme ekranına geçmesi sonrası bu düşüncem değişti ve "tek enayi biz miyiz?" demeye ve işin kolayına kaçmaya karar verdim. Gerekirse, karakterlerin farklı bölümlere geçmesi için önceden belirlenmiş yollardan, mesela uzun bir tünelden, geçmesini mecbur kılacak ve arkada gizlice sunucuları değiştireceğim. Belki zamanla (gizli) yükleme ekranlarından kurtulurum.
Dünya Sunucusu ve API
Bazı işleri elle yapmak zor. Misal, 3b modeli hazır karaktere, Unity için hazırlanmış bir animasyonu eklemek kolay bir iş. Arayüzde birkaç parametreyi işaretlemek, sonrasında hangi durumda bu animasyon oynatılacak kodlamak yetiyor. Kopyala, yapıştır.
Sonra dertli kısım başlıyor: detaylar. Ayak hareketi varsa ayak sesleri, silah hareketi varsa silah sesi için animasyona etiketleme gerekiyor. Yapması kolay, ama vakit alıyor. Test etmesi, geçiş sürelerinin deneme yanılma ile düzenlenmesi ve animasyon geçişlerinin olabildiğince akıcı olması için girilen döngü vakit alıyor.
Bunca ufak iş varken, benim yapmayabileceğim işleri outsource etme fikri çok iyi görünüyor. Lakin, bunun için yine biraz iş yapmak gerek.
Tamam, animasyonlara ses etiketleri ekleme, atak animasyonlarında hangi efektlerin gösterileceğine karar verme biraz fazla teknik bilgi gerektiren işler; ama bu animasyonları ve modelleri tekrar tekrar kullanarak farklı hikayeler, sahneler ve görevler oluşturmak tamamen programlamaya indirgenebilir.
Golang, Python, PHP, hatta curl ile yönetilebilir bir dünya mümkün. Sunucuda bunları kalıcı olarak saklamak ve sonraki sürümlere entegre etmek (böylece yükleme süresini düşürmek) de uygulanabilir ve pratik.
Burası, dışarıdan yardım almaya başlayacağım ilk yer olabilir. Oyun içinde, kullanılabilir modeller için bir galeri ekleme gibi büyük bir özelliği barındırsa da, başlangıç için koda ve modellere erişimi olan geliştiriciler API'ı fazla ek iş yapmadan kullanabilir.
Gelelim bunun zor kısmına... Karakter modellerini, hatta büyük kaleleri statik olarak bir yere koymakla, karakterlere ya da kapı gibi modellere davranışlar eklemek, sadece API ile halledilecek iş değil. İlla canlı bir arayüz gerekiyor, chat bot API gibi. Sunucudan gelen "karaktere biri saldırdı" bilgisine göre hareket edecek, tepki verecek, alışveriş yapacak davranışları kodlamak kolay olsa da, bunları "scale" etmek dert.
Aklıma gelen ilk çözüm, sürekli olarak sunucuda çalışacak, ufak kod parçaları. Lua ya da JS ile yazılan ufak davranış scriptleri oluşturulabilir.
Hatta, internete dahi bağlanmadan, sadece oyunun yerel kopyası ile NPC, boss, zindan oluşturmak ve davranış kodlamak ve bunu sunucu yöneticisine gönderek oyun dünyasına dahil edilebilir.