Bu bölümde, oyuncular için takım ve sınıfları nasıl belirleyeceğin ve özelleştireceğin gösterilir.
Kullanılan cihazlar:
-
2 adet Takım Ayarları ve Çantası
-
2 adet Sınıf Tasarlayıcı
-
2 adet Sınıf Seçici
Takım Ayarı ve Çantası

Puan tablosu ekranı için takım adları ve renkleri ayarlamak üzere Takım Ayarları ve Çantası cihazlarını kullan.
Her takım için bir cihazı oyuncular tarafından görülmeyen bir alana yerleştir. Nesne takımını ayarlamak için Kullanıcı Seçenekleri’ni aşağıdaki tabloyla eşleşecek şekilde yapılandır.

Seçenek | Değer | Açıklama |
---|---|---|
Takım Adı | Nesneler | Puan Tablosu ve Gösterge Paneli öğelerinde takımı belirtecek olan metni ayarlar. |
Takım Rengi | Gök Mavisi | Takımların puan tablosunda, Gösterge Panelinde ve belirli cihazlarda hangi renklerle görüneceğini belirler. |
Takım | Takım Dizini: 1 | Bu cihazdaki ayarların hangi takıma uygulanacağını belirler. |
Avcı takımını ayarlamak için diğer cihazın Kullanıcı Seçenekleri’ni aşağıdaki tabloyla eşleşecek şekilde yapılandır.

Seçenek | Değer | Açıklama |
---|---|---|
Takım Adı | Avcılar | Puan Tablosu ve Gösterge Paneli öğelerinde takımı belirtecek olan metni ayarlar. |
Takım Rengi | Turuncu | Takımların puan tablosunda, Gösterge Panelinde ve belirli cihazlarda hangi renklerle görüneceğini belirler. |
Takım | Takım Dizini: 2 | Bu cihazdaki ayarların hangi takıma uygulanacağını belirler. |
Sınıf Tasarlayıcı

Yeni oluşturduğun takımları değiştirmek için bir Sınıf Tasarlayıcı kullan.
Her takım için bir adet olacak şekilde iki Sınıf Tasarlayıcı cihazını, oyuncular tarafından görülmeyen bir alana yerleştir. Nesne takımını özelleştirmek için Kullanıcı Seçenekleri’ni aşağıdaki tabloyla eşleşecek şekilde yapılandır.
Seçenek | Değer | Açıklama |
---|---|---|
Sınıf Adı | Nesne | Bu sınıfın adını belirler. |
Sınıf Açıklaması | Avcılardan saklan. Hayatta kal. | Bu sınıfın açıklamasını ayarlar. |
Sınıf Tanımlayıcısı | Sınıf Yuvası: 1 | Bu sınıf için benzersiz tanımlayıcıyı ayarlar. |
Maksimum Can | 1 | Oyun sırasında oyuncuların ulaşabileceği maksimum can miktarını belirler. Nesneler tek bir isabetle avlanır. |
Eşya Listesi | Nesnematik | Bu sınıfın sahip olacağı eşyaların listesini ayarlar. |
Verilen Eşyayı Kuşan | İlk Eşya | Listedeki hangi eşyanın kuşanılacağını belirler. |
Avcı takımını özelleştirmek için diğer cihazın Kullanıcı Seçenekleri’ni aşağıdaki tabloyla eşleşecek şekilde yapılandır.

Seçenek | Değer | Açıklama |
---|---|---|
Sınıf Adı | Avcı | Bu sınıfın adını belirler. |
Sınıf Açıklaması | Nesneleri bul. Onları avla. | Bu sınıfın açıklamasını ayarlar. |
Sınıf Tanımlayıcısı | Sınıf Yuvası: 2 | Bu sınıf için benzersiz tanımlayıcıyı ayarlar. |
Eşya Listesi | Fenerli Tabanca | Bu sınıfın sahip olacağı eşyaların listesini ayarlar. |
Verilen Eşyayı Kuşan | İlk Eşya | Listedeki hangi eşyanın kuşanılacağını belirler. |
Sınıf Seçici

