Üst Öğe: learn-game-mechanics-in-unreal-editor-for-fortnite Order: 0 Type: Tutorial Tags: verse Tags: cihazlar Tags: NPC Davranışı Hero-image: hero2.png Topic-image: TopicImage.png Social-image: social2.png
Sıhhiyeciler birçok oyunda yaygın olarak görülen bir karakter arketipidir. Sıhhiyecinin görevi yakınındaki karakterleri iyileştirmektir. Ayrıca takım arkadaşları hasar aldıktan sonra onların iyileşmelerine yardımcı olur. Sıhhiyeciler oyuna bağlı olarak farklı roller üstlenebilirler. Örneğin bir hastanedeki hastalara hizmet veren doktorlar, takımlarının hem savaşmasına hem de iyileşmesine yardımcı olan çatışma sıhhiyecileri veya herhangi bir oyuncuyu iyileştiren tarafsız istasyonlar olabilirler.
Bu örnekte oluşturacağın sıhhiyeci karakteri bir mantık kuralı setini takip etmektedir.
- Boşta:
- Aracıları İyileştirmeye Başla
- İyileştirme Döngüsü
- Aracıya Git
Sıhhiyeci ilk başta boştadır ve bir aracı iyileştirme alanına girene kadar devriye gezer. Alana giren aracı, sıhhiyecinin iyileştirme kuyruğuna eklenir. Sıhhiyeci, iyileştireceği bir sonraki aracıyı takip etmelidir, bu yüzden kuyruk, ilk gelen ilk çıkar yapısında olduğu için bu amaçla faydalı bir veri yapısı sağlar. Diğer bir deyişle, iyileştirme alanına ilk giren karakter, iyileştirilecek ilk karakter olacaktır.
Sıhhiyeci iyileştireceği bir sonraki aracıyı aldığında öncelikle aracının canının iyileştirme eşiği altında olup olmadığını kontrol eder. Can eşiğin altındaysa aracının canı eşiğe ulaşana veya aracı iyileştirme alanından çıkana kadar onu belirli bir hızda iyileştirmeye başlar. İyileştirme sırasında sıhhiyeci sürekli olarak aracıya giderek ona yakın kalmaya çalışacaktır. Aracının canı yeniden eşik değerine ulaştığında sıhhiyeci iyileştirilecek olan bir sonraki aracıya geçer ve süreci baştan başlatır. İyileştirilecek bir aracı yoksa sıhhiyeci boşta durumuna geri döner.
Aşağıdaki Sonlu Durum Makinesini kullanarak sıhhiyeci NPC’nin mantığını görüntüleyebilirsin. Sonlu durum makineleri hakkında daha fazla bilgi için NPC Davranışlarını Anlama bölümüne göz at.
Bu kılavuzu tamamladığında NPC Davranış Kodunu kullanarak yakında olup canı belirli bir eşiğin altında olan diğer karakterleri iyileştiren özel bir sıhhiyeci karakterini nasıl oluşturacağını öğrenmiş olacaksın. Tam kod, referans olması için bu kılavuzun sonuna eklenmiştir.
Yeni Bir NPC Davranış Kodu oluşturma
Kendi NPC Sıhhiyeci Karakterini oluşturmaya başlamak için medic_example adlı yeni bir NPC Davranış kodu oluştur. Kendi NPC davranış kodunu oluşturma konusunda daha fazla bilgi için Kendi NPC Davranışını Oluşturma bölümüne bak. Visual Studio Code’da Verse dosyasını aç.
UEFN’de yakındaki oyuncuları iyileştiren bir sıhhiyeci karakteri çıkaran bir NPC Davranış Kodu oluşturmak için aşağıdaki adımları izle.
İyileştirme Kuyruğunu Uygulama
NPC Davranış Kodu, karakter hareketi ve hata ayıklama görselleştirmesi için kullanılan birkaç değerle başlar. Bu kodda hepsine ihtiyaç duymayacağın için gereksiz kodları şu anda kaldırmalısın.
-
medic_examplesınıf tanımının üst kısmındaOnBegin()’den önceki değerleri kaldır. Sıhhiyeci karakterin diğer karakterlere gitmek için beklemeyecek ve iyileştirme sırasında onları takip edecektir. Bu örnek için hata ayıklama değerlerine ihtiyacın yok, dolayısıyla sıhhiyecin karakterleri iyileştirirken bunu görselleştirmek için diğer objeleri kullanacaksın. -
OnBegin()’de, birinciififadesinde karakterin arayüzlerini aldıktan sonrathenifadesinin içindeki kodu sil. Sıhhiyeci karakterin çıktıktan sonra noktalar arasında döngüye girmesi gerekmez. Bunun yerine çıkma noktasının çevresinde devriye gezerek karakterlerin iyileşmesini bekleyecektir. -
“DrawDebugLocation()” ve “DrawDebugLookAt()” fonksiyonlarını kaldır. Bu örnekte hata ayıklama değerlerini kullanmayacağın için onları kullanan ilişkili fonksiyonlara da ihtiyacın olmayacak.
Gerekli olmayan kodları kaldırdıktan sonra sıhhiyeci karakterini inşa etmeye başlayabilirsin.
-
medic_examplesınıf tanımının üst kısmına aşağıdaki değerleri ekle:-
HealingThresholddüzenlenebilir kayan değeri. Karakterlerin iyileştirilebilmesi için bu can eşiğinin altında olması gerekir.# Bir karakterin iyileştirilebilmesi için altında olması gerektiği CP eşiği. @editable HealingThreshold:float = 50.0 -
“HealingDelay” adlı düzenlenebilir bir kayan değer ekle. Bu değer, karakterler iyileştirilirken her bir iyileştirme örneği arasında beklenmesi gereken süredir. Sıhhiyecinin daha yavaş veya daha hızlı iyileştirmesini istemene bağlı olarak bu değeri değiştir.
# Bir karakterin iyileştirilebilmesi için altında olması gerektiği CP eşiği. @editable HealingThreshold:float = 50.0 # Karakterleri iyileştirmeden önce beklenecek süre @editable HealingDelay:float = 1.5 -
HealingAmountdüzenlenebilir kayan değeri. Bu değer, iyileştirme örneği başına karakterlerin iyileştirileceği can miktarıdır. Sıhhiyeci NPC’in bir karakteri iyileştirdiğinde, karakteri herHealingDelaysaniyedeHealingAmountkadar iyileştirecektir.# Karakterleri iyileştirmeden önce beklenecek süre @editable HealingDelay:float = 1.5 # Karakterlerin iyileştirme örneği başına iyileştirileceği miktar @editable HealingAmount:float = 5.0 -
HealVolumedüzenlenebilir düzenleyici alanı. Bu, karakterlerin iyileşmek için gireceği bölgedir. Bu örnekte bir düzenleyici alanı kullanacaksın, çünkü düzenleyici alanında sıhhiyecinin bağlanarak iyileşmeye ihtiyaç duyabilecek karakterler olup olmadığını kontrol edebileceği birAgentEntersEventvardır.# Karakterlerin iyileştirme örneği başına iyileştirileceği miktar @editable HealingAmount:float = 5.0 # Karakterlerin iyileşmek için gireceği bölge. @editable HealVolume:mutator_zone_device = mutator_zone_device{} -
VFXSpawnerdüzenlenebilir görsel efekt çıkma yeri. Görsel geribildirim, kodunun çalıştığından emin olmak açısından önemlidir. Bu nedenle, bir karakter iyileştirilirken efektler çıkarmak için bir görsel efekt çıkma yeri kullanacaksın.# Karakterlerin iyileşmek için gireceği bölge. @editable HealVolume:mutator_zone_device = mutator_zone_device{} # Karakterler iyileştirilirken görsel efekt oynatmak için görsel efekt çıkma yeri. @editable VFXSpawner:vfx_spawner_device = vfx_spawner_device {} -
AgentToFollowadlı değişken bir isteğe bağlıagent. Bu, sıhhiyecinin karakteri iyileştirirken takip etmesi gereken bir karakter başvurusunu depolar.# Karakterler iyileştirilirken görsel efekt oynatmak için görsel efekt çıkma yeri. @editable VFXSpawner:vfx_spawner_device = vfx_spawner_device {} # İyileştirildiği sırada takip edilecek aracı var AgentToFollow:?agent = false -
AgentsToHealadlı değişken bir aracılar kuyruğu. Birden fazla karakterin iyileştirilmeye ihtiyacı varsa sıhhiyecin karakterleriHealVolume’a girdikleri sıraya göre iyileştirir. Kuyruk kodunu bir sonraki adımda ayarlayacaksın. Kuyruk veri yapısı hakkında daha fazla bilgi için Verse’te yığınlar ve kuyruklar bölümüne bak.# İyileştirildiği sırada takip edilecek aracı var AgentToFollow:?agent = false # Birden fazla aracının iyileşme bölgesine girmesi durumunda iyileştirilecek aracılar kuyruğu. var AgentsToHeal<public>:queue(agent) = queue(agent){} -
UpdateRateSecondsdeğişken kayan değeri. Bu değer,HealVolumeveVFXSpawnerkonumunun güncellenmesi arasında beklenecek süredir.# Birden fazla aracının iyileşme bölgesine girmesi durumunda iyileştirilecek aracılar kuyruğu. var AgentsToHeal<public>:queue(agent) = queue(agent){} # HealVolume ve VFXSpawner konumunun ne kadar çabuk güncelleneceğini belirtmek için kullanılır UpdateRateSeconds<private>:float = 0.1
-
-
“AgentsToHeal” kuyruğunu uygulamak için bu adımın sonunda verilen kodu kullanacaksın.
- Verse Gezgini’ne geri dönerek projenin adına sağ tıkla ve Projeye yeni Verse dosyası ekle’yi seçerek Verse Kodu Oluştur penceresini aç.
-
Verse Kodu Oluştur penceresinde kodun olarak seçmek üzere Verse Sınıfı’na tıkla.
-
Sınıf Adı alanındaki metni “queue” olarak değiştirerek Verse sınıfına bir ad ver.
-
Verse dosyasını oluşturmak için Oluştur butonuna tıkla.
-
Verse Gezgini’nde Verse dosyanın adına çift tıklayarak dosyayı Visual Studio Code’da aç.
-
“queue” dosyandaki kodu aşağıdaki kodla değiştir. Bu kod bir liste verileri yapısı kullanarak
typetüründe genel bir kuyruk uygular. Kuyruk uygulaması, kuyruğu oluşturduğun türden bağımsız olarak çalışacağı için bu bir parametrik tür örneğidir. Örneğinde bir karakter kuyruğu kullanacağın içinmedic_exampleiçindeki kuyruk tanımınqueue(agent)olacak.list(t:type) := class: Data:t Next:?list(t) queue<public>(t:type) := class<internal>: Elements<internal>:?list(t) = false Size<public>:int = 0 Enqueue<public>(NewElement:t):queue(t) = queue(t): Elements := option: list(t): Data := NewElement Next := Elements Size := Size + 1 Dequeue<public>()<decides><transacts>:tuple(queue(t), t) = List := Elements? (queue(t){Elements := List.Next, Size := Size - 1}, List.Data) Front<public>()<decides><transacts>:t = Elements?.Data CreateQueue<public><constructor>(InData:t where t:type) := queue(t): Elements := option: list(t): Data := InData Next := false Size := 1 -
Verse kodlarını ayrı klasörler halinde düzenlemen hem organize olmana yardımcı olabilir hem de sık kullanılan dosyalara kolayca başvurma yöntemleri sunabilir. Bunun bir örneği olarak bu projedeki NPC davranışlarını depolamak için bir klasör oluşturacaksın. Visual Studio Code’da, Yeni Klasör butonuna basarak UEFN projende yeni bir klasör oluştur. Klasöre
npc_behaviorsadını ver. Ardındanmedic_exampleVerse dosyanı yeni klasöre sürükle.
medic_example dosyasındaki kodun artık doğru şekilde derlenmelidir.
Bir Bölgenin İçindeki Karakterleri İyileştirme
Yaralı bir karakter HealVolume bölgesine girdiğinde karakterin canı HealingThreshold eşiğinin altındaysa sıhhiyeci karakterin onu iyileştirmeye başlamalıdır. Karakterin canı HealingThreshold eşiğinin üzerine çıktığında sıhhiyecin o karakteri iyileştirmeyi bırakmalı ve iyileştirilmeye ihtiyaç duyan bir sonraki karaktere geçmelidir. Birden fazla karakter söz konusu olduğunda sıhhiyecin karakterleri HealVolume’e girdikleri sıraya göre iyileştirmelidir. Karakterler HealVolume’e girdiklerinde onları iyileştirmek için aşağıdaki adımları izle.
-
“medic_example” dosyana geri dönerek “OnBegin()”de “then” ifadesinden sonra bir “loop” başlat.
loopiçindeAgentsToHealkuyruğundanDequeue()fonksiyonunun sonucunu al ve sonucuDequeueResultadlı bir değişken içine kaydet.then: loop: # Kuyruktaki iyileştirilecek bir sonraki aracıyı al. İyileştirilecek bir aracı varsa AgentToHeal’i çağırarak onu iyileştir. # İyileştirilecek bir aracı yoksa HealVolume’e bir aracı girene kadar bekle if: DequeueResult := AgentsToHeal.Dequeue[] -
DequeueResultdeğişkeni, hem birinci öğesi kaldırılmış olarakAgentsToHealkuyruğunun hem de kuyruğun önündeki aracının bir kopyasını döndüren birtuplefonksiyonudur.AgentsToHeal’i demetteki birinci değere ayarlayarak güncelle ve ikinci değeriAgentToHealolarak kaydet.if: DequeueResult := AgentsToHeal.Dequeue[] set AgentsToHeal = DequeueResult(0) AgentToHeal := DequeueResult(1) -
İyileştirilecek bir aracı olduğunda onu “HealVolume”’da olduğu sırada iyileştirmeye başlamalısın. Bunu gerçekleştirmek için
HealCharacter()adlı yeni bir fonksiyon tanımlayacaksın.medic_examplesınıf tanımınaHealCharacter()adlı yeni bir fonksiyon ekle. Bu fonksiyon, sıhhiyeci karakterlerin hemNavigatablehem deFocusablearayüzleri için fonksiyon bağımsız değişkeni olarakAgentToHeal’i alır. Bir karakteri iyileştirirken çeşitli asenkron görevler gerçekleştirmesi gerektiğinden bu fonksiyona ““ değiştiricisini ekle. # Karakteri iyileştir, ardından HealingDelayAmount süresi kadar bekle. # Karakterin sağlığı HealingThreshold eşiğine ulaştığında # veya karakter HealVolume bölgesinden ayrıldığında sona erer. HealCharacter(AgentToHeal:agent, Navigatable:navigatable, Focusable:focus_interface)<suspends>:void= -
HealCharacter’da,AgentToHeal’ın bölge içinde olup olmadığınıIsInVolume[]’u çağırarak ve bağımsız değişken olarakAgentToHeal’i ileterek kontrol et. Aracı bölgede ise onu iyileştirmeye başlayabilirsin. Tüm iyileştirilebilir aracılar, aracınınfort_character’ının bir parçası olanhealthfularayüzünü uygular. Aracının “fort_character” değerini al ve “CharacterToHeal” değerine kaydet.HealCharacter(AgentToHeal:agent, Navigatable:navigatable, Focusable:focus_interface)<suspends>:void= # Karakteri yalnızca HealVolume içindeyse iyileştir if: HealVolume.IsInVolume[AgentToHeal] CharacterToHeal := AgentToHeal.GetFortCharacter[] -
Karakter iyileştirmeye hazır olduğunda sıhhiyecinin iyileştirilmekte olan karaktere yakın kaldığından emin olmalısın.
MakeNavigationTarget’ı kullanarakAgentToHeal’den birnavigation_targetoluştur ve onuNavigationTargetadlı bir değişkene kaydet. Daha sonra sıhhiyecininAgentToHeal’e gitmesini sağlamak için birbranchifadesinde NPC’ninnavigatablearayüzünü kullanarakNavigateTo()fonksiyonunu çağır. Ayrıcabranchfonksiyonunda, sıhhiyecininAgentToHeale odaklandığından emin olmak içinMaintainFocus()fonksiyonunu çağır. Bu bağlamda birbranchifadesi kullanarak hemNavigateTo()hem deMaintainFocus()’u asenkron bir şekilde aynı anda çalıştırabilir vebranchsonrasında da herhangi bir kodu anında çalıştırabilirsin. Branch ifadeleri hakkında daha fazla bilgi için Verse’te branch sayfasına bak.# Karakteri yalnızca HealVolume içindeyse iyileştir if: HealVolume.IsInVolume[AgentToHeal] CharacterToHeal := AgentToHeal.GetFortCharacter[] then: Print("Karakter bölge içinde, iyileştirmeye başla") NavigationTarget := MakeNavigationTarget(AgentToHeal) branch: Navigatable.NavigateTo(NavigationTarget) Focusable.MaintainFocus(AgentToHeal) -
Sıhhiyecin bir karakteri iyileştirirken görsel efekt oynatmak için “VFXSpawner”’ı etkinleştir. Ardından bir
deferifadesindeVFXSpawner’ı devre dışı bırak.VFXSpawner’ın devre dışı bırakılmasına ilişkin kod birdeferifadesinde olduğundan kod, geçerli kapsam çıkış yapana kadar çalışmayacaktır. Bu durumda kod yalnızca fonksiyon sona erdiğinde çalışacağı için fonksiyonda gerçekleşecek son şeyin bu olacağı kesindir. Defer ifadeleri hakkında daha fazla bilgi için defer sayfasına bak.branch: Navigatable.NavigateTo(NavigationTarget) Focusable.MaintainFocus(AgentToHeal) VFXSpawner.Enable() defer: VFXSpawner.Disable() -
CharacterToHealiyileştirilirken şu iki koşuldan biri gerçekleştiğinde iyileştirme durmalıdır: Karakterin canıHealingThresholdeşiğini aşacak düzeyde iyileştirilmiştir veya karakterHealVolumebölgesinden çıkmıştır. Bunu başarmak için birraceifadesi kullanacaksın.HealVolume.AgentExitsEventüzerinde birloopileAwait()arasında birraceifadesi oluştur.branch: Navigatable.NavigateTo(NavigationTarget) Focusable.MaintainFocus(AgentToHeal) VFXSpawner.Enable() defer: VFXSpawner.Disable() race: loop: HealVolume.AgentExitsEvent.Await() -
loopiçindeGetHealth()kullanarak karakterin mevcut canını al veCurrentHealthadlı bir değere kaydet. Sonra birififadesindeCurrentHealthileHealingAmountdeğerlerinin toplamınınHealingThresholddeğerinden fazla olup olmadığını kontrol et. Fazlaysa sıhhiyecin iyileştirmeyi durdurmalı vebreakile döngüden çıkmalıdır. Ancak karakterin mevcut canı iyileştirme eşiğinin çok az altındaysa karakteri iyileştirme eşiğine kadar iyileştirmen gerekir. Birinci ifadenin içine,CurrentHealthdeğerininHealingThresholdeşiğinden az olup olmadığını kontrol eden ikinci birififadesi ekle. Azsa karakterin canınıHealingThresholdolarak ayarla.race: loop: CurrentHealth := CharacterToHeal.GetHealth() if(CurrentHealth + HealingAmount > HealingThreshold): if (CurrentHealth < HealingThreshold): CharacterToHeal.SetHealth(HealingThreshold) PrintNPCB("Karakter HealingThreshold eşiğine ulaştı, iyileştirme durduruluyor") break HealVolume.AgentExitsEvent.Await() -
CurrentHealthileHealingAmountdeğerlerinin toplamıHealingThresholddeğerinden büyük değilse karakterin canınıCurrent HealthileHealingAmounttoplamı olarak ayarla.if(CurrentHealth + HealingAmount > HealingThreshold): if (CurrentHealth < HealingThreshold): CharacterToHeal.SetHealth(HealingThreshold) PrintNPCB("Karakter HealingThreshold eşiğine ulaştı, iyileştirme durduruluyor") break else: CharacterToHeal.SetHealth(CurrentHealth + HealingAmount) -
loopsonundaHealingDelaykadar bir süre boyunca uyu. Bu uyku olmadan karakterler her simülasyon güncellemesinde iyileştirilecektir, bu nedenleHealingDelayonların anında iyileştirilmesini önler. TamamladığınHealCharacter()kodun aşağıdaki gibi görünmelidir.# Karakteri iyileştir, ardından HealingDelayAmount süresi kadar bekle. # Karakterin sağlığı HealingThreshold eşiğine ulaştığında # veya karakter HealVolume bölgesinden ayrıldığında sona erer. HealCharacter(AgentToHeal:agent, Navigatable:navigatable, Focusable:focus_interface)<suspends>:void= # Karakteri yalnızca HealVolume içindeyse iyileştir if: HealVolume.IsInVolume[AgentToHeal] CharacterToHeal := AgentToHeal.GetFortCharacter[] then: Print("Karakter bölge içinde, iyileştirmeye başla") NavigationTarget := MakeNavigationTarget(AgentToHeal) branch: Navigatable.NavigateTo(NavigationTarget) Focusable.MaintainFocus(AgentToHeal) VFXSpawner.Enable() defer: VFXSpawner.Disable() race: loop: CurrentHealth := CharacterToHeal.GetHealth() if(CurrentHealth + HealingAmount > HealingThreshold): if (CurrentHealth < HealingThreshold): CharacterToHeal.SetHealth(HealingThreshold) PrintNPCB("Karakter HealingThreshold eşiğine ulaştı, iyileştirme durduruluyor") break else: CharacterToHeal.SetHealth(CurrentHealth + HealingAmount) Sleep(HealingDelay) HealVolume.AgentExitsEvent.Await() -
OnBegin()dizisine dönerekloopiçindekithenifadesindeAgentToHeal’ı,Navigablearayüzünü veFocusablearayüzünü ileterekHealCharacter()’ı çağır.if: DequeueResult := AgentsToHeal.Dequeue[] set AgentsToHeal = DequeueResult(0) AgentToHeal := DequeueResult(1) then: Print("İyileştirilecek bir sonraki aracı kuyruktan çıkarıldı") HealCharacter(AgentToHeal, Navigatable, Focusable) -
Sıhhiyecinin yakınında her zaman iyileştirilecek bir karakter olmayacak ve
Dequeue[]fonksiyonu,AgentsToHealkuyruğunda aracı olmaması halinde başarısız olacaktır. Bu sorunu çözmek içinloop’un sonuna birelseifadesi ekle. Buififadesinin içindeHealingDelaykadar bir süre içinSleep()’i çağır, ardındanHealVolume.AgentEntersEventiçinAwait()’i uygula. Böylece sıhhiyeci karakterinAgentsToHealkuyruğunda sonsuza kadarDequeue[]’yu çağırmayacak ve onun yerine döngüyü yeniden başlatmadan önce yeni bir karakterinHealVolumebölgesine girmesini bekleyecektir. Tamamlanan döngün aşağıdaki gibi görünmelidir.loop: # Kuyruktaki iyileştirilecek bir sonraki aracıyı al. İyileştirilecek bir aracı varsa AgentToHeal’i çağırarak onu iyileştir. # İyileştirilecek bir aracı yoksa HealVolume’e bir aracı girene kadar bekle if: DequeueResult := AgentsToHeal.Dequeue[] set AgentsToHeal = DequeueResult(0) AgentToHeal := DequeueResult(1) then: Print("İyileştirilecek bir sonraki aracı kuyruktan çıkarıldı") HealCharacter(AgentToHeal, Navigatable, Focusable) else: Print("AgentsToHeal boş!") Sleep(HealingDelay) HealVolume.AgentEntersEvent.Await()
Karakterlerin Ne Zaman İyileştirme Bölgesinde Olduğunu Takip Etme
Karakterlerin HealVolume’e ne zaman girdiğini veya buradan ne zaman çıktığını öğrenmek için HealVolume’ün hem AgentEntersEvent’ini hem de AgentExitsEvent’ini yeni fonksiyonlara bağlayacaksın.
-
medic_examplesınıf tanımınaOnAgentEnters()adlı yeni bir fonksiyon ekle. Bu fonksiyon,HealVolumebölgesine yeni giren aracıyı alır veAgentsToHealkuyruğuna yerleştirir.OnAgentEnters(EnteredAgent:agent):void= Print("Aracı iyileştirme bölgesine girdi") -
OnAgentEnters()’da, bölgedeki aracının sıhhiyeci karakteri olup olmadığını kontrol et. Sıhhiyeci karakteriyseAgentsToHealkuyruğunu,Enqueue[]’nunEnteredAgentile birlikte çağrılmasının sonucuna ayarla. TamamladığınOnAgentEnters()fonksiyonun aşağıdaki gibi görünmelidir:OnAgentEnters(EnteredAgent:agent):void= Print("Aracı iyileştirme bölgesine girdi") if (EnteredAgent <> GetAgent[]): set AgentsToHeal = AgentsToHeal.Enqueue(EnteredAgent) -
Bir aracı
HealVolumebölgesinden çıktığında onuAgentsToHealkuyruğundan da çıkarman gerekmez. Bunun nedeni,OnBegin()içindeki döngününDequeue[]’yu zaten bir döngü içinde çağırıyor olmasıdır. Ancak bir aracı örneklerindeki bölgeden çıktığında kod çalıştırmak isteyebilirsin, bu yüzden şimdilik bunun için bir fonksiyon oluşturacaksın.medic_examplesınıf tanımınaOnAgentExits()adlı yeni bir fonksiyon ekle.OnAgentExits(ExitAgent:agent):void= Print("Aracı iyileştirme bölgesinden çıktı") -
OnBegin()’de,HealVolume’ünAgentEntersEvent’iniOnAgentEnters’a,AgentExitsEvent’ini iseOnAgentExits’e bağla. Bu, devre dışı durumda başlaması gerektiğinden burası, karakter çıkma yerindeDisable()’ı çağırmak için iyi bir yerdir.OnBegin<override>()<suspends>:void= Print("Merhaba Yapay Zekâ!") VFXSpawner.Disable() HealVolume.AgentEntersEvent.Subscribe(OnAgentEnters) HealVolume.AgentExitsEvent.Subscribe(OnAgentExits)
İyileştirme Bölgesini Sıhhiyeciyle Birlikte Taşıma
Sıhhiyeci karakteri hareket ettiğinde HealVolume bölgesinin de onun geçerli konumuna uyacak şekilde taşınması gerekir. Aynı durum VFXSpawner için de geçerlidir. Bunu yapmak için DeviceFollowCharacter() adlı yeni fonksiyonu kullanacaksın.
-
medic_examplesınıf tanımınaDeviceFollowCharacter()adlı yeni bir fonksiyon ekle. Bu fonksiyonun cihaz konumlarını sürekli olarak güncellemek için asenkron bir şekilde çalışması gerekir. Bu nedenle fonksiyona ““ değiştiricisini ekle. DeviceFollowCharacter()<suspends>:void= -
DeviceFollowCharacter()fonksiyonunun içinde öncelikleGetAgent[]’ı kullanarak aracıyı alıp ardındanGetFortCharater[]’ı çağırarak sıhhiyecininfort_character’ını al.DeviceFollowCharacter()<suspends>:void= if: # Bu davranışın ilişkili olduğu aracıyı (Yapay Zekâ Karakteri) al. Agent := GetAgent[] # Fortnite karakterine özgü davranışlara, olaylara, fonksiyonlara ve arayüzlere erişmek için aracının fort_character arayüzünü al. Character := Agent.GetFortCharacter[] -
Şimdi
HealVolumeveVFXSpawner’ı sürekli olarakCharacterın konumuna taşımalısın. Bunu, her iki cihazda da birMoveTo()döngüsü oluşturarak yapabilirsin. Birloopbaşlat veCharacter’ın dönüşümünü alıp onuCharacterTransformadlı bir değişkene kaydet.if: # Bu davranışın ilişkili olduğu aracıyı (Yapay Zekâ Karakteri) al. Agent := GetAgent[] # Fortnite karakterine özgü davranışlara, olaylara, fonksiyonlara ve arayüzlere erişmek için aracının fort_character arayüzünü al. Character := Agent.GetFortCharacter[] then: loop: CharacterTransform := Character.GetTransform() -
Hem
VFXSpawnerhem deHealVolumeüzerindeMoveTo()’yu çağırarak bunlarıCharacterTransform.Translation’a veCharacterTransform.Rotation’a taşı. SüreyiUpdateRateSecondssaniye olarak ayarla. Son olarakUpdateRateSecondskadar bir süre içinSleep()’i çağırarak cihazların her simülasyon güncellemesinde konumlarını güncellemesini önle. Her simülasyon güncellemesinde cihaz konumunun güncellenmesi, cihazlarında bozuk hareketlere neden olabilir. TamamladığınDeviceFollowCharacter()kodun aşağıdaki gibi görünmelidir.DeviceFollowCharacter()<suspends>:void= if: # Bu davranışın ilişkili olduğu aracıyı (Yapay Zekâ Karakteri) al. Agent := GetAgent[] # Fortnite karakterine özgü davranışlara, olaylara, fonksiyonlara ve arayüzlere erişmek için aracının fort_character arayüzünü al. Character := Agent.GetFortCharacter[] then: loop: CharacterTransform := Character.GetTransform() VFXSpawner.MoveTo(CharacterTransform.Translation, CharacterTransform.Rotation, UpdateRateSeconds) HealVolume.MoveTo(CharacterTransform.Translation, CharacterTransform.Rotation, UpdateRateSeconds) Sleep(UpdateRateSeconds) -
OnBegin()’de, karakter arayüzlerini kaydettiğinififadesinden sonra, fakat döngüden önce birDeviceFollowCharacter()örneği çıkar.
Karakterini Bölüme Ekleme
-
Sıhhiyeci adlı yeni bir NPC Karakter Tanımı oluştur. Yeni NPC karakter tanımına tıklayarak NPC Karakter Tanımı ekranını aç.
-
NPC Karakter Tanımı ekranında aşağıdaki özellikleri değiştir:
-
NPC Karakter Türü altında Tür’ü Muhafız olarak ayarla. Muhafız arayüzünü kullanarak muhafızın tetikte veya şüpheci olduğu durumlara dair olaylar gibi muhafıza özgü karakter işlevselliklerine erişebilir ve takım arkadaşı olarak kullanılacak muhafızlar işe alabilirsin. Muhafızlar silah da kuşanabilirken Özel ve Vahşi Hayvan türündeki karakterler şu anda bunu yapamaz. Ad sekmesi altında karakterinin adını da değiştirebilirsin.
-
NPC Karakter Davranışı altında Davranış’ı Verse Davranışı olarak ayarla. Ardından NPC Davranış Kodu’nu
medic_exampleolarak ayarla. Karakterin, muhafız arayüzündeki işlevselliklere erişmeye devam edecek, ancakOnBeginveOnEndsırasında ne yapacağına karar vermek için senin Verse kodunu kullanacaktır. -
Karakterinin kozmetik görünümünü değiştirmek için Değiştiriciler sekmesindeki Muhafız Çıkma Değiştiricisi altında Kozmetik sekmesine tıkla. Önceden var olan bir kozmetiği seçebilir ya da Karakter Kozmetik Yeniden Hedeflemesi’ni etkinleştirerek özel bir model kullanabilirsin. Karakter kozmetiği yeniden hedeflemesini yalnızca muhafızlar ve Özel türdeki karakterler kullanabilir, vahşi hayvanlar ise kullanamaz. Karakter değiştiricileri ile farklı karakter türlerine bunlardan hangilerinin uygulandığı konusunda daha fazla bilgi için Karakter Tanımı sayfasına bak.
-
-
NPC karakter tanımını kaydet. İçerik Tarayıcısı’nda NPC karakter tanımını bölüme sürükle. Bunu yaptığında otomatik olarak yeni bir karakter çıkma yeri oluşturulacak ve NPC karakter tanımın oraya atanacaktır.
-
Bölüme bir düzenleyici alanı ve bir görsel efekt çıkma yeri cihazı sürükle.
-
Karakter çıkma yerini seç. Anahat Düzenleyicisi’ndeki Kullanıcı Seçenekleri altında:
-
AIBehavior Kodu geçersiz kılma’yı
medic_examplekoduna ayarla. Anahat düzenleyicisindeAIBehaviorKodunu geçersiz kılman bölümdeki cihazlara başvurabilmeni sağlayacak olup HealVolume’ün ile VFXSpawner’ını atamak için bu işlevselliğe ihtiyaç duyacaksın. -
HealVolume’ü düzenleyici alanı olarak, VFXSpawner’ı ise bölüme yerleştirdiğin görsel efekt çıkma yeri olarak ayarla.
-
-
Düzenleyici alanını seç. Anahat Düzenleyicisi’ndeki Kullanıcı Seçenekleri altında Alan Oyun Sırasında Görünür’ü True olarak ayarla. Bunun sonucunda
HealVolumebölgesinin nerede olduğunu ve sıhhiyeci karakteriyle birlikte nasıl hareket ettiğini görselleştirebilmen mümkün olacaktır. -
Görsel Efekt Çıkma Yerini seç. Anahat Düzenleyicisi’ndeki Kullanıcı Seçenekleri altında Görsel Efekt seçeneğini istediğin bir efekte ayarla. Bu örnekte iyileşmeyi iletmek için Kabarcıklar efekti kullanılıyor, ancak sen havai fişekler veya kıvılcımlar gibi farklı bir şey de kullanmayı tercih edebilirsin. Görsel efekti karakterinin ihtiyaçlarına uyacak şekilde değiştir.
-
Bölümüne oynanış testi yapmak için UEFN araç çubuğunda Oturumu Başlat’a tıkla. Oynanış testi yaptığında karakterin, düzenleyici alanına giren yaralı karakterleri iyileştirmelidir. Bir karakter iyileştirilirken görsel efekt oynatılmalı ve sıhhiyeci, iyileştirilmekte olan karakteri takip edip ona odaklanmalıdır.
Tam Kod
CP’si belirli bir eşiğin altında olan karakterleri iyileştiren bir NPC Karakterinin tam kodu aşağıda verilmiştir.
medic_example.verse
using { /Fortnite.com/AI }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Verse.org/Colors }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
# Bir NPC Tanımı veya bir Karakter Çıkma Yeri cihazının Davranış Kodu Geçersiz Kılmasında kullanılabilecek, Verse ile yazılmış bir NPC Davranışı.
medic_example<public> := class(npc_behavior):
# Bir karakterin iyileştirilebilmesi için altında olması gerektiği CP eşiği.
@editable
HealingThreshold:float = 50.0
# Karakterleri iyileştirmeden önce beklenecek süre
@editable
HealingDelay:float = 1.5
# Karakterlerin iyileştirme örneği başına iyileştirileceği miktar
@editable
HealingAmount:float = 5.0
# Karakterlerin iyileşmek için gireceği bölge.
@editable
HealVolume:mutator_zone_device = mutator_zone_device{}
# Karakterler iyileştirilirken görsel efekt oynatmak için görsel efekt çıkma yeri.
@editable
VFXSpawner:vfx_spawner_device = vfx_spawner_device {}
# İyileştirildiği sırada takip edilecek aracı
var AgentToFollow:?agent = false
# Birden fazla aracının iyileşme bölgesine girmesi durumunda iyileştirilecek aracılar kuyruğu.
var AgentsToHeal<public>:queue(agent) = queue(agent){}
# HealVolume ve VFXSpawner konumunun ne kadar çabuk güncelleneceğini belirtmek için kullanılır
UpdateRateSeconds<private>:float = 0.1
OnBegin<override>()<suspends>:void=
VFXSpawner.Disable()
HealVolume.AgentEntersEvent.Subscribe(OnAgentEnters)
HealVolume.AgentExitsEvent.Subscribe(OnAgentExits)
if:
# Bu davranışın ilişkili olduğu aracıyı (Yapay Zekâ Karakteri) al.
Agent := GetAgent[]
# Fortnite karakterine özgü davranışlara, olaylara, fonksiyonlara ve arayüzlere erişmek için aracının fort_character arayüzünü al.
Character := Agent.GetFortCharacter[]
# Karakterin seyahat edeceği belirli hedefler ayarlamak için karakterin gidilebilir arayüzünü al.
Navigatable := Character.GetNavigatable[]
# Karakterin ulaştıktan sonra odaklanacağı belirli hedefler ayarlamak için karakterin focus_interface’ini al.
Focusable := Character.GetFocusInterface[]
then:
# HealVolume ve VFXSpawner’ı, NPC Karakterini sürekli olarak takip edecek şekilde ayarla
spawn{DeviceFollowCharacter()}
loop:
# Kuyruktaki iyileştirilecek bir sonraki aracıyı al. İyileştirilecek bir aracı varsa AgentToHeal’i çağırarak onu iyileştir.
# İyileştirilecek bir aracı yoksa HealVolume’e bir aracı girene kadar bekle
if:
DequeueResult := AgentsToHeal.Dequeue[]
set AgentsToHeal = DequeueResult(0)
AgentToHeal := DequeueResult(1)
then:
PrintNPCB("İyileştirilecek bir sonraki aracı kuyruktan çıkarıldı")
HealCharacter(AgentToHeal, Navigatable, Focusable)
else:
PrintNPCB("AgentsToHeal boş!")
Sleep(HealingDelay)
HealVolume.AgentEntersEvent.Await()
else:
# Kod buraya düşerse aracı ile arayüzleri toplanırken bir hata olmuş demektir
PrintNPCB( "NPC Ayarında NPC Davranış Kodu Hatası",
?Duration := 6.0,
?TextColor := NamedColors.Red )
# Karakteri iyileştir, ardından HealingDelayAmount süresi kadar bekle.
# Karakterin sağlığı HealingThreshold eşiğine ulaştığında
# veya karakter HealVolume bölgesinden ayrıldığında sona erer.
HealCharacter(AgentToHeal:agent, Navigatable:navigatable, Focusable:focus_interface)<suspends>:void=
# Karakteri yalnızca HealVolume içindeyse iyileştir
if:
HealVolume.IsInVolume[AgentToHeal]
CharacterToHeal := AgentToHeal.GetFortCharacter[]
then:
PrintNPCB("Karakter bölge içinde, iyileştirmeye başla")
NavigationTarget := MakeNavigationTarget(AgentToHeal)
branch:
Navigatable.NavigateTo(NavigationTarget)
Focusable.MaintainFocus(AgentToHeal)
VFXSpawner.Enable()
defer:
VFXSpawner.Disable()
race:
loop:
CurrentHealth := CharacterToHeal.GetHealth()
if(CurrentHealth + HealingAmount > HealingThreshold):
if (CurrentHealth < HealingThreshold):
CharacterToHeal.SetHealth(HealingThreshold)
PrintNPCB("Karakter HealingThreshold eşiğine ulaştı, iyileştirme durduruluyor")
break
else:
CharacterToHeal.SetHealth(CurrentHealth + HealingAmount)
Sleep(HealingDelay)
HealVolume.AgentExitsEvent.Await()
# HealVolume ve VFXSpawner cihazlarını, karakterin konumunda MoveTo döngüsü oluşturarak
# karakteri sürekli takip edecek şekilde ayarla.
DeviceFollowCharacter()<suspends>:void=
if:
# Bu davranışın ilişkili olduğu aracıyı (Yapay Zekâ Karakteri) al.
Agent := GetAgent[]
# Fortnite karakterine özgü davranışlara, olaylara, fonksiyonlara ve arayüzlere erişmek için aracının fort_character arayüzünü al.
Character := Agent.GetFortCharacter[]
then:
# HealVolume ve VFXSpawner üzerinde MoveTo döngüsü oluşturarak konumlarını
# NPC Karakteriyle eşleştir
loop:
CharacterTransform := Character.GetTransform()
VFXSpawner.MoveTo(CharacterTransform.Translation, CharacterTransform.Rotation, UpdateRateSeconds)
HealVolume.MoveTo(CharacterTransform.Translation, CharacterTransform.Rotation, UpdateRateSeconds)
Sleep(UpdateRateSeconds)
# NPC Karakteri dışında bir aracı HealVolume bölgesine girdiğinde
# onu AgentsToHeal kuyruğuna ekle.
OnAgentEnters(EnteredAgent:agent):void=
PrintNPCB("Aracı iyileştirme bölgesine girdi")
if (EnteredAgent <> GetAgent[]):
set AgentsToHeal = AgentsToHeal.Enqueue(EnteredAgent)
# Bir aracı HealVolume bölgesinden çıktığında günlüğe PrintNPCB ekle
OnAgentExits(ExitAgent:agent):void=
PrintNPCB("Aracı iyileştirme bölgesinden çıktı")
# Varsayılan bir süre ve renk sağlayan özel sarmalayıcı.
PrintNPCB(Msg:string,?Duration:float = 3.0, ?TextColor:color = NamedColors.Green):void =
Print("[new_npc_behavior] {Msg}", ?Color := TextColor, ?Duration := Duration)
# Bu fonksiyon, NPC yok olduğunda veya dünyadan avlandığında çalışır.
OnEnd<override>():void =
if(Agent := GetAgent[]):
Print(medic_example_message_module.OnEndMessage(Agent))
else:
PrintNPCB("OnEnd")
queue.verse
list(t:type) := class:
Data:t
Next:?list(t)
queue<public>(t:type) := class<internal>:
Elements<internal>:?list(t) = false
Size<public>:int = 0
Enqueue<public>(NewElement:t):queue(t) =
queue(t):
Elements := option:
list(t):
Data := NewElement
Next := Elements
Size := Size + 1
Dequeue<public>()<decides><transacts>:tuple(queue(t), t) =
List := Elements?
(queue(t){Elements := List.Next, Size := Size - 1}, List.Data)
Front<public>()<decides><transacts>:t = Elements?.Data
CreateQueue<public><constructor>(InData:t where t:type) := queue(t):
Elements := option:
list(t):
Data := InData
Next := false
Size := 1
Kendi Kendine Yapabileceklerin
Bu kılavuzu tamamlayarak belirli bir eşiğin altındaki karakterleri otomatik olarak iyileştiren bir sıhhiyeci karakteri oluşturmayı öğrenmiş oldun. Öğrendiklerini kullanarak kendi özel davranışlarına sahip olan kendi sıhhiyeci karakterini oluşturmayı dene.
-
Bir düşmanın bölge içinde olup olmamasına göre hasar verme ve iyileştirme bölgeleri arasında geçiş yapan bir sıhhiyeci oluşturabilir misin?
-
Peki ya karakterleri iyileştirmek için tükenebilen bir kaynak kullanan bir sıhhiyeci? Sıhhiyeci bu kaynağı nasıl geri kazanırdı? Zaman içinde mi yoksa düşmanlara saldırarak mı geri kazanırdı?