Dans cet exemple, le personnage utilise une définition de personnage personnalisée, car il n'a besoin que de se déplacer ; il n'a pas besoin d'accéder à l'API de garde ou de faune. Le comportement du personnage est piloté par un comportement Verse personnalisé nommé verse_commander_character.
Les gardes sont des personnages non-joueurs (PNJ) qui peuvent se déplacer le long de chemins désignés et peuvent devenir hostiles pour attaquer les joueurs adversaires. La faune regroupe divers animaux, tels que la poule et le sanglier, qui peuvent également se déplacer le long de chemins désignés et attaquer les adversaires.
Pour commencer à créer le PNJ personnalisé, créez un nouveau comportement de PNJ appelé verse_commander_character à l'aide de l'explorateur Verse. Pour en savoir plus sur la création de vos propres comportements de PNJ personnalisés, consultez la rubrique Créer un comportement de PNJ personnalisé.
Le personnage doit posséder les propriétés suivantes et les gérer :
CommandWaitTime : délai d'attente entre chaque commande.
FocusTime : délai nécessaire pour forcer la focalisation sur une cible. Pour faire pivoter le personnage vers la gauche ou vers la droite, utilisez son interface
focus_interfaceafin de le forcer à se placer face à un point particulier situé à sa gauche ou à sa droite. Dans la mesure où la focalisation sur une cible ne prend fin que si elle est interrompue, définissez ce paramètre sur une valeur très faible, c'est-à-dire sur un délai suffisant pour permettre au personnage de se tourner dans une direction.ReachRadius : distance à laquelle le personnage doit se rapprocher de sa cible de navigation pour considérer qu'il l'a « atteinte ».
VerseCommanderMinigame : référence à la propriété VerseCommanderMinigame du niveau, qui permet au personnage d'écouter les commandes qui en proviennent.
Références des effets visuels et des flèches : elles référencent les différents effets visuels de téléportation, ainsi que l'accessoire Flèche avant, qui permet de voir plus facilement l'orientation du personnage.
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{}Maintenant que vous avez défini les propriétés des personnages, définissez leurs comportements et les fonctions qui les pilotent.
Déplacement du personnage
Dans ce jeu, le personnage peut adopter les comportements suivants :
Avancer : la commande Avancer fait avancer le personnage d'un carré sur le plateau de jeu.
Tourner à droite ou Tourner à gauche : les commandes Tourner à droite et Tourner à gauche font pivoter le personnage de 90 degrés pour le placer face à sa droite ou sa gauche, respectivement. Ce comportement doit également se produire sans déplacer le personnage du carré sur lequel il se trouve.
Réinitialiser : lorsque la commande Réinitialiser est exécutée, le personnage est de nouveau téléporté à sa position de départ sur le plateau de jeu.
Commandes d'attente : dans la mesure où il est impossible de contrôler le mouvement du personnage directement, il convient d'écouter les commandes provenant de l'appareil VerseCommanderMinigame dans le niveau. Après avoir exécuté toutes leurs commandes, les personnages restent immobiles et attendent d'autres commandes.
Le PNJ de ce modèle ne dispose que de quelques options de déplacement : il peut avancer d'un carré dans la direction à laquelle il fait face, tourner à droite ou tourner à gauche. Chacune de ces options est rendue possible grâce à la fonction GetNavTarget(), qui crée une nouvelle cible de navigation à une distance de TileDistance pour que le personnage l'utilise. Cette cible se trouve soit vers l'avant, soit vers la droite, soit vers la gauche du personnage, selon que la commande donnée est Avancer, Droite ou Gauche.
# 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()
Lorsque le PNJ reçoit le signal Exécuter, il parcourt la liste des commandes reçues et transmet chacune d'elles à la fonction ExecuteCommand(). Il obtient tout d'abord les interfaces focus_interface et navigatable pour le personnage, puis effectue différentes actions en fonction de la commande. Pour chacune des options Avancer, Droite et Gauche, il appelle GetNavTarget() pour trouver la nouvelle transformation à utiliser. Ensuite, il avance vers la nouvelle transformation en utilisant NavigateTo() de l'interface navigatable ou utilise l'interface focus_interface pour se focaliser sur la cible à sa droite ou à sa gauche.
# 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[]
Effets visuels du personnage
Lorsque le personnage se déplace sur le plateau de jeu, une flèche indique sa position et son orientation afin de faciliter la visualisation du personnage en prise de vue du dessus. Cette flèche doit suivre le personnage et s'actualiser lorsque le personnage pivote et se déplace. La fonction MoveArrow() actualise la position de la flèche pour qu'elle corresponde à celle du personnage, en copiant sa position et son orientation. La fonction CreateArrow() génère l'accessoire de flèche et effectue un premier appel à MoveArrow() pour que vous puissiez voir où se trouve le personnage dès le début.
# 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)?
Lorsque le personnage apparaît sur le plateau, se déplace vers un nouveau plateau ou revient au début du plateau via la commande Réinitialiser, une animation de téléportation est déclenchée à la fois pour la téléportation entrante et pour la téléportation sortante. Pour créer un effet de téléportation, appelez en premier lieu Hide() sur le personnage et la flèche, puis déclenchez le TeleportOutVFX en déplaçant le générateur d'effets visuels où se trouve le personnage et en l'activant. Une fois les effets visuels de téléportation sortante terminés, vous devez téléporter le personnage vers sa nouvelle position et déclencher le TeleportInVFX à cet emplacement. Au terme de ces opérations, vous pouvez appeler Show() sur le personnage et l'accessoire de flèche pour montrer le personnage dans sa nouvelle position.
# 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()
La téléportation du personnage se fait à l'aide d'une fonction auxiliaire MoveToTile(), qui prend la transformation vers laquelle déplacer le personnage et téléporte ce dernier à cet endroit. Un léger décalage est ajouté à la valeur Z de la transformation pour éviter que le personnage ne s'imbrique dans le sol.
# 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
Traiter les commandes
Lorsque le personnage est inactif sur le plateau, il doit s'asseoir et écouter le signal d'exécution pour savoir ce qu'il doit faire ensuite. Ce comportement est rendu possible grâce à la fonction AwaitCommands(). Cette fonction possède le spécificateur suspends pour pouvoir s'exécuter de manière asynchrone, car le personnage doit Await(), c'est-à-dire attendre ExecuteCommandsEvent. Dans la mesure où les commandes sont reçues sous forme de tuple contenant une matrice des commandes et de la taille des carrés utilisée pour ces commandes, vous devez les traiter dans une boucle for en appelant ExecuteCommand(). À mesure que chaque commande est exécutée, la flèche vers l'avant est masquée et ne réapparaît qu'à la fin de l'exécution de la commande. Une fois toutes les commandes exécutées, informez l'appareil VerseCommanderMinigame que les commandes sont terminées et que vous pouvez passer à d'autres commandes.
# 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.
Au lieu de traiter de nouvelles commandes, le personnage peut également être renvoyé au début du plateau de jeu actuel à l'aide du bouton Réinitialiser. La réinitialisation étant immédiate et n'utilisant pas la file d'attente des commandes, le personnage doit l'écouter séparément du signal d'exécution. Utilisez pour cela la fonction AwaitReset(), qui attend que le mini-jeu Commandant Verse signale l'événement BoardResetEvent. PlayVFXAndMoveCharacter() est alors appelé pour replacer le personnage à la position de départ du plateau.
# 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)}Exécuter la boucle de jeu du personnage
Vous venez de configurer les différentes fonctions qui traitent les commandes. Vous devez à présent créer la boucle de jeu principale du personnage. Ce dernier doit écouter en permanence le signal d'exécution pour traiter une liste de commandes, ou le signal de réinitialisation pour revenir au début du plateau. L'attente du signal d'exécution et du signal de réinitialisation devant se faire de manière asynchrone et pouvant se produire plusieurs fois par plateau, vous devez disposer d'une fonction auxiliaire distincte qui gère la mise en boucle de ces deux signaux. Utilisez pour cela la fonction CharacterCommandLoop(), qui exécute la boucle principale du jeu pour le personnage. L'expression race lance une course entre la fonction AwaitReset() et une boucle qui appelle continuellement AwaitCommands(), pour s'assurer que le personnage est toujours à l'écoute des commandes.
# Race between resetting the character to start of the board and awaiting commands for that character.
CharacterCommandLoop()<suspends>:void=
race:
AwaitReset()
loop:
AwaitCommands()Au début du jeu, le personnage n'est pas présent dans le niveau jusqu'à ce qu'il apparaisse via le générateur de PNJ. Cela signifie que lorsqu'il apparaît, il doit rechercher l'appareil VerseCommanderMinigame dans le niveau, car il n'existe aucune référence associée. Il utilise pour cela GetCreativeObjectsWithTag() pour trouver l'objet avec la balise de jeu verse_commander_minigame_tag et le définit sur VerseCommanderMinigame. Lorsque vous créez votre propre expérience de mini-jeu, veillez à définir correctement vos balises afin que les personnages du niveau puissent trouver les objets avec lesquels ils doivent communiquer.
Après avoir trouvé l'appareil Mini-jeu Commandant Verse, le personnage doit générer la flèche vers l'avant qui le suit en utilisant CreateArrow(). Pour exécuter le jeu en boucle, la fonction CharacterCommandLoop() doit être exécutée en boucle afin de redémarrer le jeu si un signal de réinitialisation se produit. Cette même fonction doit également se produire dans une expression race sur l'événement GameEndedEvent du mini-jeu Commandant Verse, car le personnage doit immédiatement arrêter ce qu'il est en train de faire lorsque le jeu prend fin.
# 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:
Étape suivante
Vous avez défini un PNJ personnalisé qui reçoit des données de commande d'un appareil Verse et les utilise pour se déplacer sur un plateau de jeu. Pour obtenir le code complet permettant de créer le personnage personnalisé, consultez l'étape finale 7. Résultat final.
À l'étape suivante, vous apprendrez à créer un plateau sur lequel le personnage peut se déplacer et résoudre son énigme.