Programlama

Unity’de Çok Oyunculu Lobi: Socket.IO ile Sağlam Kurulum

İlginç olan şu ki, Multiplayer işine girince herkesin aklındaki ilk soru genelde “bağlantı kuruldu mu?” oluyor. Açık konuşayım, asıl mesele orası değil. Asıl çetin kısım lobi: oyuncu gelip gidiyor, host bir anda düşüyor, telefon ekranı kilitleniyor ve slot buharlaşıyor. İşte kaos tam burada başlıyor — bağlantıdan sonra, bekleme odasında.

Geçen sene Kadıköy’de bir indie ekiple sohbet ederken aynı dertten yakındılar. Oyun çalışıyor, oda açılıyor, ama biri 20 saniye Wi‑Fi gidince bütün akış dağılıyor. Ben de 2024’ün sonlarında kendi test projemde buna benzer bir senaryo kurmuştum; üç cihazla denedim, biri kapandı mı diğerleri “hâlâ bağlı sanıyor” modunda kalıyor ve işler çorba oluyordu. Bu yazıda o çorbayı biraz toparlayacağız.

Neden lobi işi sandığınızdan daha zor?

Eh, Lobi dediğimiz şey bekleme odası gibi masum duruyor (şaşırtıcı ama gerçek). Yanılıyorsunuz. İçeride üç ayrı dünya var: ağ bağlantısı, oyun durumu ve arayüz — bunları tek yerde karıştırırsanız, küçücük bir hata bile domino etkisi yaratıyor ve nereye baktığınızı bilemez hale geliyorsunuz. Mesela socket doğrudan UI’yi bilirse yarın ekran tasarımını değiştirdiğinizde ağ katmanı da kırılabiliyor. Klasik sıkıntı.

Bunu biraz açayım.

Doğrusu, Şu var ya, çoğu eğitim videosu “bağlandı” noktasında bırakıyor işi. Halbuki gerçek hayatta oyuncular sadece bağlanmıyor; ayrılıyor, geri dönüyor, host değişiyor, oda koduyla arkadaş çağrılıyor (şaşırtıcı ama gerçek). Yani oyun geliştirme meselesinden çok operasyonel dayanıklılık — ki bu tartışılır — sınavına dönüyor bu iş. Kimse bunu önceden söylemiyor.

Ben bu yapıyı ilk kez 2023’te Bursa’da bir mobil oyun prototipinde test etmiştim. En can sıkan problem şuydu: kullanıcı uygulamayı arka plana atınca sistem onu anında düşmüş sayıyordu. Kâğıt üstünde süper görünen şey, pratikte hayal kırıklığına döndü. Tam anlamıyla.

💡 Bilgi: Sağlam bir multiplayer lobi için hedefiniz sadece bağlantı kurmak değil; oturumu korumak, yeniden bağlanmayı yönetmek ve UI ile ağı birbirinden ayırmak olmalı.

Mimariyi düzgün kurmadan başlamayın

Size bir şey söyleyeyim, Bu tür projelerde en sevdiğim yaklaşım üç katmanlı yapı: Network Manager, State Store ve UI Controller. Socket.IO’dan gelen olaylar önce ağ katmanına giriyor, sonra tek bir durum deposunda toplanıyor, en son arayüze yansıyor (bu konuda ikircikliyim). Basit gibi duruyor — ve baya da işe yarıyor, ciddiyim.

Aşağıdaki ayrım mantığını hem küçük ekiplerde hem büyük yapılarda faydalı buldum; küçük startup tarafında hız kazandırıyor, enterprise tarafta ise debug süresini ciddi kısaltıyor, çünkü bir sorun çıktığında “bu bug socket tarafında mı yoksa ekran tarafında mı?” diye dakikalarca bakınmıyorsunuz — katman sınırı size cevabı veriyor zaten.

Bir dakika — bununla bitmedi.

Katman Görev Neyi engeller?
LobbyNetworkManager Soket bağlantısı ve event alışverişi UI’nin ağa bulaşmasını
LobbyStateStore Oda verisinin tek kaynak olması Dağınık state kopyalarını
LobbyUIController Ekranı güncellemek Ağın doğrudan GameObject kontrol etmesini

