Geri
FORTNITE'TAKİ PİST YARIŞI ŞABLONUNU VERSE SÜREKLİLİĞİ VE DAHA FAZLASIYLA NASIL GELİŞTİRDİK?
Fortnite Ekibi
Verse Sürekliliği'nin kullanıma sunulması, Fortnite Kreatif "Bir Pist Yarışı Tasarla" şablon adasının UEFN'e yükseltilmesini sağladı.Sinematik ve çevre düzenlemesi ekleme gibi güncellemelerden tutun da tetikleyicilerden uzaklaşıp Verse'e geçmeye kadar, bu şablonun gelişim yolculuğunu sizlerle paylaşmaktan dolayı heyecanlıyız. Karşınızda Verse Sürekliliği ile Pist Yarışı!
"Bir Pist Yarışı Tasarla" şablonu, ilk başta yeni oluşturulan pist yarışı öğelerini kullanmak ve genel kaliteyi artıran bazı güzel özelliklerle farklı bir yarış deneyimi sunmak için oluşturuldu.
Son güncelleme ile bütünsel bir yaklaşım benimsedik ve harita genelinde birçok özelliği değiştirip yükselttik. UEFN'in güçlü yeteneklerinden yararlanan bazı güncellemelerimize bir göz atalım.
Orijinal projenin eski gece-gündüz döngüsü, daha gelişmiş olan Fortnite Battle Royale 4. Bölüm aydınlatmasıyla değiştirildi. Bu yeni döngü sayesinde Lumen kullanarak daha yumuşak gölgeler ve gerçekçi global aydınlatma oluşturabildik. Ayrıca şelale gibi özellikler ekleyerek pistin kendisini görsel olarak daha ilginç hale getirdik.
Verse Sürekliliği buna bir çözüm getirerek oyun oturumları arasında veri takibini mümkün kıldı. Bu işlev, oyuncu istatistiklerini baştan sona izlememize ve yerel sıralamalar oluşturmamıza olanak tanıyor.
Amacımız bir oyuncunun turu bitirdiğinde en iyi tur zamanını güncellemek ve ayrıca yarışı bitirdiklerinde puanlarını ve galibiyetlerini kaydetmekti.
Yarış Yöneticisi cihazının LapCompletedEvent'inin oyuncu turu bitirdiğinde bunu algılamasını bekleyebildiğimiz için tur zamanlarını çok kolay güncelledik. Yarış başladığında her oyuncu için çalışan bir Süreölçer cihazı başlatıyoruz. WaitForPlayerToFinishLap fonksiyonu oyuncunun turu bitirmesini bekliyor, tur süresini hesaplıyor, istatistik tablosunu güncelliyor ve ardından bir sonraki tur kaydı için süreölçeri sıfırlıyor.
Bu sorunu çözmek için ArraySync fonksiyonunu kullandık. ArraySync, kendisine iletilen dizideki her eleman için asenkron olarak bir fonksiyon çağırır ve tüm bu fonksiyonların tamamlanmasını bekler. Bir oyuncu dizisi ve WaitForPlayerToFinishRace fonksiyonunu ileterek, fonksiyonu her birinde çağırabilir ve herkes için bitene kadar bekleyebilirdik.
Böylelikle oyunculara yarışı bitirdikleri zamanki sıralamalarına göre puan ve galibiyet yazıp istatistik tablolarını buna göre güncelleyebildik. ArraySync bittiğinde tüm oyuncuların yarışı bitirdiğini anlayıp oyunu sonlandırabiliyoruz.
Her oyuncu için kalıcı istatistiklere halihazırda sahip olduğumuzdan, bu istatistikleri alabilir ve panoları kullanarak görüntüleyebilirdik. Oyun öncesi bekleme alanına, her oyuncu için hem istatistiklerini hem de o sırada giydikleri kıyafetleri sergilemek için Pano ve Oyuncu Referansı cihazları ekledik. Ancak bu oyuncuları performanslarına göre sıralamak, hâlâ aşılması gereken bir zorluktu.
Bunu başarmak için Birleştirme Sıralaması algoritmasını uyguladık. Yaygın olarak kullanılan Birleştirme Sıralaması, böl ve yönet mantığıyla çalışır. Bir diziyi özyinelemeli olarak ikiye bölen, her bir alt diziyi sıralayan ve bunları tekrar birleştiren bir algoritmadır. Ayrıca algoritmaya bir karşılaştırma fonksiyonu aktarma özelliği ekleyip farklı oyuncu istatistiklerinin her biri için karşılaştırma fonksiyonları oluşturduk.
Oyuncuları sıralamamız gerektiğinde, her oyuncunun istatistiklerini istatistik tablosundan alabilir, hepsini bir diziye ekleyebilir ve hem bu diziyi hem de bir karşılaştırma fonksiyonunu Birleştirme Sıralaması algoritmasına aktarabilirdik. Hangi karşılaştırma fonksiyonunu aktaracağımızı seçerek, her istatistiğe göre sıralanmış oyuncu dizisini geri alabilirdik. Algoritmayı kendiniz test edebilmeniz ve kendi fonksiyonlarınıza göre uyarlayabilmeniz için yeni şablona hem Birleştirme Sıralaması algoritmasını hem de bir test dosyasını ekledik.
Sıralama mekanizmalarını devreye sokarak sıralama tablolarını tamamladık. Oyunun ilk turunda oyuncular, oyuncu referansları ve panolarıyla birlikte oyun öncesi bekleme alanında ortaya çıkıyor. Bu oyuncu referanslarını her oyuncunun baştan beri topladığı puanlara göre sıralıyoruz ve her bir istatistiği önlerindeki panoda gösteriyoruz. Böylece oyuncular yarıştan önce rekabeti inceleyebiliyor ve kazanmak istiyorlarsa kime dikkat etmeleri gerektiğini öğrenebiliyorlar.
Oynamaya devam edin; belki kendinizi sıralamanın zirvesinde bulursunuz!

