erginegider'in detaylı anlatımını:
http://www.unrealengineturkiye.com/networking-konusu.html?pid=22327#pid22327
http://www.unrealengineturkiye.com/networking-konusu.html?pid=22327#pid22327
Merhabalar,
Emin çok güzel açıklamış ama okuyan herkese faydalı olması adına biraz tafsilatlı şekilde hepsini anlatayım:
PlayerController : PlayerController oyunda bizim oynattığımız karakterin (pawn sınıfı olabilir, character sınıfı olabilir ya da bunlardan türeyebilir) "BEYNİ" gibidir. Bunu şu şekide düşünün: Bir karakteri oyunda kullanabiliyorsam bu onun beynine playercontroller hükmettiği içindir. Ya da şöyle düşüne bilirsin her karakterin beyninde bir çip var ve bu çipin ismi playercontroller. Böyle hayal ederek şimdi anlatacaklarımı hayal etmeye çalışın:
Oyun içinde bir karakter iki şekilde kumanda edilebilir. Ya oyuncu direk klavye mouse vesair her neyse elindeki komutlarla o karakteri kontrol eder (Mesela oynadığımız karakter budur). Ya da onu bir yapay zeka gibi bilgisayar onu kontrol eder (tek kişilik oyunlarda NPC ler Boss lar düşmanlar vb.). Bu nedenle iki çeşit controller var aslında. Birisi PlayerController, diğeri AIController. Bunların ikisi de Controller sınıfından türüyorlar. Yani babaları Controller sınıfı ve iki kardeş olarak birisi bizim oynadığımız karakterin beynine yerleşiyor bizimle olan bağlantısını sağlıyor. Diğeri AIController buda bizim oynatmadığımız karakterlerin beynine takılıyor ve Bilgisayarı temsil ediyor. Bir ipli kukla oyunun düşünün. Sahnede iki karakter var. Birinin ipleri sizin parmaklarınızda diğerinin ipleri ise bilgisayar işlemcisinin parmaklarında. Sahnedeki kuklaları oynatıyorsunuz. O elinizdeki ip sistemine player controller gözüyle bakabilirsiniz. Tabii ki sizin kullandığınız ve bilgisayarın kullandığı ip sistemi farklı olacak. O yüzden onun ki ayrı AIController.
Yukarıda anlattıklarımı göz önüne aldığınızda şu hususlara dikkat etmeniz lazım. Oyun içerisindeki tüm oyuncular NPC olsun Boss olsun düşman olsun ya da bizim oynattığımız karakter olsun hepsi kafalarında bir controller taşıyorlar. Sizin oynadığınız karakter kafasında bir playercontroller taşıyor. NPC ler düşmanlar ise kafalarında bir AIController taşıyorlar. Oyunda bunun haricinde hiç bir karakter kontrol edilemez (Başka şekillerde hareket ettirilebilir tabi ama ben kontrol etmekten bahsediyorum). Siz bilsenizde bilmesenizde oynattığınız karakterin bir player controller ı var ve bastığınız klavye tuşları önce o player controllera gidiyor sonra karakterinize ulaşıyor. PlayerController olmasaydı o karakteri kontrol edemezdiniz.
Siz online olmayan single player bir oyun oynadığınız da mesela oyun alanında yaratıldığınızda (Spawn) , pardon siz daha yaratılmadan bir playercontroller yaratılıyor. Bu playercontroller ın oyun içinde yaratıldığını gamemode (sonra geleceğiz) hemen fark ederek kendi bünyesinden şu soruyu soruyor "Bu player controller için hangi Pawn ı ya da karakteri spawn etmeliyim yaratmalıyım". Bulduğu cevaba göre oyunu sizin oynayacağınız karakterinizi yaratıyor (Spawn ediyor).
Online oyunlarda bir bağlantı oluşturduğunuzda UDP bağlantısı ilk sağlandığında hemen game mode bir NetPlayer oluşturuyor. Bu NetPlayer sizin kurduğunuz bağlantıyı temsil ediyor sadece. Başka bir işe yaramıyor. GameWorld bağlanan her oyuncu için yani bulduğu her NetPlayer için bir playercontroller oluşturuyor serverda. Serverda playercontroller ınız oluşunca game mode yine bakıyor bunun için oluşturmam gereken karakter nedir diye. Ona göre gelen her oyuncu için yeni bir karakter spawn ediyor level içerisinde. Yani oyuna bağlanan her gerçek oyuncu için bir adet playercontroller oluşturuluyor ki kontrol edebilsin diye. Bu serverda oluşturulan playercontroller ve onun için spawn edilen karakter replicated ise ( varsayılan olarak hepsi replicated zaten) zaten tüm client lara yani bağlı olan tüm diğer bilgisayarlara bir kopyası otomatik gönderiliyor (replicate ediliyor). Mesela online Call of Duty falan tarzi bir oyun oynadığınızı düşünelim. Karakteriniz ölüyor ama siz oyundan kopmuyorsunuz ve ölmeden önceki bir çok bilgi ölldükten sonra menüde gözükebiliyor ya da yeniden spawn olduğunuzda bir önceki durumunuza göre her şey şekilleniyor. Mesela exp. puanınız düşmüyor artmaya devam ediyor. Neden :
Çünkü öldüğünüzde sizin kullandığınız karakteriniz ölüyor aslında (destroy). Oyundan bağlantı olarak kopmuyorsunuz çünkü halen aynı NetPlayer ile oyundasınız bağlantı kopmadı daha. Bütün bilgileriniz aktarılabiliyor çünkü sizin şahsınızı temsil eden şey oynadığınız o karakter değil. O sizin sadece kuklanız. PlayerController ınız aynen duruyor ve oyun içinde halen. Bu yüzden oyunda 20 kere ölüyorsunuz ama sizin bir çok bilginiz tutuluyor hesaplanıyor ve devam ediyor. Peki bağlantım kopsa yeniden gelse ne olur o zaman: Sistem yeni bir NetPlayer ile sizi bağlar ancak sizin IP numaranızdan sizin hangi playercontroller olacağını bulup eşler ve sonrasında siz kaldığınız yerden oyuna devam edebilirsiniz.
Teori yeter.
Bu anlattıklarım ışığında şu hususlar çok büyük önem arz etmektedir:
1. Player Controller sizi temsil eder.
2. PlayerController single player yani offline oyunlar için oyunda her oyuncu için bir tanedir. Mesela online olmayan 2 kişilik oyunlarda var. StreetFighter düşünün evde oynuyorsunuz. İki kumanda var biri bir playercontroller dır diğeri diğer playercontrooller dır. Yani her oyuncu için bir adet playercontrolller vardır.
3. Online oyunlarda serverda her bağlanan oyuncu için yine birer adet playercontroller var. Bunlar tüm bağlı bilgisayarlara sürekli replicate edilerek gönderiliyorlar. Mesela 20 kişinin bağlı olduğu bir oyunu düşünelim. Serverda 20 adet playercontroller ve onlara bağlı 20 (kukla) karakter var demektir. Ancak sizin local elinizdeki bilgisayarınızda da 20 tane player controller var. Aynı oyun içinde oynayan Artvin de oturan mehmetin bilgisayarında da on an 20 playercontroller var. Ancak burda bir nokta çok önemli. Mehmet oyununu oynarken kendi kullandığı karakter localplayercontroller sadece. Diğer 19 tanesi diğerlerini temsil eden aracı (proxy) playercontrollerlar ve Mehmet ile hiç bir alakaları yok. Onlar sadece server daki eşleniklerinden gelen komutları uygulayıp boşluk kalan yerleri de simule ediyorlar.
4. Online oyunlarda bir şeyi replicate edebilmeniz için onun mutlaka serverda bir bağlı eşleniği olması lazım. Yani o obje hem local de bulunacak hemde serverda bulunacak ki ara da bir iletişim olabilsin. Bu tarz iki şey kullanabileceğiniz. Birisi karakter birisi playercontroller. Bunların dışında her iki taraftada bulunan şu an aklıma gelen başka bir şey yok. Dolayısı ile bu ikisinden birini seçmek zorundasınız. Karakteri de seçebilirsiniz playercontrollerı da seçebilirsiniz. Ancak karakteri seçerseniz karakter ödüğünde ne olacak bunu hesap etmelisiniz. Mesel exp. puanı diyelim. Bunu karakterde tutmayı ve oradan servera göndermeyi replicate etmeyi planladınız. Çok güzel. Karakter öldüğünde bu bilgi data uçacak. O zaman kulağınızı tersten tutmak gibi başka çözümler bulmanız lazım. Karakter öldüğünde halen yaşayan varolan birşey bulup ona aktarıp yeni spawn olana ordan çekebilirsiniz. Bir karakter ödüğünde aslında oyunda halen bir game mode bir game instance duruyor. Bir de playercontroller ınız duruyor. Evet uğraşıp öldüğünzüde gamemode a gameinstance a her şeyi kaydedip (mesela exp diyelim örnek olsun) sonra yeni spawn olan karakterde oradan çekebilirsiniz. Ama o objeler karaktere özel değilller. Oyunda 20 kişi için sadece bir adet gamemode bir adet gameinstance var. O zaman kendisine özel olan player controller ı kullanmak daha mantıklı değilmi. Bunu anladınız artık sanırım. Peki daha iyi bir çözüm bu tür tüm bilgileri baştan Playercontroller da tutmak daha mantıklı değil mi. Karakter isterse 100 kere ölsün player controller hep aynı ve bir sürü uğraşmak zorunda kalmazdınız. İşte bu nedenle Multiplayer Online oyun dediğinizde replication dediğinizde ilk ama ilk aklınıza gelmesi gereken birinci yer PlayerController dır.
5. Kod yazarken playercontroller için bir BP ya da class yazıyorsanız, bu kodun hem local kontrol edilen karakterin kafasında hemde diğer oyuncuları temsilen diğer oyuncuların kafasında da çalışacağını düşünmeniz gerekir. O yüzden IsLocallyControlled, IsLocalPlayerController vb. branch if cümleleri var. Bunları kontrol etmeniz lazım. Bu kod tüm hepsinde mi çalışsın yoksa ben sadece kontrol edileni mi kasdediyorum vb.
Özetle Player Controller konusunu bitirdik diyelim.
Şimdi GameMode:
GameMode oyun her kurulduğunda ( Level ya da map yüklendiğinde) ilk yaratılan şeydir. Levelin başında yaratılır ve level değişene kadar yok olmaz. Ancak multiplayer oyunlarda sadece serverda bulunur. Client larda bulunmaz. Single player oyunlarda o PC aynı zamanda kendi kendinin server ı sayıldığından bir adet bulunur.
GameMode tüm oyun kurallarını oyunun genel işleyişini kontrol eder. Hangi playercontroller hangi karakteri spawn edebilir hangisini edemez, kazanma şartları nelerdir. Bu tarz konularla uşraşır. Bir Call of duty online oyununda "death match" "team deathmatch" "free for all" gibi şeyler görürsünüz. Bu modların hepsi başka bir game mode dur. Yani o oyunlarda deathmatchgamemode ve freeforallgamemode gibi farklı varyasyonlarını görürsünüz. Oyun alanında sadece bir tane bulunur ve her yerden her zaman ulaşılabiliir. Yani karakter de istediği an ona ulaşabilir playercontroller da ulaşabilir. Ancak replication için kullanılamaz. Çünkü client larda yani bağlı bilgisayarlarda bir örneği ve eşleniği yoktur. Bir client gamemode a ulaşmaya çalışırsa öyle bir şeyin olmadığını görecektir (nullptr). Peki neden böyle dizayn edilmiş. Çünki cheat yani hile yi önlemek için çok etkili bir yöntem. Bir PES ya da FIFA oyunun düşünün. Hangi takım kaç gol attı bunu game mode da tutarsanız ve oda sadece serverda olduğu için bunu birisinin crack lemesi hile yapması imkansız hale gelir.
1. Gamemode da karakterleri ya da oyuncuları bire bir ilgilendiren değil oyunun genelini ilgilendiren datalar bilgiler tutulur. Bir futbol oyununda mesela karakterin bacağının ağrıdığı bilgisini karakterin kendisinde, o maçta kaç gol attığının bilgisini playercontroller da , iki takım arasında maçın kaç kaç olduğunun bilgisini ise Game mode da tutmak en mantıklıdır.
2. Her yerden ulaşılabilir olması bazı durumlarda onu aracı olarak kullanmaya yarayabilir. Bir bilgiyi orada tutarsanız o bilgi server da level bitene kadar kalır. Dikkat level bitene kadar. Mesela bölüm değiştiğinde Gamemode yok edilir ve yeni level için yep yeni bir tane oluşturulur.
3. GameMode replication için kullanılamaz ancak kendisine başvuran tüm playercontroller larla direk bağlantısı vardır. Ayrıca sadece serverda bulunması kısıtlamasını aşmak için GameState ve PlayerState de GameMode dan çok kolay ulaşılabilir. Yani tüm bunları kontrol eden büyük abi kendisidir.
Şimdi PlayerState e gelelim:
PlayerState: Yukarıda bazı bilgilerin bazı sebeplerle şurada burada tutulması gerekebileceğini anlatmıştım. Aslında playerstate tam bu iş için yapılmış özel bir sınıftır. Yani tek görevi player hakkında bilgileri tutmak, server ile gitip gelmesini replication yapılmasını sağlamaktır. Yani çok fazla bilgi tutmanız gerekiyorsa ki gerçek bir oyun geliştiriyorsanız bunun hemen 20 30 bilgiye çıktığını göreceksiniz, size karakter sınıfı veya playercontroller sınıfı yetmeyecektir. Daha doğrusu bu sınıfların kodlarının sırf bu yüzden çorbaya döndüğünü iyice karıştığını göreceksiniz. Bu yüzden oyundaki her kişi için ayrı bir player state tutulur. Bütün kayıtlarınızı bunda tutabilirsiniz. Bu replicate de edilir. Yani iletişimi de sağlar. Ayrıca GameMode dan PlayerController dan çok kolay kendisine ait playerstate çekilebilir. Her oyuncu için ayrı olduğundan bir birine karışması da söz konusu değildir. Mesela futfol oyunu için yorgunluk seviyesi, kaç gol attığı, oyunda kaç dakika bulunduğu vb bilgiler burada tutulabilir.
1. Oyunda multi olsun single olsun bir level kapatılıp yeni bir level açıldımı tüm herşey yok olup yeniden yaratılırlar. Buna herşey dahildir (Bir istisna var anlatacağım). Herşey yok olur. Gamemode dahil. Playercontroller lar dahil. Bir level den diğer level veri aktrarmanın en mantıklı yolu playerstate kullanmaktır. Sırf bunun için CopyProperties fonksiyonu bulunmaktadır.
2. Heryerden çok kolay ulaşılabildiğinden biraz orta yada büyük ölçekli oyun yapıyorsanız kullanmanız çok mantıklıdır.
3. Serialization yani kayıt sistemini destekler. Playercontroller ı direk kaydedemessiniz dosya olarak diske ama bunu kaydedebilirsiniz. Tekrar oyun açıldığında yüklenmesini sağlayabilirsiniz.
4. Data tutmak içindir burada bir fonksiyon bir iş yapılmamalı (mümkün olduğunca).
Yoruldum şimdi GameState e gelelim:
GameState için de tüm playerstate leri tutan bir objedir. Serverda bir tane her bilgisayarda birer tane vardır. Game modun replicasyon işlerini yürütüyor diyelim. İçinde tüm playerstate ler de olduğu için playerstateler onun vasıtası ile her yere gönderilebilirler. Oyundaki tüm oyuncuların durumunu bir yerde tutmuş olur. Gamemodedan kolaylıkla ulaşılabilir.
1.PlayerStatelerin toplu halede bir yerde bulunup gönderilmesi içindir.
2. Data tutmak içindir bir işlev içermemelidir.
GameInstance:
Tüm anlattıklarım içerisinde multiplayer le hiç bir ilgisi olmayan tek şeydir. GameInstance ı oyunun EXE si olarak düşünün. Yani bildiğiniz masa üstünüzde ki ikona çift tıklıyorsunuz ve oyununuz açılıyor. Aslında oyun açılmıyor GameInstance açılıyor. Oyunu kapattığınızda da yok oluyor. Biraz önce level geçişlerinde kaybolamayan tek bir şey olduğunu söylemiştim. O işte bu gameinstance oyunu siz "Oyundan çık" diyerek kapatmadıkça bu hayatta ve yaşıyor. Çoğu yerden yine gameinstance a ulaşabilirsiniz. Ancak bunu multi ile iligili hiç bir alakası yoktur. Oyuna 1000 kişi bağlanmış 1 kişi bağlanmamış hatta oyun single playermış gameınstance ı ilgilendirmez. O sadece sizin önünüzde çalışan program parçasıdır.
1. Yapısı itibari ile level geçişleri ile ilgili şeylerde işe yarayabilir.
2. Mesela Ana menu buraya koyulabilir. Oyun açıldığında ekran gelsin diye. Buradan diğer leveller açılabilir.
3. Multiplayer ile ilgili hiç bir konuda hiç bir işe yaramaz.
Sanırım çoğu şeye değindim. Önemli den önemsize gitmeye çalıştım. O yüzden uzun anlattıklarım en önemli diye düşünebilirsin..
Faydalı olması dileğiyle, kolay gelsin.