Ha bu arada — bu yapı bana mutfaktaki düzeni hatırlatıyor. Bıçaklar çekmecede, tabaklar rafta. Kimse yoğurt kabının içinde bıçak aramaz ya! Yazılımda da aynı mantık geçerli. Gülünç benzetme belki ama aklımda kalmasına yardımcı oldu. Anker’ın Bu Güç İstasyonu Şu An Cebinize Daha Yakın yazımızda bu konuya da değinmiştik.

Neden namespace socket kullanılır?

/lobby gibi özel namespace kullanmak bence çok temiz bir hamle. Aynı sunucuda farklı modüller — ki bu tartışılır — varsa event isimleri birbirine girmiyor (kendi tecrübem). Bugün lobby var, yarın chat geliyor; ikisini aynı köke yığarsanız işler bulanıyor — denedim, biliyorum.

private SocketIOClient _root;
private NamespaceSocket _lobby;
private void Start()
{
_root = new SocketIOClient(TransportFactoryHelper.CreateDefault());
_root.ReconnectConfig = new ReconnectConfig { autoReconnect = false };
_lobby = _root.Of("/lobby");
_root.Connect("http://localhost:3001");
}

Burada autoReconnect’i kapatmak kritik nokta. Çünkü körlemesine yeniden bağlanmak yerine siz oturumu bilinçli biçimde geri topluyorsunuz — oyuncuya “seni yeni biri gibi açtım” demek yerine mevcut kimliğiyle devam ettirmek daha doğru (ciddiyim). Şey, yani… ince fark ama kullanıcı deneyiminde hissediliyor.

Dataları taşırken IL2CPP sürprizine dikkat edin

JSON snapshot kullanan projelerde model sınıfları sıradan görünür. Ama sahnede önemli rol oynuyorlar — özellikle WebGL veya IL2CPP derlemelerinde bazı alanların silinmesi can sıkıcı bir sürpriz oluyor. Siz ne dersiniz? [Preserve] burada hayat kurtarıyor çünkü Unity bazen kullanılmadığını düşündüğü alanları budayabiliyor.

[JsonProperty] ise server’dan gelen alan adlarıyla C# property’lerini eşleştiriyor. Açık konuşayım; minification sonrası veri kaybı yaşamak kadar sinir bozucu az şey var geliştirici hayatında. O an loglara bakarsınız, her şey sanki doğruymuş gibi görünür, ama veri boş gelir. Saatlerce kafayı yersiniz. Bu konuyla ilgili Beyaz Saray’ın AI Freni: Eyaletlerde Neler Oluyor? yazımıza da göz atmanızı tavsiye ederim.

  • [Serializable] ile modelin Unity tarafında rahat taşınması sağlanır.
  • [Preserve] ile AOT derlemelerde alanların kaybolması önlenir.
  • [JsonProperty] ile server-client şeması uyumlu tutulur.
  • Sürüm numarası eklemek ileride migration işini kolaylaştırır.

Sadece çalışan değil, geri dönebilen veri modeli lazım

Lobi verisi statik değil; version artar, host değişir, oyuncu listesi kısalır ya da uzar. Bu yüzden RoomState yapısını salt veri taşıyan basit bir sınıf olarak görmek eksik kalıyor — onu zaman içinde değişen, migrate edilebilen bir yapı olarak tasarlamak gerekiyor. OpenAI’nin 100 Dolarlık Codex Paketi: Kimler İçin? yazımızda bu konuya da değinmiştik.

Multiplayer lobide esas başarı ölçüsü “bağlantı kuruldu” cümlesi değil; kopan bağlantının ne kadar zarif toparlandığıdır.

Kodun kalbi değil ama omurgası: host migration ve reconnect

Bakın, Üretim ortamındaki fark tam burada çıkıyor. Host gidince odanın ölmemesi lazım. Ev sahibi çıkınca bütün salon kapanıyorsa tasarımınız eğreti kalmış demektir — bunu özellikle İstanbul’da çalışan bir arkadaşımın co-op prototipinde gördüm; host uygulamayı kapattığında diğer iki kişi menüye atılıyordu ve herkes moral bozukluğu yaşıyordu. Tekrar tekrar.

Durun, bir saniye.