Bunu yapmak için CircuitInfo adında ikinci bir oyuncu zayıf harita değişkeni oluşturduk. Bu CircuitInfo değişkeni, oyunun sonunda veya bir oyuncu ayrıldığında sıfırlamamız gereken tüm bilgileri tutuyor.
Hangi bilgilerin sıfırlanacağını (pist bilgisi) ve hangilerinin sonsuza kadar kalıcı olacağını (oyuncu istatistikleri) netleştirmek için ikinci bir zayıf harita değişkeni kullandık.
Her oyuncu için CircuitInfo oyuncu zayıf harita değişkenine aşağıdaki bilgileri kaydediyoruz:
Verse cihazının OnBegin fonksiyonunda (her turun başında çalışır), tüm aktif oyuncuları yineleyerek ve kalıcı verilerinden de son tamamlanan en yüksek tur değerini alarak hangi turda olduğumuzu buluyoruz. Bunu her turda yalnızca bir kez yapıyoruz ve tur bilgisini bir oturum zayıf harita değişkenine kaydediyoruz, böylece yeniden hesaplamaya gerek kalmadan projedeki tüm Verse kodları bu değere istediği zaman erişebiliyor.
Bir oyuncunun yarışı tamamlaması, Yarış Yöneticisi cihazının RaceCompletedEvent'ini bekleyerek tespit ediliyor. Bitiş sırasını ve geçerli turu oyuncuyla ilişkili CircuitInfo zayıf harita değişkenine kaydediyoruz. Bu bilgiyi iki koşul altında sıfırlıyoruz:
Güncellenmiş şablonda, açılış sinematiğimizi elde etmek için Dalga Tetikleyici'yi Sequencer ile değiştirdik. Sequencer'ı kullanarak farklı kameralar, gösterge paneli (HUD) öğeleri ve aktif oyuncu sayısına göre ayarlanan dinamik bir dizilim görünümü ekleyebildik.
Dalga Tetikleyici'yi yapılandırdığımız gibi, cihazları önemli anlarda sekansa bağladık ve böylece bir sonraki oyuncunun skorunu ne zaman görüntüleyeceğimizi veya giriş sahnesini ne zaman keseceğimizi belirleyebildik.

