Bir kapak sistemi, AI birimlerinin haritadaki çeşitli nesnelerin arkasına siper alarak doğrudan ateşten kaçınmasını sağlar. Bir kapak sistemi kullanmak, bir oyunun gerçekçilik seviyesini artırır ve her tür için temel taktik unsurları sunar. Bu tür sistemler iki farklı modülden oluşur: kapak oluşturma ve kapak bulma. Kapak oluşturma tipik olarak statiktir ve oyun başlamadan önce yapılırken, kapak bulma oyun sırasında gerçek zamanlı olarak gerçekleşir.
Bu makalede, Unreal Engine 4’te tamamen dinamik, gerçek zamanlı bir kapak oluşturma modülünün nasıl sıfırdan oluşturulacağını açıklayarak ve bir kapak bulma modülünün uygulanmasını sağlayarak kapak sistemlerinin statik doğasına meydan okuyorum.
Sağlam bir kapak sistemi oluşturmak ilk bakışta göz korkutucu görünebilir, ancak bunun sadece bir dizi basit tekniğin birbirine yapıştırıldığını anladığınızda, elinizdeki görev çok daha az göz korkutucu görünecektir.
İster yeni nesil gerçek zamanlı strateji (RTS) oyunu yapıyor olun, ister bunu birinci şahıs nişancı (FPS) oyununda kullanmak istiyorsanız, bu makaledeki bilgileri faydalı bulacağınızı umuyorum. Demo projesini indirmenizi ve bir araya getirildiğinde hepsinin nasıl çalıştığını kontrol etmenizi öneririm.
Proje, iyi yorumlanmış kaynak koduyla birlikte yukarıda tartışılan tüm tekniklerin tamamen işlevsel bir uygulamasını içerir.
Demo projesini ve kaynak kodunu indirin.
İçindekiler
Araçlar ve Ön Koşullar
Öğretici Unreal Engine 4 (UE4) sürüm 4.18’i kullanır, ancak motorun eski sürümleriyle de çalışmalıdır. Örnek proje ve kaynak kodu C ++ ile yazılmıştır. Örnek projeyi ve kaynak kodunu anlamak için UE4, C ++ ve UE4 Taslakları hakkında temel bir anlayışa ihtiyacınız var.
Tasarım
Bir kapak sistemi tasarlarken karşılaşacağınız en önemli üç zorluk aşağıdaki gibidir:
- Veri üretimi
- Veri kalıcılığı
- Veri kullanımı
Bu makale, korumanın çalışma zamanında mevcut olabileceği veya tamamen ortadan kalkabileceği gerçek zamanlı dinamik bir kapak sistemi oluşturmaya odaklandığından, üçüne de optimize edilmiş bir yaklaşım uygulamak önemlidir.
İki veri oluşturma yöntemini ele alıyorum : navmesh kenar yürüyüşü ve 3B nesne taraması .
Kapak verileriniz eşzamanlı olarak oluşturulursa, oyun performansınızda gözle görülür bir aksamaya neden olarak oyunda gecikmelere neden olur. Kapak verisi üretimini paralel hale getirmek için Unreal Engine’in mükemmel çok iş parçacıklı API’lerinden nasıl yararlanılacağını gösteriyorum, tipik olarak günümüz oyun donanımlarında bulunan çok çekirdekli işlemeden yararlanıyorum.
Benzer şekilde, kapsama verilerine erişim çok yavaşsa, oyununuz önemli miktarda yavaşlar ve kapak sorgularında büyük miktarda CPU ve / veya GPU döngüsü tüketir. Bundan kaçınmak için, uzamsal verilerin gerçek zamanlı eşzamanlı araması için tasarlanmış bir veri yapısı kullanmak en iyisidir : oktree . Sekizlerin uygun şekilde kullanılması, özel kapak verilerinin , örneğin örtü malzemesi (taşa karşı saman), yükseklik, sağlık vb. Hızlı ve verimli erişimle depolanmasına da olanak tanır .
Veri kullanım optimizasyonları – birimleriniz gerçek zamanlı olarak hangi kapak noktasının kullanılacağına aktif olarak karar verirken – raycast sayısını en aza indirin ve uzamsal arama olanaklarının (sekizler) kullanılabilirliğinin yanı sıra doğrudan getirme talepleri (diziler veya haritalar) için destek sağlayın .
Bir birimin ateş açmak için nasıl siperden çıkabileceğini öngörmek için, gözetleme veya eğilme yeteneklerinin haritasını çıkarmak gerekir . Bir tank siperden dışarı bakamaz – bir piyadenin yapabileceği. Bunu çok fazla raycast kullanmadan gerçekleştirmenin bulduğum en iyi yolu, birimler üzerinde “eğilme ofsetleri” tanımlamaktır. Bunlar, kapaktan yapılan vuruş testi sonrasında ünitenin konumuna eklenen basit şamandıralar.
Son özellik, gerçek zamanlı dinamik güncellemelerdir – oyunda yeni bir nesne ortaya çıktığında, Unreal’ın olay sistemini kullanarak delegeler aracılığıyla onun çevresinde (ve içinde) koruma noktaları oluşturuyoruz. Bu, Tick için kaynakları israf etmememizi sağlar ve bu da, özen gösterilmezse oyunu önemli ölçüde yavaşlatabilir. Biz recast en navmesh kiremit güncelleme olayların içine kanca sadece gerektiğinde ilgili fayans ve güncelleme kapak noktaları.
Tüm tekno konuşmaya rağmen, aslında harika bir şekilde basit: birkaç önemsiz döngü ve UE4 belgelerinden birkaç eksik sayfa. Öyleyse hadi başlayalım.
Veri Oluşturma – İki Yol
Kapak verisi oluşturmak için birden fazla strateji var ve en önemli ikisini ele alıyorum: birincisi, 3B taramaya benzer bir teknik ve ardından bir navmesh kenar yürüyüş yaklaşımı.
3B nesne taraması, bir nesnenin çevresinde oluşturulan bir 3B ızgaraya dayanır. İşin büyük kısmını yapmak için genellikle her eksen için bir tane olmak üzere 3 ana for-loop’unuz vardır. Izgara üzerinde sabit bir mesafe olan noktalar üzerinde yineleme yaparsınız ve bir raycast ile herhangi bir şeye çarpıp vurmadığınızı kontrol edersiniz.
3D nesne taraması:
- Kapak noktalarını kenar yürüyüşüne göre daha düzgün dağıtır
- Navmesh ile uyumlu olmayan, ancak “kuvvet alanları” gibi bir kapak sağlayan nesneleri destekler
- Minimum hata şansı vardır
- Daha yavaştır (çok sayıda ızgara noktası nedeniyle)
- Manzaralarla kötü başa çıkıyor
Navmesh tabanlı yaklaşım çoğunlukla navmesh verilerine dayanır ve nesnelerle kendi başına ilgilenmez: Haritadaki bir nokta herhangi bir navmesh poligonu tarafından KAPATILMIYOR ise, o zaman bu, koruma sağlayacak kadar büyük bir şey tarafından işgal edildiği anlamına gelir.
- Oldukça hızlı
- Sağlam peyzaj topolojisini kolayca idare eder
- Güç alanları ve benzerleriyle başa çıkamıyorum
- Biraz daha hataya meyillidir: döşeme sınırları, uyumsuz noktalar
- Kapatma noktalarını eşit olarak dağıtmaz
Bunları ilerledikçe daha ayrıntılı olarak ele alacağım, öyleyse hadi 3B nesne taramanın işine bakalım!
Nesne Tabanlı Kapak Noktası Oluşturma
Navmesh’i delikler için taramak yerine, nesnelerin kendilerini tararız. Bunu 3B’de bir nesneyi taramak gibi düşünün: X, Y, Z eksenleri boyunca dilimleyin, dilimleri bir ızgaraya böldünüz ve nesnenin çevresinin – veya 3B çevresinin – zeminle nerede buluştuğunu belirlemek için ışın yayınlarını kullanın. Bu aynı zamanda C-şekilleri, halkalar, kaleler gibi düzensiz şekilli nesneler için de işe yarar.
3D tarama ızgarası şuna benzer:
Bu, esasen, oyuncunun sınırlayıcı kutusunu 3 boyutlu bir ızgaraya bölen çok basit 3 döngü ile gerçekleştirilir. Ancak ızgarada birçok nokta var ve bazıları nesnemize yakın bile değil, bu yüzden onları filtrelemeliyiz.
Ve neden sadece bir 2D ızgara kullanmıyorsunuz, sorabilirsiniz? İki şey yüzünden:
- Çok katlı nesneler (çok katlı evleri düşünün)
- Eğimli zeminlerde döndürülmüş nesneler
Geçersiz ızgara noktalarını filtrelemek için, en yakın yer düzlemine yeterince yakın olup olmadığını belirlemek için her noktadan -Z yönünde aşağıya bir ışın atarız. Eğer öyleyse, o zaman onu geçerli olarak işaretleriz ve bir sonrakine geçerek, sonunda her noktadan ışınları aşağıya atarız.
Neyse ki, raycasting çok ucuzdur, bu nedenle tek tek nesneler için endişelenmemize gerek yoktur – yalnızca çalışma zamanında çok sayıda nesneye sahip olduğumuzda sorun yaşamaya başlayabiliriz, ancak biz bu köprüyü geçerken orada ol.
Mavi: yere, altındaki ızgara noktasından daha yakın Kırmızı: zeminden aşağıdaki ızgara noktasından
daha uzak
Yalnızca mavi olanları sakladığımız için, bir sonraki geçişte endişelenecek çok daha az noktamız var: minimum zemin boşluğunu ve minimum kaplama yüksekliğini kontrol etmek.
Kırmızı: nesneye çok yakın
Yeşil: en küçük birimin altına sığması için nesneden yeterince uzak
Kırmızı: çok kısa
Mavi: yeterince uzun veya boş
Üst ortografik görünümden şu şekilde görünüyor:
Nihayetinde aradığımız şey, navmesh üzerindeki kırmızı işaretlere en yakın noktalar. Bunlar, aşağıdaki beyaz işaretçilerin bir alt kümesiyle temsil edilir:
Nihai koruma noktaları aşağıdaki mor işaretçilerle temsil edilir. Kırmızı işaretçileri (yukarıda) yineleriz ve navmesh’e düşen kırmızı işaretlere en yakın olan beyaz işaretçileri seçeriz:
Nihai sonucumuz şuna benzer:
Eğimli bir navmesh üzerinde ölçeklenmiş, döndürülmüş, çok katlı bir aktör şöyle görünüyor:
Yukarıdaki resimlerden de görebileceğiniz gibi, bu teknik hem kapak nesnesinde hem de zemin düzleminde hem döndürmeyi hem de ölçeklendirmeyi destekler. Her tür geometri için uygundur ve artık sahneye elle tek bir işaretçi yerleştirmek için seviye tasarımcılarına sahip olmak zorunda değilsiniz.
Bu tür otomatikleştirilmiş nokta oluşturma, çok iş parçacıklı yürütme ile iyi oturduğundan, UE4’e iş parçacığı havuzuna koyması için talimat verdiğimiz zaman uyumsuz bir görev içindeki tüm mantığı loblayacağız. En iyisi, tüm bunlar kutudan çıkar çıkmaz motor tarafından destekleniyor!
Her tür oyuncuyla çalışmasını sağlamak için özel bir UActorComponent oluşturuyoruz ve 3D tarama görevlerimizi oradan oluşturuyoruz. Buna UCoverGeneratorComponent diyelim . Bu bileşeni herhangi bir güç alanı türü aktörlere ekleyin . Normal nesneler için kullanmayın – daha sonra özetlediğim navmesh tabanlı jeneratör, mükemmel çok amaçlı çözümümüz.
Ağır vuruş zamanı, örtme sisteminizin ihtiyaçlarının% 90’ını karşılayan jeneratör. Bu yüzden daha fazla uzatmadan, kenarı yürümeye başlayalım!
Kenar yürüme yoluyla örtü oluşturma aslında çok basit bir işlemdir: iki köşe alın, ortaya çıkan kenara her iki yönde dik bir ışın atın, ışının bir şeye çarpıp çarpmadığını görün ve eğer evet ise, o zaman siper bulduk.
Çıkıntı veya uçurum duvarı algılamayı ekleyerek ışın sayımı açısından işleri daha da karmaşık hale getirebiliriz:
Bununla birlikte, bu, her navmesh tepe noktası başına en az 4 ışın daha ekliyor, bu nedenle şimdi toplamda 6’dayız: dikey yer ışınları için 2, çıkıntı algılama için 4. Hatta daha ileri gidebilir ve bu güzel uçurum duvarları için eğim toleransı uygulayabiliriz, böylece manzaralar gibi sağlam topoloji düzgün bir şekilde taranır:
Ancak bu, taraf başına en az bir ışın daha, bu da bizi en kötü senaryoda toplam 8 ışına çıkarıyor. Bu özelliğin projenizin performans maliyetine değip değmeyeceğine siz karar verirsiniz – Neslin çoğu zaten tam olarak eşzamansız olarak gerçekleştiği için açık bırakma eğilimindeyim ve oyun, kapak sistemi tüm bu süslü çıkıntıları incelemekle meşgulken bile başlayabilir. Ben bıraktım.
Hız
Birkaç kenarda yürümek, nispeten küçük bir nesneyi bile ızgara noktalarına dilimlemekten çok daha ucuzdur. Izgara noktalarının çoğunun size en az bir raycast’e mal olduğunu ve basit bir ağda bunlardan binlercesi olabileceğini düşünün. Sınırlayıcı kutu ne kadar büyükse, 3D tarama ile çalışmak o kadar pahalıdır.
Öte yandan, karmaşık bir nesnedeki navmesh polys sayısı birkaç yüzü geçmez, bu nedenle nesne istediğiniz kadar büyük olabilir. Sınırlayıcı kutusunun, navmesh çoklu sayısı üzerinde hiçbir şekilde etkisi yoktur. Nesnenizde çok fazla yürünebilir alan varsa, büyük olasılıkla birkaç polisle birleştirilecektir. Yüzeyde birçok dakika detayınız varsa, üzerinde gezinme bile olmayabilir. Ve bir canavar varlığı oluşturmayı başarsanız bile, navmesh çoklu sayısı, onu taramak için gereken 3B ızgara noktalarının sayısına kıyasla büyük olasılıkla soluk kalıyor.
Sağlam Peyzaj Topolojisi
Manzaralar, navmesh’lerin olduğu ve UE4’e entegre açık kaynaklı yol bulma uygulaması olan Recast’in parladığı yerlerdir.
Manzaralar ve 3B nesne tarama yaklaşımı ile ilgili sorun, çoğu zaman kapak noktalarını amaçlanan kapak nesnesi yerine peyzaja ait olarak yanlış tanımlamasıdır. Navmesh tabanlı nesil kullanırken bu bir sorun değildir ve performans kazanımlarının yanı sıra bu tekniği neden elimizden geldiğince kullanmamızın ana nedenidir.
Kuvvet Alanları (Kalkanlar)
Kuvvet alanları, Recast’in geçmediği bir şeydir ve bu nedenle, 3B nesne tarayıcının tek gücüdür. Navmesh’i hiç etkilemeyen dinamik nesneler olduklarından, kapak noktası veri yapısında bir noktanın bunlardan birine ait olup olmadığını belirtmek için bir boole bayrağı oluşturdum. Demo projesinde sarı işaretlerle belirtilmiştir. Reinhardt’ın Overwatch’daki kalkanını düşünün, ancak hareket etmeyen bir kalkan. Bu, birimlerin içlerinden ateş ederken aynı zamanda düşman ateşinden korunmalarını sağlar.
Hatalar
Navmesh tabanlı yaklaşımın dezavantajları yoktur ve çoğu zaman bu, Recast’in döşeme sınırlarında görünen gereksiz kenarlarda kendini gösterir. Kapak oluşturma sırasında onları ayırmak dışında onlar hakkında yapabileceğimiz pek bir şey yok.
Gördüğünüz gibi, birkaç fazla köşe var, ancak bunların çoğu kapak noktası oluşturma sırasında atılıyor. Onlarla baş etmenin birincil yolu, ışınları kenarlarının XY eksenlerine dik iki yönde atmak ve bunu sabit bir yükseklikten yapmaktır. Hiçbir şey vurulmadıysa, o zaman bizim noktamız sadece bir kiremit sınırı tepe noktasıdır ve güvenli bir şekilde atılabilir. Bunlar nesnelerinize de nüfuz eder, ancak aynı ayıklama tekniği geçerlidir.
Diğer hata türü, Recast’in kapalı ve açık alanlar arasında ayrım yapmaması, yani katı nesnelerin içinde de bir gezinme oluşturması gerçeğinden kaynaklanır:
Bu açıkça bir işe yaramaz ve bunun üstesinden gelmenin tek yolu, haritanızda daha büyük katı ağlara sahip olduğunuz yerlere navigasyon değiştirici birimleri yerleştirmektir.
Bu, çoğunlukla doğru navmesh oluşturmaya neden olur. Ancak, bu iç gezinmeleri tamamen gizleyemeyeceğiniz durumlar olduğunu unutmayın. Yine de, kapak sistemimiz ulaşılamayan örtü noktalarını otomatik olarak filtrelediği için sorun değil, bu sadece küçük bir performans kaybına neden olacaktır. Navmesh yol bulma sorguları, kapak bulma kodumuzun geri kalanına kıyasla nispeten pahalı olma eğilimindedir, bu nedenle yine de ulaşılamayan navmesh adalarının sayısını en aza indirmeyi hedeflemelisiniz.
Ardından, uzamsal verilere hızlı ve optimize edilmiş erişim sağlayan bir veri yapısında kapak noktalarımızı nasıl saklayacağımıza bakacağız: oktree.
Veri Sürekliliği – Octree
Bir ahtapotu bir ağaçla geçmeye benzer: hayal etmesi kolay ama tırmanması zor. Oktree, “küpü 8 küçük küp halinde bölün, durulayın ve tekrarlayın” demenin süslü bir yolundan başka bir şey değildir. Benzer şekilde, bir dörtlü ağaç tam da budur – dört küçük kareye bölünmüş bir kare, bu da daha küçük dört kareye bölünmüştür, vb. Tüm kapak noktaları haritamızı bir oktree’de saklayarak, uzamsal sorgularımızın her zaman alabilecekleri kadar verimli olmasını sağlayabiliriz.
İyi haber şu ki, UE4 tamamen işleyen bir oktree uygulaması içerdiğinden, işin çoğu bizim için Epic tarafından yapıldı. Kötü haber: neredeyse hiç belge yok. Korkmayın, çok karmaşık olmayacak ve Epic’in canavarlarını nasıl kullandığını görmek için her zaman FNavigationOctree’ye bakabiliriz .
Oktree’nin bir özelliği, mevcut veriyi ondan silmek istediğinizde, bir eleman kimliğini iletmeniz gerektiğidir. Ancak bu kimlikler oktree’de saklanmıyor – onlar için kendi depolama tesisimizi kurmalıyız.
FNavigationOctree’nin adımlarını takip ederek , basit bir TMap <const FVector, FOctreeElementId> Eleme ntToID kullanıyoruz; burada FV ector, bir kapak noktasının konumudur ve FOctreeEle mentId, Epic’in, öğenin bulunduğu düğüm ve dizini. Ayrıca haritaya yapılan tüm erişim çağrılarını iş parçacığı güvenli sarmalayıcı yöntemlerinde kapsıyoruz. Oldukça standart şeyler.
Oktree’mizin yarıçapı (boyutu) navmesh’lerimizinkini taklit etmelidir. Ancak basitlik uğruna, bunu sadece 64000 olarak ayarladık, bu aynı zamanda UNavigationSystem’in varsayılan olarak navmesh için dahili olarak kullandığı değerdir .
Gerçek Zamanlı Dinamik Güncellemeler
Kapak sistemimizin temel özelliklerinden biri, çalışma zamanında ortamdaki değişikliklere yanıt verebilme ve yeni geometriyi anında işleyebilme yeteneğidir.
Bu, ARecastNavMesh’i alt sınıflara ayırarak ve OnNavMeshTilesUpdated yöntemini geçersiz kılarak yaptığımız Recast’ın döşeme güncelleme etkinliğine bağlanarak gerçekleştirilir . Geçersiz kılınan yöntemin içindeki işlevsellik çok basittir, ancak vazgeçilmezdir: bir kutucuk her güncellendiğinde özel bir dinamik çok noktaya yayın temsilcisini bilgilendirin. Daha sonra ana teminat sistemi sınıfımız olan UCoverSystem’den (bir tekli) temsilciye abone oluyoruz ve buna göre kapak noktası oluşturucu görevlerini oluşturuyoruz.
Alt sınıfımıza AChangeNotifyingRecastNavMesh diyoruz ve onu özel bir oyun modu aracılığıyla oyuna bağlıyoruz . Oyun modu geçersiz kılar PostActorCreated () bildirilen yöntemini AActor ve kullanır ) SpawnActor ( bizim örneğini AChangeNotifyingRecastNavMesh olarak takip:
void ACoverDemoGameModeBase::PostActorCreated(){ Super::PostActorCreated(); GetWorld()->SpawnActor<AChangeNotifyingRecastNavMesh>(AChangeNotifyingRecastNavMesh::StaticClass());}
Tek bir olayda güncellenen birden çok döşeme olabileceğinden ve döşemelerin bazıları nispeten kısa bir süre içinde birden çok güncelleme alacağından, görev oluşturma mantığımızı aynı döşemeyi güncellememek için zaman dilimine ayırıyoruz. art arda iki kez.
Ayrıca Proje Ayarları ==> Navigasyon Sistemi ==> Aracılar ==> Desteklenen Aracılar’a gidip Navigasyon D ata K lası ve Tercih Edilen Gezinme Verilerinin her ikisinin de ChangeNotifyingReca stNavMesh olarak ayarlanması gereken yeni bir giriş eklemeniz gerekir. yani:
Ayrıca Navigasyon Sistemi altında Otomatik Navigasyon Verisi Oluştur seçeneğinin işaretini kaldırmanız gerekir :
Yeni ayarların uygulandığını görmek için düzenleyiciyi yeniden başlatmanız gerekebilir.
Çarpışma Yapılandırması
Piyonlar ve araçlar gibi birimlerin etrafında örtü oluşturulmamalıdır, bu yüzden özel bir izleme kanalı tanımlayarak bunları dışarıda bırakalım. C ++ ‘da ECC_GameTraceChannel1 olarak başvurabiliriz .
Git Proje Ayarlar … ==> Motor ==> Col lision ve o tıklayarak n Yeni İz Ch frekanslarını … düğmesini.
Ad: nUnits Yok
Varsayılan Yanıt : Yoksay
Şimdi, İzleme Kanallarının altındaki Ön Ayar bölümünü genişletin ve yanıtlarını yeni oluşturulan NonUnits izleme kanalımıza göre ayarlamak için aşağıdaki ön ayarların her birine çift tıklayın . Aşağıda listelenmeyenleri olduğu gibi bırakın – zaten varsayılan olarak Yoksay’a ayarlıdırlar ve orada istediğimiz şey budur.
Üzerinde onay kutusunu işaretleyin Blok içinde NonUnits aşağıdaki tüm ön ayarları satır:
- Hepsini engelle
- BlockAllDynamic
- Yok edilebilir
- Görünmez Duvar
- InvisibleWallDynamic
Daha sonra, onay kutusunu işaretleyin Overlap içinde NonUnits aşağıdaki tüm ön ayarları satır:
- Örtüşme Tümü
- OverlapAllDynamic
Ardından, ” Kalkan ” veya ” Kuvvet Alanı ” adlı yeni bir Nesne Kanalı tanımlayın :
Ve son olarak, ” NonBlockingShield ” veya ” NonBlockingForceField ” adlı özel bir çarpışma Ön Ayarı oluşturun :
Çalışma Zamanında Kapak Bulma
Artık, süslü küçük oktree’nizde kapak noktalarınız var ve her şey verimli ve çok iş parçacıklı, tüm döşeme güncellemelerinde geçen özel navmesh … Her şey yolunda, bu yüzden şimdi bu verileri kullanmaya başlama zamanı!
Birimleriniz, bir RTS yapıyorsanız, muhtemelen bir seferde düzinelerce birim aramak istiyor – daha iyisi, taktik ağırlıklı bir RTS (teknik olarak bir RTT) – peki buna en iyi nasıl yaklaşmalılar? Çok kolay: sadece oktree’yi sorgulayın, ihtiyaçlarına uygun bir nokta seçin, seçilen yeri ayırın ve oraya gidin.
Bir CoverFinder hizmeti veya görevi oluşturmanızı öneririm , ana sınıf UBTService veya UBTTaskNode olabilir . Bir göreve giderseniz, ona bir Cooldown dekoratörü ekleyebilirsiniz, böylece yalnızca her x saniyede bir çağrılır ve oktree ve navmesh’inizi sorgularla veya PhysX’inizi raycast’lerle doldurmaz.
Bunun yerine , UBTService için bir UCoverFinder hizmeti de oluşturabilirsiniz . Demo projesinde sizin için her iki sınıfı da oluşturdum, ancak sistemi kapak sorgularıyla spam yaptığımı * yapıyorum *, böylece davranış ağacınızdaki UCoverFinder tik aralığını daha az kaynak tüketecek şekilde ayarlamak isteyeceksiniz. senin oyunda.
Kapak Değerlendirmesi
Siper bulucu, hedef düşman biriminden belirli bir mesafe arasındaki koruma noktalarını değerlendirir. Kapak demo projesinde bunlara sırasıyla minimum ve maksimum saldırı aralığı diyorum. Bulucu, kapsamı maksimum saldırı menzili olan sınırlayıcı kutu içindeki noktalar için oktree’yi sorgular ve ardından düşmana minimum saldırı menzilinden daha yakın olan noktaları filtreler. Buna ünitemizin optimum aralığı diyelim .
Daha sonra, aşağıdaki koşulların geçerli olduğu ilkini bulana kadar optimum aralığında kapak noktalarını yineler:
- Birim, düşmanı doğrudan siperden vuramaz
- Ünite dikizleyerek veya siperden dışarı doğru eğilerek düşmanı vurabilir
- Düşmanın görüş hattı diğer birimler tarafından engellenmez
- Ünite, navmesh üzerinde yol bulma yoluyla kapak noktasına ulaşabilir
Birliğimizin dikizleyerek veya siperden dışarı doğru eğilerek düşmanı vurup vuramayacağını kontrol etmek için, birimin eğilme (veya gözetleme) yeteneği parametresi tarafından yönlendirilen iki ray yayını kullanıyoruz. Bu, ünitenin konumuna, baktığı yere dik bir yönde eklenen basit bir şamandıra ofsetidir.
Açık mavi ok: Düşmanı öne doğru eğerek vuramaz
Turuncu ok: Eğilerek düşmanı vurabilir
Yukarıdaki ekran görüntüsünde, sarı bir birim, mavi birime güvenli bir şekilde çarpabileceği bir nokta belirledi, böylece mavi bir kapak için kapışırken karşılık gelen kapak noktasına hareket ediyor.
Ünitenin her iki tarafında kontrol iki kez yapılır: bir kez ayakta durma pozisyonundan ve başarısız olursa çömelmiş bir pozisyondan. Bu, en kötü durum senaryosunda 4 raycast ile sonuçlanır – ayakta: sol, ayakta: sağ, çömelmiş: sol, çömelmiş: sağ.
İyi bir nokta bulunana kadar her kapak noktası için aynı prosedür tekrarlanır ve sonuçta <kötü koruma noktaları & g t; x 5 ray yayını genel olarak.
Kuvvet alanları söz konusu olduğunda durum biraz farklıdır: Buradaki tek şart, birimin düşmanını doğrudan koruma noktasından vurabilmesidir. Diğer bir deyişle, yalın / dik kontroller yapılmaz, ancak gerekli olan fazladan bir kontrol vardır: ünite kalkanın içinden geçmelidir.
Bunun için kaputun altındaki Shield nesne kanalımızı kullanan özel NonBlockShield çarpışma ön ayarımızı kullanmalıyız . Yani, bu genel olarak 2 raycast ile sonuçlanır: biri NonUnits’e ve diğeri Shields’a karşı ve her ikisi de kuvvet alanı tipi korumanın kabul edilebilir olması için başarılı olmalıdır.
İstatistikler
Kapak sistemi, uygun bir şekilde STATGROUP_CoverSystem adlı kendi istatistik grubuyla birlikte gelir . Aşağıdaki bilgileri toplar:
- Örtü bulmak için harcanan zaman (döngü sayacı)
- Toplamda ortaya çıkan görev sayısına eşit olan FindCover’a yapılan toplam çağrı sayısı (dword)
- Oyunda siper bulmak için harcanan toplam süre (float)
- Kapak oluşturmak için harcanan zaman (döngü sayacı)
- Toplam kapak oluşturma çağrı sayısı (hem uçta yürüme hem de 3d nesne taraması dahildir)
- Teminat oluşturmak için harcanan toplam süre (her iki yöntemi içerir)
- Etkin görev sayısı (dword)
Eylemde görmek için konsola stat CoverSystem yazın .
Profil oluşturma
Özel istatistikler ayarlandığından, kapak sisteminin profilini çıkarmak çok kolaydır. Sadece konsola stat startfile ve stat stopfile yazın ve Window => Developer To ols altındaki Session Frontend’i kullanarak oluşan günlük dosyasını görüntüleyin .
Sonuç
Özetle, sağlam bir kapak sistemi, kapak oluşturma için iki ayrı teknik kullanır: 3B nesne tarama ve navmesh kenar yürüyüşü. İlki, kuvvet alanı tipi koruma (statik kalkanlar) için en iyisidir, ikincisi ise diğer her şey için (manzaralar, nesneler vb.) İyi çalışır.
Nesne tarama, aktörleri 3B ızgaralar halinde dilimlemeyi içerirken, navmesh kenar yürüyüşü, çıkıntı algılama için isteğe bağlı destekle mevcut navmesh polislerini bir alanı geçmek için alır.
Her iki teknik de verileri sekizli olarak depolar ve bu da verimli mekansal arama olanakları sağlar.
Gerçek zamanlı dinamik güncellemeler, Recast’in döşeme güncelleme etkinliklerine abone olarak ve zaman dilimleme ile etkinleştirilir.
Çalışma zamanında örtü noktaları bulma, birimler için “gözetleme” veya “eğilme” ofsetleri tanımlanarak daha çok yönlü hale getirilir.
Ray yayını sayısını azaltan çıkıntı algılamayı devre dışı bırakarak kapak oluşturma performansını artırabilirsiniz.
Navmesh tabanlı tekniğin en iyi şekilde çalışması için bazı ekstra adımlar atmalısınız, örneğin, navigasyon değiştirici birimlerini harita üzerinde, içinde gezinme bulunan daha büyük nesnelerin olduğu yerlere yerleştirmek gibi. Özel nesne kanalları, izleme kanalları ve çarpışmalar gibi bazı proje kurulumları da gereklidir.
Eminim şimdiye kadar benden yeterince aldınız, öyleyse neden demo projesini indirmiyorsunuz ve yukarıda tartışılan tüm tekniklerin tamamen işlevsel bir uygulamasını içeren kaynak kodunu araştırmıyorsunuz? Bir şey net değilse veya takılırsanız, aşağıdaki yorumlar bölümünde bana bildirmekten çekinmeyin!
Demo projesini ve kaynak kodunu indirin.
Dilerseniz Bir Sonra Ki Blog Sayfalarımıza Göz Atabilirsiniz..
Görüşmek Üzere Hoşçakalın WebOdasıyla Kalın..
Hata!
Yorumunuz Çok Kısa, Yorum yapabilmek için en az En az 10 karakter gerekli