Peki çözüm ne? Önce grace window fikri geliyor akla. Basitçe söyleyeyim: belli bir süre boyunca düşen oyuncuya tekrar katılma hakkı veriyorsunuz. Telefon kilitlendi diye insanları cezalandırmıyorsunuz. Ama burada fazla cömert olmamak da gerekiyor — yoksa oda güvenliği zedelenebiliyor. Biraz ince ayar işi bu.

Bi saniye — Sonra host migration geliyor. Sahibi giden masada sandalye boş kalmasın diye başka biri doğal aday olarak seçiliyor; mesela en uzun süre bağlı kalan kişi ya da sunucuya ping’i en düşük olan oyuncu öne çıkarılabilir. Her oyunda aynı strateji işlemez tabii.

“Bağlantı sağlam” demek yetmiyor — Asıl mesele “kopunca ne oluyor?” sorusu. Bu soruyu cevaplayamayan proje canlıda çok yorar.

Küçük takım için pratik öneri

Küçük ekipteyseniz önce basit tutun. Durum deposunu tek dosyada bile başlatabilirsiniz, ama loglama mutlaka olsun. Kâğıt üstünde büyük mimari çizmek kolaydır; bazen iki ekstra event bile size fazlasıyla yeter, ihtiyaç büyürse o zaman katmanı genişletirsiniz. Ben olsam erken aşamada gereksiz soyutlamaya kaçmamaya çalışırım açıkçası.

Büyük ölçekli ürünlerde ne değişir?

Büyük ekiplerde versiyonlama şart oluyor. Oda şemasını sabitlemezseniz client sürümleri birbirini anlamıyor. Gözünüzü korkutmasın,. Sürüm bayrağı olmadan canlı servis yönetmek biraz trafik ışığı olmayan kavşağa benziyor — nasıl geçtiğinizi siz de bilmiyorsunuz, karşı taraf da bilmiyor (ben de ilk duyduğumda şaşırmıştım)

💡 Bilgi: Host migration planınız yoksa oyununuz kısa seanslarda iyi görünse bile uzun testlerde duvara toslar. Kalabalık oyunlarda geri dönüş penceresi koymak neredeyse şarttır. Eğer rekabetçi yapıdaysa süreyi kısa tutun; sosyal lobilerde biraz esneyebilirsiniz. Evet.

Ekran tarafını sade tutmanın getirisi çok büyük

Bunu yaşayan biri olarak söyleyeyim, User interface çoğu zaman küçümseniyor (en azından benim deneyimim böyle). Haksızlık bu. Kriz anlarının ilk görüldüğü yer orasıdır — ekran direkt sokete dokunursa birkaç hafta sonra bakım kabusa dönüyor, o yüzden UI sadece state dinlesin, düğmeye bassın, gösterimini yapsın. Ne eksik ne fazla.

Bir de şu var: bazen geliştirici her şeyi tek ekranda çözmeye çalışıyor. Yapmayın. Kodu parçalamak size bugün beş dakika kaybettirebilir ama iki ay sonra beş saat kazandırır. “Şimdi bunu niye söylüyorsun?” diyorsanız — çünkü ben o beş saati kaybettim (şaşırtıcı ama gerçek)

Açık konuşayım, Aynısını geçen ay Ankara’daki freelance işimde yaşadım. Arkadaş grubu için yaptığım mini lobby demo’sunda hazır görselden vazgeçip sade butonlara döndüğümde hata sayısı gözle görülür şekilde düştü. Görsel gösteriş azalınca sistem davranışı netleşti. Biraz tatsızdı belki ama doğru karardı. Kesinlikle. Transformer’larda Self-Attention Neden Oyunu Değiştirdi? yazımızda da bu konuya değinmiştik. Yunanistan Semalarında Görülen RQ-180 Ne Anlatıyor? yazımızda da bu konuya değinmiştik.

Bir de kullanıcıya net feedback vermek gerekiyor: “yeniden bağlanılıyor”, “oda bulunamadı”, “host değişti”… Bunlar yoksa insanlar uygulamanın donduğunu sanıyor. Basit mesajlar bazen karmaşık animasyonlardan çok daha değerli oluyor.

Sizin için hangi senaryo daha uygun?