Tasarımı ileri taşıyan yeni özellikler yayınlandıkça bu şablonu güncellemeyi sabırsızlıkla bekliyoruz. Bu sırada şablonu indirebilir, bileşenlerini keşfedebilir ve UEFN'deki şablon sekmesi aracılığıyla işlevselliğini projelerinize entegre edebilirsiniz. Yarışlarınızın, sıralamalarınızın ve daha fazlasının nasıl şekillendiğini görmek için sabırsızlanıyoruz!
"Bir Pist Yarışı Tasarla" şablonu, ilk başta yeni oluşturulan pist yarışı öğelerini kullanmak ve genel kaliteyi artıran bazı güzel özelliklerle farklı bir yarış deneyimi sunmak için oluşturuldu.
Son güncelleme ile bütünsel bir yaklaşım benimsedik ve harita genelinde birçok özelliği değiştirip yükselttik. UEFN'in güçlü yeteneklerinden yararlanan bazı güncellemelerimize bir göz atalım.
Görsel Tasarım
UEFN'deki manzara modu, yarışın köklerine inmemizi ve yeni manzara düzenleme araçlarını kullanarak bir off-road pisti oluşturmamızı sağladı. Orijinal adamızın arka planında yer alan kaya öğelerinden oluşan dağlar, daha doğal bir peyzaj tasarımıyla değiştirildi.Orijinal projenin eski gece-gündüz döngüsü, daha gelişmiş olan Fortnite Battle Royale 4. Bölüm aydınlatmasıyla değiştirildi. Bu yeni döngü sayesinde Lumen kullanarak daha yumuşak gölgeler ve gerçekçi global aydınlatma oluşturabildik. Ayrıca şelale gibi özellikler ekleyerek pistin kendisini görsel olarak daha ilginç hale getirdik.
Verse Sürekliliği: Daha İyi Bir Sıralama Tablosu
Orijinal haritada, Oyuncu Referansı cihazını kullanan kule ilk sıradaki oyuncuyu ve kaç puanı olduğunu gösteriyordu. Ancak veriler oturumdan oturuma kalıcı değildi.Verse Sürekliliği buna bir çözüm getirerek oyun oturumları arasında veri takibini mümkün kıldı. Bu işlev, oyuncu istatistiklerini baştan sona izlememize ve yerel sıralamalar oluşturmamıza olanak tanıyor.
Oyuncu İstatistiklerini Takip Etme
Oyuncuların baştan sona galibiyetlerini, en iyi tur zamanlarını ve her yarış bitiminde kazandığı puanları izleyen kalıcı bir oyuncu istatistikleri tablosu sınıfı geliştirdik. Ayrıca oyuncuları oyuncu istatistikleri tablolarıyla eşleştirmek için PlayerStatsMap adlı kalıcı bir zayıf harita kullandık ve bu istatistiklerin turlar ve oturumlar boyunca kalıcı olmasını sağladık. Ardından oyuncu başına bu istatistiklerin başlatılması, alınması ve güncellenmesi işlemlerini gerçekleştirmek için bir istatistik yöneticisi sınıfı oluşturduk.Amacımız bir oyuncunun turu bitirdiğinde en iyi tur zamanını güncellemek ve ayrıca yarışı bitirdiklerinde puanlarını ve galibiyetlerini kaydetmekti.
Yarış Yöneticisi cihazının LapCompletedEvent'inin oyuncu turu bitirdiğinde bunu algılamasını bekleyebildiğimiz için tur zamanlarını çok kolay güncelledik. Yarış başladığında her oyuncu için çalışan bir Süreölçer cihazı başlatıyoruz. WaitForPlayerToFinishLap fonksiyonu oyuncunun turu bitirmesini bekliyor, tur süresini hesaplıyor, istatistik tablosunu güncelliyor ve ardından bir sonraki tur kaydı için süreölçeri sıfırlıyor.
Galibiyetlerin ve Puanların Kaydedilmesi
Galibiyetlerin ve puanların kaydedilmesinin daha karmaşık olduğunu fark ettik. Yarış Yöneticisinin “RaceCompletedEvent'ini beklemek ve oyuncuların yarışı ne zaman bitirdiklerini öğrenmek için aynı şekilde WaitForPlayerToFinishRace fonksiyonunu kullanabileceğimizi biliyorduk. Öte yandan, oyunun sadece tüm oyuncular bitirdiğinde sona ermesini istiyorduk ama Yarış Yöneticisi'nin bunu izlemesinin veya yarış bittiğinde oyunu sonlandırmasının bir yolu yoktu.Bu sorunu çözmek için ArraySync fonksiyonunu kullandık. ArraySync, kendisine iletilen dizideki her eleman için asenkron olarak bir fonksiyon çağırır ve tüm bu fonksiyonların tamamlanmasını bekler. Bir oyuncu dizisi ve WaitForPlayerToFinishRace fonksiyonunu ileterek, fonksiyonu her birinde çağırabilir ve herkes için bitene kadar bekleyebilirdik.
Böylelikle oyunculara yarışı bitirdikleri zamanki sıralamalarına göre puan ve galibiyet yazıp istatistik tablolarını buna göre güncelleyebildik. ArraySync bittiğinde tüm oyuncuların yarışı bitirdiğini anlayıp oyunu sonlandırabiliyoruz.
Sonuçların Gösterilmesi
İstatistikleri kaydetmek kolay ama bu istatistikleri oyunculara göstermenin bir yolunu da bulmalıydık. En iyi oyuncuları vurgulamak için görünür olan ve oyuncuları başından beri topladıkları puanlara göre sıralayan bölüm içi sıralama tabloları oluşturmak istedik.Her oyuncu için kalıcı istatistiklere halihazırda sahip olduğumuzdan, bu istatistikleri alabilir ve panoları kullanarak görüntüleyebilirdik. Oyun öncesi bekleme alanına, her oyuncu için hem istatistiklerini hem de o sırada giydikleri kıyafetleri sergilemek için Pano ve Oyuncu Referansı cihazları ekledik. Ancak bu oyuncuları performanslarına göre sıralamak, hâlâ aşılması gereken bir zorluktu.
Bunu başarmak için Birleştirme Sıralaması algoritmasını uyguladık. Yaygın olarak kullanılan Birleştirme Sıralaması, böl ve yönet mantığıyla çalışır. Bir diziyi özyinelemeli olarak ikiye bölen, her bir alt diziyi sıralayan ve bunları tekrar birleştiren bir algoritmadır. Ayrıca algoritmaya bir karşılaştırma fonksiyonu aktarma özelliği ekleyip farklı oyuncu istatistiklerinin her biri için karşılaştırma fonksiyonları oluşturduk.
Oyuncuları sıralamamız gerektiğinde, her oyuncunun istatistiklerini istatistik tablosundan alabilir, hepsini bir diziye ekleyebilir ve hem bu diziyi hem de bir karşılaştırma fonksiyonunu Birleştirme Sıralaması algoritmasına aktarabilirdik. Hangi karşılaştırma fonksiyonunu aktaracağımızı seçerek, her istatistiğe göre sıralanmış oyuncu dizisini geri alabilirdik. Algoritmayı kendiniz test edebilmeniz ve kendi fonksiyonlarınıza göre uyarlayabilmeniz için yeni şablona hem Birleştirme Sıralaması algoritmasını hem de bir test dosyasını ekledik.
Sıralama mekanizmalarını devreye sokarak sıralama tablolarını tamamladık. Oyunun ilk turunda oyuncular, oyuncu referansları ve panolarıyla birlikte oyun öncesi bekleme alanında ortaya çıkıyor. Bu oyuncu referanslarını her oyuncunun baştan beri topladığı puanlara göre sıralıyoruz ve her bir istatistiği önlerindeki panoda gösteriyoruz. Böylece oyuncular yarıştan önce rekabeti inceleyebiliyor ve kazanmak istiyorlarsa kime dikkat etmeleri gerektiğini öğrenebiliyorlar.
Oynamaya devam edin; belki kendinizi sıralamanın zirvesinde bulursunuz!