Oluşturduğun özelleştirilmiş sınıfları ve takımları yönetmek için Sınıf Tasarlayıcıyı Sınıf Seçiciyle eşleştir.
Verse ile birlikte, bu cihazdaki ayarlar, 1. Sınıf Yuvasındaki oyuncular yeniden çıkarıldıklarında bu oyuncuların 2. Sınıf Yuvasına aktarılmasına sebep olur.
Her takım için bir adet olacak şekilde iki Sınıf Seçiciyi, oyuncular tarafından görülmeyen bir alana yerleştir. Nesne takımını yönetmek için bu cihaza ilişkin Kullanıcı Seçenekleri’ni yapılandırmak amacıyla aşağıdaki tabloda yer alan ayarları kullan.

Seçenek | Değer | Açıklama |
---|---|---|
Geçiş Yapılacak Sınıf | Sınıf Yuvası: 1 | Oyuncunun geçiş yapması gereken sınıfı belirler. |
Oyun Sırasında Görünür | False | Bu cihaz oyun içinde görünmeyecektir. |
Bölge Sesi | False | Oyuncular bölgeye girdiğinde Sınıf Seçicinin ses efektleri çalıp çalmayacağını belirler. |
Geçiş Yapılacak Takım | Takım Dizini: 1 | Oyuncunun geçiş yapacağı takımı belirler. |
Geçişte Eşyaları Temizle | True | Geçiş uygulandığında oyuncunun çantasındaki eşyaların kaldırılıp kaldırılmayacağını ayarlar. |
Etki Aktörü Oyunda Görünür | False | Cihazın etki aktörünün oyun sırasında görünür olup olmayacağını belirler. |
Etkinleştirmede Görsel Efekti Görüntüle | False | Bir oyuncunun sınıfını veya takımını değiştirirken cihazın bir görsel efekt oluşturup oluşturmayacağını belirler. |
Avcı takımını yönetmek için bu cihaza ilişkin Kullanıcı Seçenekleri’ni yapılandırmak amacıyla aşağıdaki tabloda yer alan ayarları kullan.