Küçük bir bağımsız oyun yapıyorsanız öncelik hız olabilir. Tek sunucu, basit room code ve temel ready-state çoğu zaman yeterli. Hedefiniz hızlıca oynanabilirlik göstermekse fazla mühendislik sizi yavaşlatır — gerçekten.

Eh, Ama live ops düşünüyorsanız tablo değişiyor. Reconnect politikası, kötü ağ koşulları altında davranış, bahsettiğim grace window gibi detaylar olmazsa olmaz hale geliyor. Fark küçücük görünür; kullanıcı tarafındaki etkisi ise baya büyük.

Kendi not defterime şöyle yazmıştım: “erken aşamada güzel çalışan lobby, yayın sonrası gerçek testte ter döker.” Hâlâ bunun altına imza atarım. Neyse, uzatmayalım — sistem dayanıklıysa tasarım özgürlüğünüz de artar.

  1. Ağın UI’den bağımsız olduğundan emin olun.
  2. Düşen oyuncuyu hemen silmeyin, recover penceresi verin.
  3. Status mesajlarını açık yazın, kısacık olsun yeter.
  4. Sürüm numarasıyla oda şemasını kontrol edin.
  5. Tetikleyici event’leri loglayın, kurtarıcı olur.

Sıkça Sorulan Sorular

Unity’de multiplayer lobi kurarken Socket.IO uygun mu?

Evet,Soket.IO özellikle oda yönetimi ve gerçek zamanlı event akışı için gayet uygun.Basit projelerde hızlı sonuç verir,daha karmaşık yapılarda ise ek altyapıya ihtiyaç duyabilirsiniz.

Neden autoReconnect kapatılıyor?

Çünkü yeniden bağlanma kararını sizin vermeniz gerekir.Kullanıcının eski oturumunu korumak istiyorsanız kör otomatik reconnect yerine kontrollü akış daha güvenlidir.

`[Preserve]` Unity’de neden önemli?

AOT/IL2CPP derlemelerde kullanılmadığı sanılan alanlar silinebiliyor.[Preserve] bunların korunmasına yardım ediyor.Yoksa JSON deserialize sırasında sessizce veri kaybı yaşayabilirsiniz.

Host disconnect olursa oda tamamen kapanmalı mı?

Zorunlu değil.En iyi yaklaşım host migration veya kısa bir grace window tanımlamak.Oyun tipine göre karar vermek lazım.

Kaynaklar ve İleri Okuma

socketio-unity GitHub Sayfası

Unity Resmi Dokümantasyonu

\

Socket.IO Resmi Dokümantasyonu

Aşkın KILIÇ

20+ yıl deneyimli Azure Solutions Architect. Microsoft sertifikalı bulut mimari ve DevOps danışmanı. Azure, yapay zekâ ve bulut teknolojileri üzerine Türkçe teknik içerikler üretiyor.

AZ-305AZ-104AZ-500AZ-400DP-203AI-102

Bu içerik işinize yaradı mı?

Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.

Haftalık Bülten

Her pazar özenle seçilmiş teknoloji yazıları doğrudan e-postanıza gelsin.

← Onceki Yazi
OpenAI’nin 100 Dolarlık Codex Paketi: Kimler İçin?
Sonraki Yazi →
Transformer’larda Self-Attention Neden Oyunu Değiştirdi?

Yorum Yaz

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Haftalık Bülten

Azure, DevOps ve Yapay Zeka dünyasındaki en güncel içerikleri her hafta doğrudan e-postanıza alın.

Spam yok. İstediğiniz zaman iptal edebilirsiniz.
📱
Uygulamayı Yükle Ana ekrana ekle, çevrimdışı oku
Kategoriler
Ara
Paylaş
İçindekiler
← OpenAI’nin 100 Dolarlık Codex ...
Transformer’larda Self-Attenti... →
📩

Gitmeden önce!

Her pazar özenle seçilmiş teknoloji yazıları ve AI haberleri doğrudan e-postanıza gelsin. Ücretsiz, spam yok.

🔒 Bilgileriniz güvende. İstediğiniz zaman ayrılabilirsiniz.

📬 Haftalık bülten: Teknoloji + AI haberleri