Başlangıç Çizgisinde Yarışçı Sırası
Haritanın Fortnite Kreatif versiyonu, her oyunun başında oyuncuları rastgele bir sıraya yerleştirir. Oyuncuları sıralamalarda daha yükseklere ulaşmaları için motive etmek adına, başlangıç sırasını bir önceki turun bitiş pozisyonlarına göre belirledik.Tur Bilgisinin Takibi
Sıralamalar için kullandığımız kalıcı verilerin aksine, yarışçı sırası ve pist bilgilerinin tüm oyun oturumlarında değil, turlar arasında kalıcı olması lazımdı. Verse'deki oturum zayıf harita değişkeni, her turda verilerini sıfırlar, bu nedenle bu bilgileri her oyuncu için saklamamız ve oyun bittikten sonra sıfırlamamız gerekir.Bunu yapmak için CircuitInfo adında ikinci bir oyuncu zayıf harita değişkeni oluşturduk. Bu CircuitInfo değişkeni, oyunun sonunda veya bir oyuncu ayrıldığında sıfırlamamız gereken tüm bilgileri tutuyor.
Hangi bilgilerin sıfırlanacağını (pist bilgisi) ve hangilerinin sonsuza kadar kalıcı olacağını (oyuncu istatistikleri) netleştirmek için ikinci bir zayıf harita değişkeni kullandık.
Her oyuncu için CircuitInfo oyuncu zayıf harita değişkenine aşağıdaki bilgileri kaydediyoruz:
- Bitiş sırası
- Son tamamlanan tur
Tura Özgü Mantık
Tura özgü mantığı uygulamak (ilk tur değilse oyuncuları son bitiş sıralarına göre sıralamak gibi) ve oyuncu verilerini ne zaman sıfırlayacağımızı bilmek için hangi turda olduğumuzu bilmemiz gerekir. Şu anda geçerli turu alacak bir API bulunmuyor, dolayısıyla bunu her oyuncu için kalıcı verilere kaydetmeliyiz.Verse cihazının OnBegin fonksiyonunda (her turun başında çalışır), tüm aktif oyuncuları yineleyerek ve kalıcı verilerinden de son tamamlanan en yüksek tur değerini alarak hangi turda olduğumuzu buluyoruz. Bunu her turda yalnızca bir kez yapıyoruz ve tur bilgisini bir oturum zayıf harita değişkenine kaydediyoruz, böylece yeniden hesaplamaya gerek kalmadan projedeki tüm Verse kodları bu değere istediği zaman erişebiliyor.
Bir oyuncunun yarışı tamamlaması, Yarış Yöneticisi cihazının RaceCompletedEvent'ini bekleyerek tespit ediliyor. Bitiş sırasını ve geçerli turu oyuncuyla ilişkili CircuitInfo zayıf harita değişkenine kaydediyoruz. Bu bilgiyi iki koşul altında sıfırlıyoruz:
- Oyuncu oyun sırasında ayrılırsa: Ayrıldıklarını bilmek için oyun alanının PlayerRemovedEvent'ine bağlanıyoruz ve ResetCircuitInfo fonksiyonumuzu çağırıyoruz.
- Her turun başında, tamamlanan son turu hesaplıyoruz: Bu son tur ise, oyuncunun verilerini yenilemek için ResetCircuitInfo'yu çağırıyoruz. Kaç tur olduğunu, Verse cihazında bir oyun için toplam tur sayısına ayarlanmış düzenlenebilir bir özelliğe dayanarak biliyoruz. Bunun tur ayarlarıyla eşleştiğinden emin olmak ada üreticisine düşen bir görev.
Oturum Zayıf Haritaları ve Oyuncu Zayıf Haritaları Ne Zaman Kullanılır?
Bu yeni Pist Yarışı, kodunuzda oturum zayıf harita değişkenini ve oyuncu zayıf harita değişkenini kullanmanın farklarını ve gerekçelerini ortaya koymak için harika bir örnek:- Oturum zayıf harita değişkenleri tekiller ve her seferinde yeniden hesaplamak istemediğiniz geçerli tur için verileri saklamada faydalıdır.
- Oyuncu zayıf harita değişkenleriyse birden fazla tur ve oyun oturumu boyunca kalıcı olması gereken ama her bir oyuncuyla ilişkilendirilmesi gereken bilgiler için tasarlanmıştır.
Açılış Sekansı Dalga Tetikleyicisi
Pist Yarışı şablonunun orijinal versiyonunda, yarışın "hazır - ayarla - başla" kısmını yönetmek için Dalga Tetikleyici adında bir cihaz kullandık. Dalga Tetikleyici, metni görüntülemek ve başlangıç çizgisindeki ışıkları etkinleştirmek için tetikleyicileri etkinleştirerek belirli bir süre boyunca bir olay sekansı oynatıyor.Güncellenmiş şablonda, açılış sinematiğimizi elde etmek için Dalga Tetikleyici'yi Sequencer ile değiştirdik. Sequencer'ı kullanarak farklı kameralar, gösterge paneli (HUD) öğeleri ve aktif oyuncu sayısına göre ayarlanan dinamik bir dizilim görünümü ekleyebildik.
Dalga Tetikleyici'yi yapılandırdığımız gibi, cihazları önemli anlarda sekansa bağladık ve böylece bir sonraki oyuncunun skorunu ne zaman görüntüleyeceğimizi veya giriş sahnesini ne zaman keseceğimizi belirleyebildik.

Sırada Ne Var?
UEFN gelişmeye devam ettiği sürece bu şablonu da geliştireceğimizi umuyoruz. Hedefimiz, eğlenceli ve ilgi çekici adalar oluşturmak için en yeni özelliklerden yararlanarak UEFN ile daha sofistike içerikler oluşturmaya devam etmenizi sağlamak.Tasarımı ileri taşıyan yeni özellikler yayınlandıkça bu şablonu güncellemeyi sabırsızlıkla bekliyoruz. Bu sırada şablonu indirebilir, bileşenlerini keşfedebilir ve UEFN'deki şablon sekmesi aracılığıyla işlevselliğini projelerinize entegre edebilirsiniz. Yarışlarınızın, sıralamalarınızın ve daha fazlasının nasıl şekillendiğini görmek için sabırsızlanıyoruz!