Çok oyunculu oyunlarda oyuncu takımları bir hedefe ulaşmak için rekabet eder ya da işbirliği yapar. Her takımdaki oyuncu sayısı, oynanışı çarpıcı biçimde etkileyebilir ve birçok geliştirici, eğlenceli deneyimler yaratmak için belirli oyuncu oranlarını seçer.
Takım dengeleme, belirli bir orana uyarak oyuncuları takımlara ayırır. Çoğu çok oyunculu oyun, hiçbir takımın avantajlı olmaması için takımları eşit olacak şekilde dengeler. Bazı oyunlar, aşırı güçlü bir oyuncunun karşısına dört oyuncu koymak gibi dengesiz senaryoları kasıtlı olarak oluşturur. Kurulumdan bağımsız olarak takım dengesi, birden fazla oyuncu takımı için ilgi çekici deneyimler yaratmanın ayrılmaz bir parçasıdır.
Bu kılavuzu tamamlayarak çalışma zamanında ve oyuna yeni bir oyuncunun katıldığı her durumda oyuncu takımlarını dinamik olarak dengelemeyi öğreneceksin. Tam kod, referans olması için bu kılavuzun sonuna eklenmiştir.
Kullanılan Verse Dili Özellikleri
array: Bu cihaz, her takımın bir referansını depolamak için diziler kullanır.
option: Bu cihaz, bir oyuncunun o anda bulunduğu takımdan daha az oyuncuya sahip bir takımın olup olmadığını belirlemek için seçenekleri (option) kullanır.
for: için (for) ifadesiyle cihazın kullandığı dizileri yineleyebilirsin.
if:eğer (if) ifadesi, oyuncuların takım boyutlarına göre yeni bir takıma geçmesinin gerekli olup olmadığını kontrol etmek için kullanılır.
failure: Başarısızlık (failure) bağlamları, dizilere erişmek ve programın akışını kontrol etmek için kullanılır.
Kullanılan Verse API’leri
Bağlanılabilir: Sürmekte olan bir oyuna yeni bir oyuncu katıldığında takımları dinamik olarak yeniden dengelemek için
PlayerAddedEvent()öğesine bağlanırsın.Takımlar: Takım sınıfı; takımlara oyuncu ekler, takımlardan oyuncuları kaldırır ve alır. Bu eğitimde oyuncuları ve takım görevlerini doğrudan yönlendirmek için takım sınıfını kullanacaksın.
Oyun Alanı: Oyun alanı, oyuna katılan ve oyundan ayrılan oyuncularla ilgili bağlanılabilir olayları takip eder. Aynı zamanda oyuncu ve takımların listelerini alır ve belirli bir oyuncunun takımını bulur. Bu eğitimde birden fazla oyun alanı olayına bağlanacak, oyuncuları ve takımları oyun alanı yöntemlerini kullanarak alacak ve böylece onları doğrudan yönetebileceksin.
Bölümü Kurmak
Bu örnekte aşağıdaki cihaz kullanılıyor.
4 adet Oyuncu Doğma Karesi cihazı: Bu cihaz, oyuncunun oyun başlangıcında nerede doğacağını belirler.
Bölümünü ayarlamak için şu adımları izle:
Bölüme bir Oyuncu Doğma Karesi ekle.
Anahat Düzenleyicisi’nde doğma karesini seçerek Ayrıntılar panelini aç.
Ayrıntılar panelinde Kullanıcı Seçenekleri altında:
Oyuncu Takımı’nı 1 değerine sahip Takım Dizini olarak ayarla
Oyunda Görünürlüğü Etkinleştir
Büyütmek için görsele tıkla.
Doğma karesini kopyala ve birinci doğma karesinin yanına yerleştir.
Her iki doğma karesini de çoğalt ve birinci doğma kareleri grubundan uzakta bir yere yerleştir. 2. takımın oyuncularının burada doğar.
Çoğaltılan doğma karelerini seç ve Ayrıntılar panelindeki Kullanıcı Seçenekleri bölümünün altından her iki doğma karesinin Takım Dizini değerini 2 olarak değiştir.
Anahat Düzenleyicisi fonksiyonunda Ada Ayarları Cihazını seçerek Ayrıntılar panelini aç. Kullanıcı Seçenekleri - Oyun Kuralları altında:
Takımları 2 değerine sahip Takım Dizini olarak ayarla. Bu örnekte iki takım kullanılıyor ancak dilediğin sayıda takımın olabilir.
Takım Boyutu fonksiyonunu Dinamik olarak ayarla. Bu ayarla Verse kodun takım dengeleme işini devralabilir.
Yeni oyuncuların oyun devam ederken katılabilmesi için Sürmekte Olan Oyuna Katılma ayarını Doğma olarak belirle.
Büyütmek için görsele tıkla.
Verse Gezgini öğesini kullanarak team_multiplayer_balancing adlı yeni bir Verse cihazı oluştur ve cihazı bölüme sürükle. (Verse’te yeni bir cihazın nasıl oluşturulacağını öğrenmek için Verse Kullanarak Kendi Cihazını Oluşturma bölümüne bakabilirsin.)
Bölümün şu kuruluma benzer şekilde görünmelidir:
Takımları Eşit Olarak Ayırma
Oyun Başlangıcında Takımları Dengeleme
Bu adımda oyun başlangıcında ve oyuna yeni bir oyuncu katıldığında oyuncuların takımlara nasıl eşit olarak ayrılacağı gösteriliyor.
Verse Gezgini’ni aç ve team_multiplayer_balancing.verse dosyasına çift tıklayarak kodu Visual Studio Code ile aç.
team_multiplayer_balancingsınıf tanımında oyuncuların bulunduğu her bir takımda referansları depolayacakTeamsadlı bir değişkentakımdizisi ekle.Verseteam_multiplayer_balance := class(creative_device): # Holds the teams found with GetTeams() var Teams : []team = array{}OnBegin()fonksiyonundaTeamsdizisini daha önce Ada Ayarları içinde ayarlanan takımlarla eşleşecek şekilde güncelle. Oyun alanındaki tüm takımları almak içinfort_team_collectionAPI’sindenGetTeams()fonksiyonunu çağır.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()GetPlayers()fonksiyonunu çağırarak oyundaki tüm oyuncuları bul veAllPlayersadlı bir oyuncu dizisine kaydet.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() AllPlayers := GetPlayspace().GetPlayers()Tüm oyuncuların listesini yinele ve aynı sayıda oyuncuya sahip takımlar oluştur. Bir oyuncunun o anda bulunduğu takımı başka bir takımla karşılaştırıp oyuncu için en uygun takım olup olmadığını belirleyebilirsin. Bu durumda,
GetTeam[]fonksiyonunu kullanarak oyun başladığında oyuncunun otomatik olarak atandığı takımı kullanabilirsin (çünkü oyuncular birden fazla takımın olduğu oyun modlarında bir takıma dahil olmak zorundadır).GetTeam[]fonksiyonu, aracı türünde bir parametre gerektirir ancak oyuncu aracı alt sınıfı olduğundan oyuncuyu tür dönüştürme olmadan geçirebilirsin.VerseAllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalancedTakım bir iç sınıf olduğundan başlatılamaz ve yalnızca var olan bir takım objesinin referansı olarak kullanılabilir.
Tüm takımlar dengelenene kadar oyuncuları en az sayıda oyuncuya sahip takıma ataman gerekir. Bunu yapmak için her oyuncuyu ve sonra her takımı bir
fordöngüsü kullanarak kontrol etmen gerekir. Biri oyuncuları yinelemek ve diğeri takımları yinelemek üzere iki for döngüsü kullanabilirsin ancak bu örnekte takım for döngüsünü kendi yöntemi içine çıkaracaksın. Her bir oyuncunun referansını ve sonra oyuncuların bulunduğu her bir takımın referansınıCurrentTeamadlı bir sabite alarak oyuncu for döngüsünü ayarla.TeamSizeadında yeni bir değişken tamsayı oluştur ve0ile başlat, ardından bu oyuncunun o anda bulunduğu takımın boyutuna eşit olacak şekilde ayarla.GetAgents[]başarısız olabilir ifadesi olduğundan bu kümeyi bir if ifadesi içine almalısın.Versefor (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalanced var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")FindSmallestTeam()adlı bir metot oluştur. Bu metot,TeamSize’ı bağımsız değişken olarak geçirdiğinde isteğe bağlı bir takım (?team) döndürür ve en az sayıda oyuncuya sahip takımı bulma ve döndürme işlemlerini üstlenir.FindSmallestTeam()içindeSmallestTeamadlı yeni bir takım seçeneği başlat.FindSmallestTeam()fonksiyonunu çağırdığında oyuncu zaten en küçük takımda olabileceğinden burada bir seçenek kullanırsın.SmallestTeamseçeneğin varsayılan olarak false olduğundan, daha küçük bir takım bulunmazsafalseolarak kalır.FindSmallestTeam()fonksiyonu,falsedeğerini döndürürse belirtilen oyuncunun zaten en küçük takımda olduğunu kesin olarak bilirsin. AyrıcaCurrentTeamSizedeğişken tamsayısınıTeamSizedeğeriyle başlatman gerekir. Daha az oyuncuya sahip başka bir takımın boyutuna güncellenebilmesi içinCurrentTeamSizedeğerinin değişken olması gerekir.VerseFindSmallestTeam(CurrentTeamSize : int) : ?team= var SmallestTeam : ?team = false var TeamSize : int = CurrentTeamSizeTeamSizedeğeri,SmallestTeamboyutunu takip ettiğinden bu değeri her takımın boyutuyla karşılaştırman gerekir. Her bir takımı yinele ve takımların boyutunuCandidateTeamSizeadlı yerel tamsayı olarak al.CandidateTeamSizedeğeriTeamSizedeğerinden küçükseSmallestTeamdeğerini bu takıma,TeamSizedeğerini ise bu takımın boyutuna ayarla.TeamSize > CandidateTeamSizekoşulu for döngüsünün parantezi içinde kontrol edildiğinden bir filtre koşuludur. Filtre koşulu kullanmak, döngünün içindeki kodun yalnızca filtre koşulu başarılı olursa çalışmasını garanti eder. Bu daSmallestTeamdeğerinin, bulunması halinde en az oyuncuya sahip takıma ayarlanmasını garanti eder. Daha az oyuncuya sahip bir takım bulunamazsaSmallestTeamfalse olarak kalır.Son olarak tüm takımlar kontrol edildikten sonra
SmallestTeamdeğeri döndürülür.Versefor(Team : Teams, CandidateTeamSize := GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize): set SmallestTeam = option{Team} set TeamSize = CandidateTeamSize Print("Found a team with less players: {CandidateTeamSize}") return SmallestTeamOnBegin()fonksiyonundafordöngüsünün içindeSmallestTeamadlı yeni bir takım seçeneği oluştur veTeamSizebağımsız değişken olarak geçirildiğindeFindSmallestTeam()değeriyle başlat.VerseSmallestTeam : ?team = FindSmallestTeam(TeamSize)Ardından
SmallestTeamisteğe bağlı değişkenindeki değere erişmeyi dene. Değer false ise oyuncu zaten en küçük takımdadır ve bir atama gerekli değildir. Aksi takdirde oyuncuyu yeni takımına ataman gerekir. Birçok yöntem, bir seçeneği doğrudan bağımsız değişken olarak geçirmemize izin vermediğinden değeriTeamToAssignyerel değişkenine çıkarman gerekir.AddToTeam[player, team]kullanarak bir oyuncuyu bu takıma atamayı deneyebilirsin. Bir oyuncuyu zaten ait olduğu takıma atamayı denersen bu atamanın başarısız olacağını unutma. Bunun herhangi bir negatif etkisi olmaz ancakfordöngüsü yalnızca bir sonraki oyuncuya yinelenir ve birinci oyuncuyu ilk takımında bırakır.Verseif (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")
OnBegin(), aşağıdaki kod bloğu gibi görünmelidir.VerseOnBegin<override>()<suspends> : void = Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() Print("Beginning to Assign Players") Playspace := GetPlayspace() AllPlayers := Playspace.GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := Playspace.GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = Playspace.GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")
Oyun Sırasında Katılan Oyuncuyu İşleme
Takımları sürmekte olan bir oyun için de otomatik dengeleyebilmek istediğinden yeni bir oyuncu katıldığında başlatılan olaya abone olman gerekir. Yeni yazdığın tüm kodları tekrarlamak istemeyeceğinden bir ortak yönteme yeniden düzenleyebilirsin.
BalanceTeams()adlı bir metot oluştur veGetTeams()kullanarakTeamsdeğişkenini ayarladıktan sonraki tüm kodu taşı. Bu metotOnBegin()metodu içinde çağrılır, böylece oyun başladığında takımların dengeli olması sağlanır.BalanceTeams()aşağıdaki gibi görünmelidir.VerseBalanceTeams() : void = AllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}") SmallestTeam : ?team = FindSmallestTeam(TeamSize) if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")BalanceTeams()metodunu bir çağrı içerenOnPlayerAdded()adlı başka bir metot oluştur.Playerdeğişkenini kullanmayacak olsan da bu değişken, metot tanımı için gereklidir çünküPlayerAddedEvent()olayına bu metodu kullanarak bağlanırsın. Bağlanılabilir olaylar hakkında daha ayrıntılı bilgi için Cihaz Etkileşimlerinin Kodlanması sayfasına bakabilirsin.VerseOnPlayerAdded(InPlayer : player) : void = Print("A new Player joined, assigning them to a team!") BalanceTeams()OnBegin()içindeOnPlayerAddedkullanarakPlayerAddedEvent()oyun alanına bağlan. Şimdi oyuna bir oyuncu katıldığındaOnPlayerAdded, takımları otomatik olarak dengelemek içinBalanceTeams()fonksiyonunu çağırır.VerseOnBegin<override>()<suspends> : void = GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) Print("Beginning to balance teams") BalanceTeams()Kodu Visual Studio Code’a kaydet ve Verse Kodu Oluştur’a tıklayarak kodunu derle.
Bölümün oynanış testini yapmak için UEFN araç çubuğunda Oturumu Başlat düğmesine tıkla.
Bölümüne oynanış testi uygulamak için her bir takımın boyutunu ve kodun yazdırılan çıktı günlüğünde bulduğu daha küçük takımları görebilmen gerekir. Oyuncular takımlar arasında eşit olarak dağıtılmış olmalı ve oyuna katılan her yeni oyuncu bu eşitlenmiş dengeyi korumalıdır.
Tam Kod
Aşağıdaki kod, oyuncu takımlarını otomatik olarak dengeleyen bir cihazın tam kodudur.
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
team_multiplayer_balance := class(creative_device):
# Holds the teams found with GetTeams()
var Teams : []team = array{}
OnBegin<override>()<suspends> : void =
Print("Verse Device Started!")
Kendi Kendine Yapabileceklerin
Bu kılavuzu tamamlayarak oyuncu takımlarını otomatik olarak dengeleyen bir cihazı Verse kullanarak oluşturmayı öğrenmiş oldun.
Öğrendiklerini kullanarak bir oyuncuya karşı dört oyuncu gibi asimetrik oyun modları için kasıtlı olarak dengesi bozulmuş takımlar oluşturmayı dene.