Merhaba! Ben Savaş Robotları Projesinin Müşteri Geliştiricisi Vladimir Popov. Bu yazının yazıldığı sırada, War Robots birkaç yıldır ortalıktaydı ve bu süre zarfında oyunda düzinelerce yeni mekanizma ortaya çıktı. Doğal olarak robotların çeşitli yetenekleri önemlidir, çünkü onlar olmadan robotlar benzersizliklerini kaybederler ve bu da oyunu daha ilginç hale getirir.
Bu yazıda oyunumuzda oynanış yeteneği sisteminin nasıl çalıştığını ve nasıl geliştiğini paylaşacağım. Ve işleri daha erişilebilir kılmak için, işleri basit terimlerle ve çok fazla teknik ayrıntıya girmeden açıklayacağım.
Öncelikle proje geçmişine bakalım ve artık kullanılmayan eski bir uygulamaya bakalım.
Daha önce yetenekler çok önemsiz bir şekilde tasarlanıyordu: Robota bağlı bir bileşene sahiptiler. Bu, programcının yeteneğin nasıl çalıştığını tam olarak tanımladığı bir yapıydı: hem akışını hem de diğer yeteneklerle nasıl etkileşime girdiğini. Tüm mantık tek bir bileşen içinde açıklanmıştır ve oyun tasarımcısı bunu basitçe robota bağlayabilir ve parametreleri gerektiği gibi yapılandırabilir. Yetenek akışını değiştirmenin mümkün olmadığını belirtmekte fayda var; oyun tasarımcıları yalnızca parametreleri ve zamanlamaları değiştirebilirdi.
Eski bir yetenek yalnızca iki durumda mevcut olabilir: etkin ve etkin olmayan ve her duruma kendi eylemi atanabilir.
Daha önce robot “Stalker”ın sahip olduğu “Jammer” yeteneğinin bir örneğine bakalım; şu şekilde çalıştı:
Uzun bir süre bu işlevsellik bizim için yeterliydi, ancak zamanla hem oyun tasarımcıları hem de programcılar artık bu yaklaşımdan memnun kalmadılar: programcıların bu yetenekleri desteklemesi zordu çünkü kod canavarlaşmıştı; bu, her durumun tanımlanması gereken çok uzun bir miras zincirini içeriyordu. Buna ek olarak, oyun tasarımcıları esneklikten yoksundu; bir yetenekte herhangi bir değişiklik yapmak için, bitişik bir yetenek aynı işlevselliğe sahip olsa bile, programcılardan değişiklik siparişi vermek zorundaydılar.
Dolayısıyla bir şeylerin değişmesi gerektiğini anladık. Bu nedenle, her yeteneğin birbiriyle ilişkili birkaç nesne kümesi olarak temsil edildiği yeni bir sistem geliştirdik. İşlevsellik durum yeteneklerine ve durum bileşenlerine bölündü.
O nasıl çalışır? Her yeteneğin bir ana amacı vardır. Bu merkezi nesne, diğer yetenek nesnelerini dış dünyaya bağlar ve bunun tersi de geçerlidir; aynı zamanda tüm ana kararları da verir.
Herhangi bir sayıda durum olabilir. Temel olarak, bu yinelemedeki durum, eski versiyondaki aktif/etkin olmayan durumlardan çok farklı değildir, ancak artık bunlardan herhangi bir sayıda olabilir ve amaçları daha soyut hale gelmiştir. Bir yeteneğin aynı anda yalnızca bir aktif duruma sahip olabileceğini not edeceğiz.
Eski sisteme kıyasla ana yenilik bileşenlerdi: Bir bileşen bir eylemi tanımlar ve her durum herhangi bir sayıda bileşene sahip olabilir.
Yeni yetenekler nasıl çalışıyor? Bir yetenek yalnızca durumlardan birinde olabilir; ana nesne bunların değiştirilmesinden sorumludur. Bir duruma bağlanan bileşenler, durumun etkinleştirilmesine/devre dışı bırakılmasına tepki verir ve buna bağlı olarak bir eylemi gerçekleştirmeye başlayabilir veya gerçekleştirmeyi bırakabilir.
Tüm nesneler özelleştirilebilir hale geldi; Bir oyun tasarımcısı durumları ve bileşenleri istediği gibi karıştırabilir, böylece önceden yüklenmiş bloklardan yeni bir yetenek oluşturabilir. Artık programcıların yalnızca yeni bir bileşen veya durum oluşturmak için resme girmeleri gerekiyor, bu da kod yazmayı çok daha kolay hale getiriyor: küçük varlıklarla çalışıyorlar, bazı basit öğeleri tanımlıyorlar ve artık yeteneği kendileri geliştirmiyorlar; bunu artık oyun tasarımcıları yapıyor.
Akış şu şekilde oldu:
Daha sonra bu prosedür defalarca tekrarlanır. Kullanım kolaylığı açısından, bir durum yalnızca bileşen taşıyıcısı olarak hizmet vermekle kalmaz, aynı zamanda başka bir duruma ne zaman geçileceğini de belirler ve ana nesneden geçiş yapmasını ister. Zamanla bu da bizim için yeterli olmadı ve yetenek diyagramı şu şekle dönüştü:
Ana nesne, durum ve bileşenler yerinde kaldı ancak yeni unsurlar da eklendi.
Gözünüze çarpan ilk şey, her duruma ve bileşene koşullar eklemiş olmamızdır: eyaletler için bunlar, eyaletten ayrılmaya ilişkin ek gereksinimleri tanımlar; bileşenler için bileşenin eylemini gerçekleştirip gerçekleştiremeyeceğini belirlerler.
Yük konteyneri yükleri içerir, bunları yeniden şarj eder, gerekirse yeniden şarjı durdurur ve durumların kullanması için yük sağlar.
Birkaç durumun ortak bir yürütme süresine sahip olması gerektiğinde, ancak kendi yürütme zamanlarının tanımlanmadığı durumlarda bir zamanlayıcı kullanılır.
Tüm yetenek nesnelerinin isteğe bağlı olduğunu unutmamak önemlidir. Teknik olarak çalışabilme yeteneği için yalnızca bir ana nesneye ve bir duruma ihtiyaç vardır.
Aslında tamamen programcıların katılımı olmadan oluşturulan çok fazla yetenek olmasa da, genel olarak geliştirme gözle görülür şekilde daha ucuz hale geldi, çünkü programcıların artık yalnızca çok küçük şeyler yazması gerekiyor: örneğin, bir yeni durum veya iki bileşen - gerisi yeniden kullanılır.
Yeteneklerimizin bileşenlerini özetleyelim:
Ana nesne bir durum makinesinin işlevlerini yerine getirir. Devletlere ve bileşenlere dünya hakkında bilgi sağlar ve dünyaya yetenekler hakkında bilgi sağlar. Ana nesne, yeteneğin durumları, bileşenleri ve servis parçaları (yükler ve harici zamanlayıcılar) arasında bir bağlantı görevi görür.
Durum , ana nesneden gelen etkinleştirme ve devre dışı bırakma komutlarını dinler ve buna göre bileşenleri etkinleştirip devre dışı bırakır ve ayrıca ana nesnenin başka bir duruma geçmesini ister. Bir sonrakine ne zaman geçmesi gerektiğini devlet belirler; Bunu yapmak için kendi iç durumunu kullanır: Oyuncunun yetenek düğmesine tıklayıp tıklamadığı, durumun etkinleştirilmesinden bu yana belirli bir süre geçip geçmediği vb. ve durumla bağlantılı dış koşullar.
Bileşen, durumdan gelen etkinleştirme ve devre dışı bırakma komutlarını dinler ve bazı eylemleri gerçekleştirir: ayrık veya uzun vadeli. Eylemler tamamen farklı olabilir: hasara neden olabilir, bir müttefiki iyileştirebilir, bir animasyonu açabilir vb.
Koşul, istenen öğenin hangi durumda olduğunu kontrol eder ve bunu duruma veya bileşene bildirir. Koşullar karmaşık olabilir. Bir durum, koşulun karşılanmaması durumunda başka bir duruma geçiş talebinde bulunmaz. Koşul karşılanmazsa bileşen ayrıca bir eylem gerçekleştirmez. Koşullar isteğe bağlı bir varlıktır; her yetenek bunlara sahip değildir.
Yük konteyneri yükleri tutar, yeniden şarj eder, gerektiğinde yeniden şarjı durdurur ve durumlara yük sağlar. Çoklu şarj yeteneklerinde, oyuncunun onu birkaç kez kullanmasına izin vermeniz gerektiğinde, ancak art arda n defadan fazla olmamak üzere kullanılır.
Zamanlayıcı, birkaç durumun ortak bir süreye sahip olduğu durumlarda kullanılır, ancak her birinin ne kadar süreceği bilinmemektedir. Herhangi bir durum n saniye boyunca bir zamanlayıcı başlatabilir. İlgili tüm devletler zamanlayıcı bitiş olayına abone olur ve bittiğinde bir şeyler yapar.
Şimdi yetenek diyagramına dönelim. İşlevselliği nasıl değişti?
Devletler ücretleri ek bir geçiş koşulu olarak kullanabilirler. Böyle bir geçiş meydana gelirse yüklerin sayısı azalır. Devletler ayrıca ortak bir zamanlayıcı kullanabilirler. Bu durumda, bunların yürütülmesi için toplam süre bir zamanlayıcı tarafından belirlenecek ve her durum ayrı ayrı herhangi bir zamanda devam edebilir.
Yeni yetenek kullanıcı arayüzleri için tekerleği tamamen yeniden icat etmedik.
Ana nesnenin kendi kullanıcı arayüzü vardır. Her zaman kullanıcı arayüzünde olması gereken ve mevcut etkin duruma bağlı olmayan bazı öğeleri tanımlar.
Kullanıcı arayüzünde her durumun kendi çifti vardır ve durum kullanıcı arayüzü yalnızca durumu etkin olduğunda görüntülenir. Durumuyla ilgili verileri alır ve bunu şu veya bu şekilde görüntüleyebilir. Örneğin, süre durumlarının kullanıcı arayüzünde genellikle kalan süreyi görüntüleyen bir çubuk ve metin bulunur.
Durumun bir yeteneği sürdürmek için harici bir komutu beklediği bir durumda, kullanıcı arayüzü bir düğme görüntüler ve buna basıldığında komut duruma gönderilir.
Belirli örnekleri kullanarak yeteneklerin nasıl çalıştığına bakacağız; öncelikle “Engizisyoncu” isimli robota bakalım. Birbirini takip eden dört durumumuz var; durumların üstünde bunların ekranını kullanıcı arayüzünde görebilirsiniz. Bunlardan ikisi için onlara ait bileşenleri de görüyoruz; diğer iki eyaletin bileşenleri yoktur.
İşte yeteneğin akışı:
Her şey “WaitForClick” durumuyla başlar. Şu anda yetenek hiçbir şey yapmıyor; sadece komutları bekler.
Böyle bir komut alınır alınmaz ana nesne durum değiştirir. Bir sonraki aktif durum “WaitForGrounded”dır.
Bu durumun bazı bileşenleri vardır ve bu nedenle etkinleştirildiğinde robot atlar ve bir ses ve animasyon çalar. Diğer şeylerin yanı sıra, durum aktifken robot, robota nişan almayı yasaklayan Jammer etkisinden etkilenir.
Robot yere indiğinde yeteneği bir sonraki duruma geçer.
Bu durumun üç bileşeni vardır: Zaten tanıdık olan Ses ve Jammer'ın yanı sıra, n yarıçapındaki tüm oyuncular için kameranın sallanmasına neden olan Sarsıntı.
Bu durum Duration'a sahip olduğundan n saniye boyunca çalışır, ardından yetenek bir sonraki duruma geçer.
Son durum da bir Süre ile birlikte gelir, ancak herhangi bir bileşeni yoktur: düzenli bir bekleme süresindedir.
Tamamlandığında yetenek ilk durumuna geri döner.
Bir başka örnek ise “Hayalet”. Inquisitor'a çok benziyor ama bazı nüanslar var:
WaitForClick ile başlıyoruz.
Daha sonra ışınlanmanın kurulduğu Süre, makinenin istatistikleri değiştirilir, ses ve animasyon oynatılır.
Bundan sonra: Makinenin istatistiklerinin değiştirildiği, animasyon ve FX'in oynatıldığı DurationOrClick.
Bir tıklama yapıldıysa, mekanik ışınlanmaların, istatistiklerin değiştiği ve animasyonun, FX'in ve seslerin oynatıldığı başka bir Süreye gideriz.
Bu durumdan sonra (veya DurationOrClick için süre dolduktan sonra) Süre'ye geçiyoruz.
Buradaki temel fark, dallanmalı durumları görmemizdir: SüreOrTıklama, belirtilen süre geçmişse A durumuna veya oyuncu daha önce yetenek düğmesine basmışsa B durumuna gider.
Sistemimiz basit bir şeyden oldukça karmaşık bir şeye doğru evrilmiş gibi görünse de bu değişiklik hem programcıların hem de oyun tasarımcılarının hayatını kolaylaştırdı. Programcıların yardımına artık çoğunlukla küçük bileşenler eklenirken ihtiyaç duyulurken, ikinci grup ekip üyeleri daha fazla özerklik kazandı ve artık mevcut durum ve bileşenlerden bağımsız olarak yeni yetenekler bir araya getirebiliyor. Başka bir bonus olarak oyuncular aynı zamanda makinelerin daha çeşitli ve karmaşık yeteneklerinden de kazanç elde ettiler.