Seçenek | Değer | Açıklama |
---|---|---|
Geçiş Yapılacak Sınıf | Sınıf Yuvası: 2 | Oyuncunun geçiş yapması gereken sınıfı belirler. |
Geçiş Yapılacak Takım | Takım Dizini: 2 | Oyuncunun geçiş yapacağı takımı belirler. |
Verse ile Takım İşlevselliği Oluşturma
Bu Nesne Avı oyununda, Avcılar ve Nesneler olmak üzere iki takım vardır. Oyunun işleyebilmesi için her iki takım için de aynı şeylerden bazılarını yapabilmen gerekir. Örneğin:
-
bir takıma oyuncu ekleme
-
bir takımdan oyuncu çıkarma
-
oyunculara takımlarıyla ilgili bilgiler gösterme
Kod kopyalamadan her iki takım için de bu işlevselliği oluşturmak için <abstract>
belirleyicisiyle bir sınıf oluşturacaksın. abstract
belirleyicisini içeren sınıfların, alt sınıflarının devraldığı ve daha da geliştirdiği kısmi bir işlevselliğe sahip olması amaçlanır. Öncelikle base_team
adında bir soyut sınıf oluşturacak ve bu soyut sınıfa hem Nesne hem de Avcı takımlarında ortak olarak bulunacak işlevselliği vereceksin.
Bu belge, bu oynanışta ihtiyaç duyulan oyun mekaniğinin nasıl yürütüleceğini gösteren Verse kod parçacıkları içerir. Aşağıdaki adımları izle ve bu eğitimin 6. adımındaki kodun tamamını kopyala.
Projende base_team.verse adlı yeni bir Verse dosyası oluştur. Bu bir Verse cihazı olmayacağından onu boş bir Verse dosyası olarak oluşturabilirsin.
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_team := class(log_channel){}
# Bu sınıf, deneyimdeki farklı takımlar için gereken cihazları tanımlar.
# Bu sınıf soyut olduğundan tek başına kullanılamaz. Başka bir sınıf tarafından devralınması gerekir.
base_team := class<abstract>:
Logger:log = log{Channel:=log_team}
@editable # Takıma bir oyuncu ayarlamak için kullanılır.
ClassSelector:class_and_team_selector_device = class_and_team_selector_device{}
@editable # Takımdaki aracılara puan vermek için kullanılır.
ScoreManager:score_manager_device = score_manager_device{}
@editable # Takım görevi başlığını görüntülemek için kullanılır.
TeamTitle:hud_message_device = hud_message_device{}
@editable # Takım görevi açıklamasını görüntülemek için kullanılır.
TeamDescription:hud_message_device = hud_message_device{}
@editable # Takım üyesi (nesne takımı) veya düşman (avcı takımı) avlanma olaylarına bağlanmak için kullanılır.
TeamManager:team_settings_and_inventory_device = team_settings_and_inventory_device{}
# Bu, takımdaki aracıların bir dizisidir.
var TeamAgents<private>:[]agent = array{}
# Bu olayın işareti, TeamAgents dizisi boşaldığında verilir (raundun sonuna işaret eder).
TeamEmptyEvent:event() = event(){}
# Geçerli TeamAgents dizisini döndürür.
# Bu gereklidir, çünkü TeamAgents dizisi özel olduğundan diğer sınıflar ona doğrudan erişemez.
GetAgents()<decides><transacts>:[]agent =
TeamAgents
# TeamAgents dizisinin boyutunu döndür
# Bunun için bir fonksiyon gerekir, çünkü TeamAgents dizisi özel olduğundan diğer sınıflar ona doğrudan erişemez.
Count()<transacts>:int =
TeamAgents.Length
# Bir aracının TeamAgents dizisindeki bir dizini döndürür, aksi takdirde başarısız olur.
FindOnTeam(Agent:agent)<decides><transacts>: int =
Index := TeamAgents.Find[Agent]
# Aracıyı takıma ayarla ve oyuncuyu bilgilendir.
InitializeAgent(Agent:agent):void =
AddAgentToTeam(Agent)
ClassSelector.ChangeTeamAndClass(Agent)
DisplayTeamInformation(Agent)
# TeamAgents’a bir aracı ekle.
AddAgentToTeam(AgentToAdd:agent):void =
if (not FindOnTeam[AgentToAdd]):
Logger.Print("Aracı takıma ekleniyor.")
set TeamAgents += array{AgentToAdd}
# Oyuncuya hangi takımda olduğunu göstermek için Gösterge Paneli mesajı cihazlarını etkinleştirir.
DisplayTeamInformation(Agent:agent):void =
TeamTitle.Show(Agent)
TeamDescription.Show(Agent)
# Bir aracı maçtan ayrıldığında, onu TeamAgents dizisinden kaldır ve raundun sonunu kontrol et.
EliminateAgent(Agent:agent)<suspends>:void =
Sleep(0.0) # Devam etmeden önce oyuncunun yeniden çıkarılmasını sağlamak için 1 oyun tikini geciktirme.
RemoveAgentFromTeam(Agent)
# TeamAgents’tan bir aracıyı kaldır.
# Kaldırılan aracı sonuncuysa, TeamEmptyEvent’e sinyal ver.
RemoveAgentFromTeam(AgentToRemove:agent):void =
set TeamAgents = TeamAgents.RemoveAllElements(AgentToRemove)
Logger.Print("Takımda kalan aracıları {Count()}.")
if (Count() < 1):
Logger.Print("Takımda aracı kalmadı. Raunt sonlandırılıyor.")
TeamEmptyEvent.Signal()
Artık bu sınıfa sahip olduğuna göre, Nesne takımı ile Avcı takımına ilişkin sınıfları oluşturabilirsin. Bunların her biri base_team
’den devralacağından birkaç avantaj söz konusudur:
-
Her takımın uygulanmasına yönelik kod çok daha kısadır, çünkü bunların ortak fonksiyon ve verileri zaten
base_team
’de tanımlanmış durumdadır. -
Hangi kodun Nesne ve Avcı takımlarına özel olduğunu anlamak daha kolaydır, çünkü bunlar, ortak kod içine karıştırılmak yerine kendi sınıflarındadırlar.
-
Oyun moduna daha fazla takım eklemek çok daha kolaydır. Tüm yeni takımlar
base_team
’den devralır ve yeni bir takımı farklı kılan kod onun kendi sınıfındadır.
<abstract>
belirticisiyle bir sınıfın örneğini oluşturamayacağını unutma. Soyut sınıftan devralan bir sınıf oluşturman ve bu sınıfın örneğini oluşturman gerekir.
Avcı Takımı
Öncelikle Avcı takımına ilişkin sınıfı oluştur. Projende hunter_team.verse adlı yeni bir Verse dosyası oluştur. Bu bir Verse cihazı olmayacağından onu boş bir Verse dosyası olarak oluşturabilirsin.
hunter_team
adlı bir sınıf bildir. Bu sınıf <concrete>
olmalı ve ayrıca base_team
’den devralmalıdır.
hunter_team := class<concrete>(base_team):
Bir sınıfı <concrete>
yapmak, sınıfın tüm alanlarının varsayılan bir değere sahip olması gerektiği anlamına gelir. Daha fazla bilgi için Belirleyiciler ve Öznitelikler bölümüne bak.
Aşağıda hunter_team.verse betiğinin tam kodu yer almaktadır.
hunter_team
sınıfının, base_team
sınıfındaki fonksiyonlarla aynı adı taşıyan iki fonksiyonu vardır. Buna izin verilir çünkü her ikisi de <override>
belirleyicisine sahiptir. Bunun sonucunda, bu fonksiyonlar hunter_team
’in bir örneğinde çağrıldığında hunter_team
sınıfındaki sürüm kullanılır.
Örneğin, aşağıdaki kodda hunter_team
’de tanımlanan InitializeAgent()
sürümü kullanılır çünkü bu sürüm, base_team
’de aynı adı taşıyan fonksiyonu geçersiz kılar. Bunu, geçersiz kılma fonksiyonu olmadığından base_team
’de tanımlanan sürümü kullanacak olan Count()
’a yönelik çağrıyla karşılaştır.
HunterTeam:hunter_team = hunter_team{}
# hunter_team’deki fonksiyonu kullanır
HunterTeam.InitializeAgent(StartingHunterAgent)
# base_team’deki fonksiyonu kullanır
HunterTeam.Count()
Bu geçersiz kılınmış iki fonksiyon (super:)
’ı da kullanır. Bu sayede, base_team
’de tanımlanan fonksiyonların sürümünü çağırabilirler, çünkü base_team
, hunter_team
’in üst sınıfıdır. InitializeAgent()
ile EliminateAgent()
durumunda ise her ikisi de günlüğe bir şey yazdırmak için Logger.Print()
’i kullanır. Ardından base_team
’den ilgili fonksiyonlarını çağırırlar. Bunun anlamı, fonksiyonların, Logger.Print()
’e yönelik çağrılar dışında base_team
’deki sürümlerle tamamen aynı şekilde çalışıyor olmasıdır.
<override>’ ile
(super:)` hakkında daha fazla bilgi edinmek için Alt Sınıf bölümüne bak
Nesne Takımı
Şimdi Nesne takımına ilişkin sınıfı oluştur. Projende prop_team.verse adlı yeni bir Verse dosyası oluştur. Bu bir Verse cihazı olmayacağından onu boş bir Verse dosyası olarak oluşturabilirsin.
Nesne takımının üyeleri için daha fazlasını yönetmen gerekir. Bu takım üyelerinin, bir süreölçere ve ne kadar ileri gittiklerine bağlı olarak başlatılması ve durdurulması gereken kalp atışı efektleri vardır. Ayrıca avlandıklarında Avcı takımına geçirilmeleri gerekir.
Nesne takımının üyelerini yönetmek için RunPropGameLoop()
metodunu kullanacaksın. Bu metodu, bir nesnenin oyundaki tüm yolculuğuna ilişkin yönetici olarak düşünebilirsin. Bu metot her nesne takımı üyesi için, doğduğu andan, avlandığı veya oyunu bıraktığı ana kadar geçerli olacaktır.
# Nesne aracısı hareket etmeyi durdurursa nesne aracısının MinimumMoveDistance’ı aştığını ve kalp atışı süreölçerinin tamamlandığını mı yoksa nesne aracısının avlandığını mı görmek için yarış.
RunPropGameLoop(PropAgent:agent)<suspends>:void =
Logger.Print("Nesne aracısı oyun döngüsü başlatılıyor.")
# Nesne aracısı avlanana veya oyuncu oturumdan ayrılana kadar nesne davranışı üzerinden sonsuza kadar döngü halinde çalıştır.
race:
PropAgent.AwaitNoLongerAProp()
loop:
# Nesne aracısı minimum mesafeden daha az hareket edene kadar bekle, ardından ilerle.
PropAgent.AwaitStopMoving(MinimumMoveDistance)
# Nesne aracısı minimum mesafenin ötesine geçene kadar kalp atışı için geri sayım yap ve ardından kalp atışını süresiz olarak çal.
race:
PropAgent.AwaitStartMoving(MinimumMoveDistance)
block:
CountdownTimer(PropAgent)
PropAgent.StartHeartbeat()
Sleep(0.0) # Yarış tamamlandığında (nesne aracısı hareket ettiğinde), döngüyü yeniden başlat.
RunPropGameLoop()
’un, PropAgent
adlı tek bir parametresi vardır. Bu, Nesne takımındaki bir oyuncuyu temsil eden bir sabittir. Aynı zamanda <suspends>
belirleyicisine sahiptir, bu da tamamlanmasının zaman alacağı anlamına gelir. Bu durumda, aktarılan PropAgent
artık Nesne takımında olmayana kadar tamamlanmaz.
Bu metodun tüm işlevselliği bir yarış ifadesinde yer alır. Buna göre, bu yarıştaki ifadelerden biri tamamlanmadan metot tamamlanmayacaktır. Bu ifadeler şunlardır:
-
PropAgent.AwaitNoLongerAProp()
-
loop
Bu yarıştaki döngü ifadesi hiç sonlanmayacaktır. Kasıtlı olarak sonsuzdur. Bu durumda, yarışı her zaman kazanacak ve metodu tamamlayacak olan metot AwaitNoLongerAProp()
’tur. Yarışı bu şekilde kullanman, programına, bir şey olana kadar belirli bir kod dizisini tekrar tekrar çalıştırmasını söylemek gibidir. Bu güçlü ifadeyle ilgili daha fazla bilgi edinmek için Yarış sayfasına bak.
Bu kod ile, AwaitNoLongerAProp()
yarışı kazanır.
# Nesne aracısı artık PropAgents dizisinin bir parçası olmayana kadar döngü halinde çalıştır. Kaldırma, nesne aracısının elenmesi ve avcıya dönüştürülmesi veya oyuncunun oturumdan ayrılması halinde gerçekleşir.
(PropAgent:agent).AwaitNoLongerAProp()<suspends>:void =
loop:
if (not FindOnTeam[PropAgent]):
Logger.Print("Nesne aracısı davranışı iptal ediliyor.")
break
Sleep(0.0) # Bir sonraki oyun tikine ilerle.
Bu metot sürekli olarak PropAgent
’ın Nesne takımında olup olmadığını kontrol eder. not FindOnTeam[PropAgent]
başarılı olana kadar çalışan, ardından kırılarak metodu tamamlayan bir döngüyle başlar. Bunlar hakkında daha fazla bilgi edinmek için Döngü ve Kırılma bölümüne bak.
FindOnTeam[]
, base_team
’de bildirilen başarısız olabilir bir fonksiyondur. PropAgent
Nesne takımında bulunursa başarılı olur. Ancak not
işlecini kullanman gerekir, çünkü döngüden yalnızca, PropAgent
Nesne takımında bulunmadığında çıkman uygun olacaktır. not
ile ilgili daha fazla bilgi edinmek için İşleçler bölümüne bak.
Son olarak, döngünün sonuna bir Sleep(0.0)
eklemen gerekir. Bu sayede döngü bir kez çalışır ve ardından bir sonraki simülasyon güncellemesine ilerler. Bu kontrolü daha sık çalıştırmana gerek olmadığından Sleep(0.0)
performansa yardımcı olması için eklenir. Daha fazla bilgi edinmek için Sleep ile ilgili Verse API Başvurusu sayfasına bak.
Artık AwaitNoLongerAProp()
’un nasıl çalıştığını bildiğine göre, RunPropGameLoop()
’ta onunla yarışan sonsuz döngüyü yazabilirsin.