Il personaggio in questo esempio utilizza una definizione di tipo personaggio personalizzato, poiché deve solo muoversi e non ha bisogno di accedere all'API di guardia o fauna selvatica. Il comportamento del personaggio è guidato da un comportamento del verso personalizzato denominata verse_commander_character.
Le guardie sono personaggi non giocabili (PNG) che possono muoversi lungo il percorso designato e diventare ostili per attaccare i giocatori nemici. Gli animali selvatici sono animali, come polli e cinghiali, che possono anche muoversi lungo il percorso designato e attaccare i giocatori nemici.
Per iniziare a creare il PNG personalizzato, crea un nuovo comportamento PNG denominato vese_commander_character utilizzando Verse Explorer. Per informazioni sulla creazione di comportamenti PNG personalizzati, vedi Creare un comportamento PNG personalizzato.
Il personaggio deve conoscere e gestire le seguenti proprietà:
CommandWaitTime: tempo di attesa tra un comando e l'altro.
FocusTime: per quanto tempo forzare la messa a fuoco su un target. Girare il personaggio a sinistra o a destra viene gestito utilizzando
focus_interfacedel personaggio per costringerlo a guardare un determinato punto alla sua sinistra o alla sua destra. Dal momento che la messa a fuoco su una destinazione non si completa a meno che non venga interrotta, questo è impostato su un numero molto basso, giusto il tempo necessario al personaggio per girarsi per guardare in una direzione.ReachRadius: questo è quanto deve avvicinarsi il personaggio alla sua destinazione di navigazione per considerare di averla "raggiunta".
VerseCommanderMinigame: questo è un riferimento al VerseCommanderMinigame nel livello e permette al personaggio di ascoltare i comandi provenienti da esso.
Riferimenti VFX e freccia: Questi fanno riferimento ai diversi VFX del teletrasporto in entrata e in uscita e all'oggetto scenografico Freccia in avanti che rende più facile vedere l'orientamento del personaggio.
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{}Ora che abbiamo definito le proprietà del personaggio, definiamo i suoi comportamenti e le funzioni che li guidano.
Movimento del personaggio
Il personaggio in questo gioco ha i comportamenti seguenti:
Sposta in avanti: il comando Avanti sposta il personaggio in avanti di 1 tile sul tabellone.
Gira a destra o Gira a sinistra: i comandi Gira a destra e Gira a sinistra fanno ruotare il personaggio di 90 gradi per rivolgersi rispettivamente a destra o a sinistra. Questo deve avvenire anche senza spostare il personaggio dal tile su cui si trova.
Reimposta: quando viene impartito il comando Reimposta il personaggio si teletrasporta di nuovo nella posizione di partenza sul tabellone.
Comandi di attesa: dal momento che il movimento del personaggio non può essere controllato direttamente, deve ascoltare i comandi provenienti dal dispositivo VerseCommanderMinigame nel livello. Dopo aver eseguito tutti i comandi, rimarrà fermo in attesa di ulteriori comandi.
Il PNG in questo modello ha solo poche opzioni di movimento, essendo in grado di avanzare nella direzione in cui è rivolto di un tile, girare a destra o girare a sinistra. Ognuna di queste opzioni viene eseguita tramite la funzione GetNavTarget() che crea una nuova destinazione di navigazione a una distanza TileDistance per il personaggio da utilizzare. Questa destinazione è in avanti, a destra o a sinistra locale del personaggio, a seconda che il comando dato sia Avanti, Destra o Sinistra.
# 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()
Quando il PNG riceve il segnale di esecuzione, scorre l'elenco dei comandi ricevuti e passa ciascuno di essi alla funzione ExecuteCommand(). Innanzitutto, ottiene l'interfaccia focus_interface e navigatable del personaggio, quindi esegue azioni diverse in base al comando. Per ognuno dei comandi Avanti, Destra e Sinistra, chiama GetNavTarget() per trovare la nuova trasformazione da utilizzare per il PNG. Quindi, prosegue in avanti verso la nuova trasformazione utilizzando NavigateTo() dall'interfaccia navigatable o utilizza focus_interface per concentrarsi sulla destinazione a destra o sinistra.
# 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[]
VFX del personaggio
Quando il personaggio si muove sul tabellone, un oggetto scenografico freccia gli mostra la posizione e l'orientamento per facilitare la visualizzazione del personaggio dalla telecamera dall'alto verso il basso. Questa freccia deve seguire il personaggio e aggiornarsi man mano che il personaggio si gira e si muove. La funzione MoveArrow() aggiorna la posizione della freccia in modo che corrisponda a quella dei personaggi, copiandone la posizione e l'orientamento. La funzione CreateArrow() genera l'oggetto scenografico freccia ed esegue una chiamata iniziale a MoveArrow() per vedere dove si trova il personaggio fin dall'inizio.
# 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)?
Quando il personaggio si genera sul tabellone, si sposta su un nuovo tabellone o si reimposta all'inizio del tabellone tramite il comando Reimposta, viene riprodotta un'animazione di teletrasporto sia per il teletrasporto in entrata che per il teletrasporto in uscita. Per creare un effetto di teletrasporto, prima chiamiamo Hide() sul personaggio e sulla freccia, quindi riproduciamo TeleportOutVFX spostando il generatore VFX dove si trova il personaggio e abilitandolo. Una volta terminato il teletrasporto di VFX, dobbiamo teletrasportare il personaggio nella sua nuova posizione e riprodurre il TeleportInVFX in quella posizione. Al termine, possiamo quindi chiamare Show() sul personaggio e l'oggetto scenografico freccia per mostrare il personaggio nella nuova posizione.
# 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()
Il teletrasporto del personaggio viene eseguito con una funzione di supporto MoveToTile() che prende la trasformazione per spostare il personaggio e lo teletrasporta lì. Al valore Z della trasformazione viene aggiunto un piccolo offset per evitare che il carattere si agganci al pavimento.
# 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
Elaborazione comandi in corso
Quando il personaggio è inattivo sul tabellone, deve sedersi e ascoltare il segnale di esecuzione per sapere cosa fare dopo. Questo accade nella funzione AwaitCommands(). Questa funzione ha lo specificatore suspends in modo che possa essere eseguito in modo asincrono poiché il personaggio deve Await() ExecuteCommandsEvent. Poiché i comandi vengono inseriti come una tupla che contiene un array di comandi e TileSize utilizzato per tali comandi, ognuno di essi deve essere elaborato in un loop for chiamando ExecuteCommand(). Durante l'esecuzione di ogni comando, nascondiamo la freccia avanti e la mostriamo di nuovo solo al termine dell'esecuzione del comando. Una volta terminata l'esecuzione di tutti i comandi, segnaliamo al minigioco Verse Commander che abbiamo finito con i comandi e siamo pronti per altri.
# 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.
Invece di elaborare nuovi comandi, il personaggio può anche essere reimpostato all'inizio del tabellone di gioco corrente con il pulsante Reimposta. Poiché la reimpostazione è immediata e non utilizza la coda dei comandi, il personaggio deve ascoltarlo separatamente dal segnale di esecuzione. Questo accade nella funzione AwaitReset() che attende che BoardResetEvent invii segnali dal minigioco Verse Commander. Quando lo fa, chiama PlayVFXAndMoveCharacter() per riportare il personaggio nella posizione iniziale del tabellone.
# 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)}Esecuzione del loop di gioco del personaggio
Ora che le diverse funzioni che elaborano i comandi sono impostate, è il momento di creare il loop di gioco principale del personaggio. Il personaggio deve rimanere continuamente in ascolto del segnale di esecuzione per elaborare un elenco di comandi o del segnale di reimpostazione per tornare all'inizio del tabellone. Poiché l'attesa del segnale di esecuzione e del segnale di reimpostazione deve avvenire in modo asincrono e può verificarsi più volte per tabellone, è necessaria una funzione di supporto separata che gestisca il loop per entrambi. Questo è gestito dalla funzione CharacterCommandLoop() che esegue il loop di gioco principale per il personaggio. In un'espressione race, corre tra la funzione AwaitReset() e un loop che chiama continuamente AwaitCommands() per assicurarsi che il personaggio sia sempre in ascolto dei comandi.
# Race between resetting the character to start of the board and awaiting commands for that character.
CharacterCommandLoop()<suspends>:void=
race:
AwaitReset()
loop:
AwaitCommands()All'inizio del gioco, il personaggio non è presente nel livello fino a quando non si genera dal generatore PNG. Ciò significa che quando si genera, deve trovare il minigioco Verse Commander nel livello poiché non ha un riferimento a esso. A tale scopo, utilizza GetCreativeObjectsWithTag() per trovare l'oggetto con il tag gameplay verse_commander_minigame_tag e impostandolo come VerseCommanderMinigame. Quando crei la tua esperienza di minigioco, assicurati di impostare correttamente i tag in modo che i personaggi del livello possano trovare gli oggetti con cui hanno bisogno di comunicare.
Dopo aver trovato il minigioco Verse Commander, il personaggio deve generare la freccia in avanti che lo segue utilizzando CreateArrow(). Per eseguire il loop di gioco, è necessario eseguire continuamente il loop della funzione CharacterCommandLoop() per riavviarlo se si verifica un segnale di reimpostazione. Questo deve accadere anche in un'espressione race a fronte di GameEndedEvent del minigioco Verse Commander, poiché se il gioco termina il personaggio deve interrompere immediatamente ciò che sta facendo.
# 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:
Step successivo
Abbiamo definito un PNG personalizzato che prende i dati dei comandi da un dispositivo Verse e li utilizza per muoversi su un tabellone. Puoi trovare l'elenco completo del codice per creare il personaggio personalizzato nello step finale 7. Risultato finale.
Nello step successivo, imparerai come creare un tabellone su cui il personaggio possa muoversi e risolvere il suo puzzle.