Bu örnekteki karakter, Özel türde bir karakter tanımı kullanır çünkü karakterin yalnızca hareket etmesi gerekir ve muhafız veya vahşi hayvan API'sine erişim ihtiyacı yoktur. Karakterin davranışı, verse_commander_character adlı özel bir Verse Davranışı tarafından yönetilir.
Muhafızlar, belirlenen yol boyunca hareket edebilen ve düşman oyunculara saldırmak için düşman haline gelebilen, oyuncu olmayan karakterlerdir (NPC). Vahşi hayvan, tavuk ve yaban domuzu gibi bir hayvandır ve aynı zamanda belirlenen yol boyunca hareket ederek düşman oyunculara saldırabilir.
Özel NPC’yi oluşturmaya başlamak için Verse Gezgini’ni kullanarak verse_commander_character adında yeni bir NPC Davranışı oluştur. Kendi özel NPC davranışlarını oluşturma konusunda bilgi edinmek için Özel NPC Davranışı Oluşturma bölümüne bakabilirsin.
Karakterin aşağıdaki özellikleri bilmesi ve yönetmesi gerekir:
CommandWaitTime: Her komut arasında ne kadar süre bekleneceğini belirtir.
FocusTime: Bir hedefe odaklanmanın ne kadar süreyle zorlanacağını belirtir. Karakterin sola veya sağa döndürülmesi, karakterin
focus_interfaceözelliği kullanılarak, karakterin solundaki veya sağındaki belirli bir noktaya bakması zorlanarak yapılır. Bir hedefe odaklanma, kesintiye uğramadığı sürece tamamlanmadığından, bu değer çok düşük bir sayı olarak (yalnızca karakterin bir yöne bakmasını sağlayacak şekilde dönmesine yetecek bir süre) ayarlanır.ReachRadius: Karakterin navigasyon hedefine “ulaştığını” kabul etmek için hedefine ne kadar yaklaşması gerektiğini belirtir.
VerseCommanderMinigame: Bölümdeki VerseCommanderMinigame referansıdır ve karakterin oradan gelen komutları dinleyebilmesini sağlar.
Görsel Efekt ve Ok Referansları: Farklı içe/dışa ışınlanma görsel efektlerinin (VFX) yanı sıra karakterin yönelimini görmeyi kolaylaştıran İleri Ok nesnesine referans verir.
Verse# A Verse-authored NPC Behavior that can be used within an NPC Definition or a Character Spawner device's Behavior Script Override. verse_commander_character<public> := class(npc_behavior): # The VFX that play when the NPC teleports out. @editable CharacterTeleportOutVFX:vfx_spawner_device = vfx_spawner_device{} # The VFX that play when the NPC teleports in. @editable CharacterTeleportInVFX:vfx_spawner_device = vfx_spawner_device{}Artık karakterin özelliklerini tanımladığımıza göre, şimdi de davranışlarını ve onları yönlendiren fonksiyonları tanımlayalım.
Karakter Hareketi
Bu oyundaki karakter aşağıdaki davranışlara sahiptir:
İleri Git: İleri komutu, karakteri oyun alanında 1 kare ileriye taşır.
Sağa Dön veya Sola Dön: Sağa Dön ve Sola Dön komutları, karakteri sırasıyla sağına veya soluna bakacak şekilde 90 derece döndürür. Bunun aynı zamanda karakteri üzerinde durduğu kareden başka bir yere hareket ettirmeksizin olması gerekir.
Sıfırla: Sıfırla komutu verildiğinde karakter oyun alanındaki başlangıç konumuna geri ışınlanır.
Komut Bekle: Karakterin hareketi doğrudan kontrol edilemediği için bölümdeki VerseCommanderMinigame cihazından gelen komutları dinlemesi gerekir. Tüm komutlarını yerine getirdikten sonra hareketsiz kalacak ve sonraki komutları bekleyecektir.
Bu şablondaki NPC yalnızca birkaç hareket seçeneğine sahip; baktığı yönde bir kare ilerleyebilir, sağa dönebilir veya sola dönebilir. Bu seçeneklerin her biri, karakterin kullanacağı, karaktere TileDistance mesafede yeni bir navigasyon hedefi oluşturan GetNavTarget() fonksiyonuyla gerçekleştirilir. Bu hedef, verilen komutun İleri, Sağ veya Sol olmasına bağlı olarak karakterin yerel ilerisinde, sağında veya solundadır.
# Gets a new navigation target for the NPC based on the current transform and the given command.
GetNavTarget(CurrentTransform:transform, Command:command, TileDistance:vector3):transform=
# Based on the command, get the character's local forward, right, or left (negative right).
Direction :=
if (Command = Commands.Forward):
CurrentTransform.Rotation.GetLocalForward()
else if (Command = Commands.TurnRight):
CurrentTransform.Rotation.GetLocalRight()
else if (Command = Commands.TurnLeft):
-CurrentTransform.Rotation.GetLocalRight()
NPC, Yürüt (Execute) sinyalini aldığında, aldığı komutların listesini yineler ve her komutu ExecuteCommand() fonksiyonuna iletir. Öncelikle karakter için focus_interface ve navigatable arayüzünü alır, ardından komuta bağlı olarak farklı eylemleri gerçekleştirir. İleri, Sağ ve Sol yönleri için NPC’nin kullanacağı yeni dönüşümü bulmak üzere GetNavTarget() çağrısı yapar. Ardından, ya navigatable arayüzden NavigateTo() fonksiyonunu kullanarak yeni dönüşüme doğru ilerler ya da focus_interface kullanarak sağındaki veya solundaki hedefe odaklanır.
# Executes the given command, either moving the NPC forward one tile or turning them left
# or right.
ExecuteCommand(Command:command, TileSize:vector3)<suspends>:void=
if:
# Get the Agent (the NPC).
Agent := GetAgent[]
# Gets the Fortnite Character interface, which gets you access to its gameplay data
# including its AI module for navigation and focus.
Character := Agent.GetFortCharacter[]
Karakter Görsel Efekti
Karakter oyun alanında hareket ettiğinde, yukarıdan aşağıya kameradan görselleştirilmesini kolaylaştırmak için bir ok nesnesi karakterin konumunu ve yönünü gösterir. Bu okun karakteri takip etmesi ve karakter dönüp hareket ettikçe güncellenmesi gerekir. MoveArrow() fonksiyonu, okun konumunu ve yönünü kopyalayarak karakterinkiyle eşleşecek şekilde günceller. CreateArrow() fonksiyonu ok nesnesini oluşturur ve ilk MoveArrow() çağrısını yapar, böylece karakterin başından itibaren nerede olduğunu görebilirsin.
# Creates an arrow prop at the NPC's position that visually shows the orientation of the NPC.
CreateArrow(Agent:agent):void=
if :
Character := Agent.GetFortCharacter[]
then:
var Transform:transform = Character.GetTransform()
# Spawn the arrow prop, then set the mesh and material for the prop.
SpawnPropResult := SpawnProp(ForwardArrowAsset, Transform)
if:
SpawnedProp := SpawnPropResult(0)?
Karakter oyun alanında doğduğunda, yeni bir oyun alanına geçtiğinde veya Sıfırla (Reset) komutuyla oyun alanının başlangıcına sıfırlandığında, hem içe hem de dışa ışınlanma için bir ışınlanma animasyonu oynatılır. Işınlanma efekti oluşturmak için önce karakter ve ok üzerinde Hide() çağrısı yaparız, ardından VFX (Görsel Efekt) çıkma yerini karakterin olduğu yere taşıyıp etkinleştirerek TeleportOutVFX görsel efektini oynatırız. Dışa ışınlama görsel efekti bittiğinde, karakteri yeni konumuna ışınlamamız ve o konumda TeleportInVFX’i oynatmamız gerekir. Hepsi tamamlandığında karakteri yeni konumda göstermek için karakter ya da ok nesnesi üzerinde Show() çağrısı yapabiliriz.
# Hides the NPC and the arrow prop, then teleports both to a new position,
# playing VFX for teleporting in and teleporting out.
PlayVFXAndMoveCharacter(StartPosition:transform)<suspends>:void=
if:
Agent := GetAgent[]
FortCharacter := Agent.GetFortCharacter[]
then:
# Hide the NPC and the arrow.
FortCharacter.Hide()
ForwardArrow.Hide()
Karakterin ışınlanması, karakterin taşınacağı dönüşümü alan ve onu oraya ışınlayan MoveToTile() yardımcı fonksiyonuyla yapılır. Karakterin zemine girerek kesilmesini önlemek için dönüşümün Z değerine küçük bir sapma eklenir.
# Teleports the NPC to the given transform.
MoveToTile(Transform:transform)<transacts><decides>:void=
# Get the Agent (the NPC).
Agent := GetAgent[]
# Gets the Fortnite Character interface, which gets you access to its gameplay data
# including its AI module for navigation and focus.
Character := Agent.GetFortCharacter[]
var NewTransform:transform = Transform
Komutları İşleme
Karakter oyun alanında hareketsizken, bundan sonra ne yapacağını öğrenmek için bekleyip Yürüt (Execute) sinyalini dinlemelidir. Bu işlem AwaitCommands() fonksiyonu içinde gerçekleşir. Bu fonksiyon suspends belirticisine sahiptir, böylece karakterin ExecuteCommandsEvent olayını Await() ile beklemesi gerektiğinden asenkron bir şekilde çalışabilir. Komutlar, bir komut dizisi ile birlikte bu komutlar için kullanılan TileSize’ı içeren bir demet olarak geldiğinden, her birinin ExecuteCommand() fonksiyonu çağrılarak bir for döngüsünde işlenmesi gerekir. Her komut yürütülürken ileri oku gizleriz ve ancak komutun yürütülmesi bittiğinde tekrar gösteririz. Tüm komutların yürütülmesi bittiğinde, Verse Kumandası Mini Oyun cihazına komutlarla işimizin bittiğine ve başka komutlar için hazır olduğumuza dair sinyal veririz.
# Waits for commands to be sent from the verse_commander_minigame, then
# executes each command.
AwaitCommands()<suspends>:void=
if:
Agent := GetAgent[]
then:
# Wait for commands to be sent from the verse commander minigame.
ExecuteResult := VerseCommanderMinigame.ExecuteCommandsEvent.Await()
# For each execute result tuple, execute the command and pass the tile size from the tuple.
Yeni komutları işlemek yerine, Sıfırla düğmesiyle karakter geçerli oyun alanının başlangıcına sıfırlanabilir. Sıfırlama anında gerçekleştiğinden ve komut sırasını kullanmadığından, karakterin bunu Yürüt (Execute) sinyalinden ayrı olarak dinlemesi gerekir. Bu, Verse Kumandası Mini Oyun cihazından BoardResetEvent sinyalini bekleyen AwaitReset() fonksiyonunda gerçekleşir. Gerçekleştiğinde, karakteri oyun alanının başlangıç konumuna taşımak için PlayVFXAndMoveCharacter() çağrısı yapar.
# Waits for the current board to be reset, then moves the
# NPC back to the starting position of the board along with VFX.
AwaitReset()<suspends>:void=
# Wait for the current board to be reset.
# The event payload is the starting position for the board.
StartPosition := VerseCommanderMinigame.BoardResetEvent.Await()
spawn{PlayVFXAndMoveCharacter(StartPosition)}Karakter Oyun Döngüsünü Çalıştırma
Komutları işleyen farklı fonksiyonlar ayarlandığına göre, şimdi sıra karakterin temel oyun döngüsünü oluşturmaya geldi. Karakterin, bir komut listesini işlemek için Yürüt (Execute) sinyalini veya oyun alanının başlangıcına geri dönmek için Sıfırla (Reset) sinyalini sürekli olarak dinlemesi gerekir. Her Yürüt (Execute) sinyali ve Sıfırla (Reset) sinyali beklemenin asenkron olarak gerçekleşmesi gerektiğinden ve bunlar oyun alanı başına birden çok kez olabileceğinden, her ikisinde de döngüyü gerçekleştiren ayrı bir yardımcı fonksiyona ihtiyacın olacak. Bu, karakter için ana oyun döngüsünü çalıştıran CharacterCommandLoop() fonksiyonu tarafından işlenir. Bir race ifadesinde bu fonksiyon, karakterin her zaman komutları dinlediğinden emin olmak için AwaitReset() fonksiyonuyla sürekli olarak AwaitCommands() çağrısı yapan bir döngü arasında yarışır.
# Race between resetting the character to start of the board and awaiting commands for that character.
CharacterCommandLoop()<suspends>:void=
race:
AwaitReset()
loop:
AwaitCommands()Oyun başladığında karakter, Karakter Çıkma Yerinden doğana kadar bölümde olmayacak. Bu, karakter doğduğunda buna bir referansı olmadığı için bölümdeki Verse Kumandası Mini Oyun cihazını bulması gerektiği anlamına gelir. Bunu, verse_commander_minigame_tag Oynanış Etiketi ile objeyi bulmak için GetCreativeObjectsWithTag() kullanarak ve objeyi VerseCommanderMinigame olarak ayarlayarak yapar. Kendi mini oyun deneyimini oluştururken, bölümdeki karakterlerin iletişim kurmaları gereken objeleri bulabilmeleri için etiketlerini doğru şekilde ayarladığından emin olmalısın.
Verse Kumandası Mini Oyun cihazını bulduktan sonra karakterin CreateArrow() fonksiyonunu kullanarak kendisini takip eden ileri oku üretmesi gerekir. Oyun döngüsünü çalıştırmak için Sıfırla sinyali oluştuğunda yeniden başlatmak üzere CharacterCommandLoop() fonksiyonunu sürekli döngüye alması gerekir. Bunun aynı zamanda Verse Kumandası Mini Oyun cihazındaki GameEndedEvent olayına karşı bir race ifadesinde de olması gerekir çünkü oyun biterse karakterin yaptığı şeyi derhal bırakması gerekecektir.
# This function runs when the NPC is spawned in the world and ready to follow a behavior.
OnBegin<override>()<suspends>:void=
# Get the Verse Commander Minigame Device.
# Assumption is that there is only one device in the level.
CreativeObjects := GetCreativeObjectsWithTag(verse_commander_minigame_tag{})
if:
CreativeObject := CreativeObjects[0]
MinigameManager := verse_commander_minigame[CreativeObject]
then:
Sonraki Adım
Bir Verse cihazından komut verileri alan ve bunu oyun alanında hareket etmek için kullanan özel bir NPC tanımladık. Özel karakteri oluşturmak için gereken kodun tam listesini en sondaki 7. Nihai Sonuç adımında bulabilirsin.
Bir sonraki adımda, karakterin hareket edebilmesi ve bulmacayı çözebilmesi için bir oyun alanını nasıl oluşturacağını öğreneceksin.