Le pouvoir d'invisibilité de l'infiltré pose un problème intéressant lorsqu'il s'agit de s'emparer de l'objectif des défenseurs. Comment les défenseurs peuvent-ils repérer un joueur invisible qui retourne à sa base l'objectif en main ? Pour résoudre ce problème, vous pouvez recourir à une aide visuelle et montrer aux défenseurs où se trouve l'infiltré.
Procédez comme suit pour savoir comment créer un objet qui flotte au-dessus de la tête d'un joueur qui s'est emparé d'un objectif.
Créer le gestionnaire d'objets de capture
- Créez un nouvel appareil Verse nommé item_capture_manager à l'aide de l'explorateur Verse, puis faites-le glisser dans le niveau.
- En haut du fichier
item_capture_manager:- Ajoutez
using { /UnrealEngine.com/Temporary/SpatialMath}pour accéder à la structurevector3. Vous l'utiliserez pour savoir où téléporter les indicateurs qui flottent au-dessus de la tête d'un joueur. Ajoutez égalementusing { /Fortnite.com/Characters}pour accéder aufort_characterd'un joueur.using { /Fortnite.com/Devices } using { /Verse.org/Simulation } } using { /Fortnite.com/Characters } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath }
- Ajoutez
- Dans la définition de classe
item_capture_manager, ajoutez les champs suivants :- Une matrice modifiable de générateur d'objets de capture nommée
CaptureItemSpawners. Cette matrice contient le générateur d'objets de capture des infiltrés.item_capture_manager := class(creative_device): Logger:log = log{Channel := triad_item_capture_log_channel} # Générateur d'objets de capture qui fait apparaître l'objet à capturer. @editable CaptureItemSpawner:capture_item_spawner_device = capture_item_spawner_device{} - Un accessoire créatif modifiable nommé
CaptureItemIndicator. C'est cet accessoire qui flotte au-dessus de la tête des infiltrés lorsqu'ils s'emparent de l'objectif.# Générateur d'objets de capture qui fait apparaître l'objet à capturer. @editable CaptureItemSpawner:capture_item_spawner_device = capture_item_spawner_device{} # Accessoire qui flotte au-dessus de la tête d'un joueur lorsqu'il tient l'objet issu # du CaptureItemSpawner. @editable CaptureItemIndicator:creative_prop = creative_prop{} - Un indicateur de carte modifiable nommé
MapIndicator. Il se trouve dans le CaptureItemSpawner du niveau et affiche sur la carte où se trouvent les objectifs de chaque équipe.# Accessoire qui flotte au-dessus de la tête d'un joueur lorsqu'il tient l'objet issu # du CaptureItemSpawner. @editable CaptureItemIndicator:creative_prop = creative_prop{} # Indicateur qui affiche sur la carte où se trouvent les objectifs de chaque équipe @editable MapIndicator:map_indicator_device = map_indicator_device{} - Deux floats modifiables,
UpdateRateSecondsetVerticalOffset. Le premier contrôle la vitesse à laquelle la position deCaptureItemIndicatorchange, le deuxième la distance à laquelleCaptureItemIndicatorflotte au-dessus de la tête du joueur.# Indicateur qui affiche sur la carte où se trouvent les objectifs de chaque équipe @editable MapIndicator:map_indicator_device = map_indicator_device{} # Fréquence à laquelle l'indicateur CaptureItemIndicator met à jour sa position. @editable UpdateRateSeconds:float = 0.15 # Hauteur à laquelle l'indicateur CaptureItemIndicator flotte au-dessus de la tête du joueur. @editable VerticalOffset:float = 180.0 - Un appareil de message d'ATH modifiable nommé
ItemGrabbedMessageDevice. Il envoie un message à chaque joueur lorsqu'un objectif est récupéré.# Hauteur à laquelle l'indicateur CaptureItemIndicator flotte au-dessus de la tête du joueur. @editable VerticalOffset:float = 180.0 # Affiche un message lorsqu'un joueur s'empare de l'objet à capturer. @editable ItemGrabbedMessageDevice:hud_message_device = hud_message_device{} - Un gestionnaire de score modifiable nommé
ScoreManagerDevice. Cet appareil attribue des points à une équipe chaque fois qu'un joueur capture l'objet.# Affiche un message lorsqu'un joueur s'empare de l'objet à capturer. @editable ItemGrabbedMessageDevice:hud_message_device = hud_message_device{} # Attribue des points lorsqu'un joueur capture l'objet à capturer. @editable ScoreManagerDevice:score_manager_device = score_manager_device{} - Un float modifiable nommé
ReturnTime. Si l'élément de capture a un délai de retour avant de retourner au CaptureItemSpawner, vous devez suivre la durée de ce délai de retour pour savoir quand renvoyer les indicateurs au CaptureItemSpawner.
- Une matrice modifiable de générateur d'objets de capture nommée
- Ajoutez une nouvelle méthode
FollowCharacter()à la définition de classeitem_capture_manager. Cette méthode nécessite unfort_characteret le suit en utilisant l'indicateur au-dessus de sa tête. Ajoutez le spécificateur<suspends>à cette fonction, car vous souhaitez en faire apparaître un pour chaque joueur qui s'est emparé d'un objectif.# L'indicateur CaptureItemIndicator suit continuellement le joueur, au-dessus de sa tête. # Les courses entre la boucle de mise à jour pour le CaptureItemIndictator, et si le joueur # capture l'objet, le laisse tomber ou est éliminé. FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Spawned FollowCharacter function")
Faire une course tout en tenant l'objectif
Il est important de réfléchir à ce qui se passe lorsqu'un joueur saisit l'objectif. Le joueur peut :
- Se déplacer, auquel cas vous devez mettre à jour en continu votre CaptureItem et vos indicateurs de carte en fonction de la position du joueur. Cela peut s'effectuer dans une boucle. Capturez l'objectif en veillant à ce que les indicateurs retournent au CaptureItemSpawner et restent hors de vue, car ils ne doivent être visibles que lorsqu'un joueur tient l'objet de capture.
- Laisser tomber l'objet ou être éliminé, auquel cas les indicateurs doivent rester à l'endroit où l'objet a été déposé et revenir au CaptureItemSpawner lorsque l'objet à capturer revient.
Pour cela, vous allez configurer une expression race. En utilisant une race entre les trois conditions ci-dessus, vous pouvez continuer à mettre à jour la position des indicateurs tout en attendant que le joueur laisse tomber ou capture l'objectif.
- Ajoutez une expression
raceàFollowCharacter(). Configurez la course opposant uneloop, unAwait()de l'ItemCapturedEventdeCaptureItemSpawner, unAwait()de l'ItemCapturedDroppedEventdeCaptureItemSpawneret unAwait()de l'EliminatedEvent()deFortCharacter.FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Spawned FollowCharacter function") race: loop: CaptureItemSpawner.ItemCapturedEvent.Await() CaptureItemSpawner.ItemDroppedEvent.Await() FortCharacter.EliminatedEvent().Await() - Dans la
loop, obtenez la position deFortCharacteret enregistrez-la dans une variableTransform.loop: Transform := FortCharacter.GetTransform() - Maintenant, faites apparaître un
MoveTo()pour déplacerCaptureItemIndicatoretMapIndicatorselon la translation et la rotation deTransformplus leVerticalOffsetque vous avez défini plus tôt, sur une durée deUpdateRateSeconds. Vous voulez faire apparaître (Spawn{}) les deux fonctionsMoveTo()parce que leCaptureItemIndicatoret leMapIndicatoront besoin de se déplacer exactement au même moment, plutôt que d'attendre que l'expression de l'autre se termine. La translation étant unvector3composé des coordonnéesX,YetZ, vous devrez placer leVerticalOffsetdans un nouveauvector3.VerticalOffsetétant la distance verticale au-dessus de la tête d'un joueur, définissez-le comme valeurZduvector3.loop: Transform := FortCharacter.GetTransform() spawn{CaptureItemIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} - Enfin, il faut entrer en veille pendant
0.0seconde. Cela permet de s'assurer que la boucle ne s'exécute qu'une seule fois par mise à jour de simulation et qu'elle ne devient pas folle en générant des fonctionsMoveTo(). Votre codeFollowCharacter()devrait maintenant ressembler à ceci :# L'indicateur CaptureItemIndicator suit continuellement le joueur, au-dessus de sa tête. # Les courses entre la boucle de mise à jour pour le CaptureItemIndictator, et si le joueur # capture l'objet, le laisse tomber ou est éliminé. FollowCharacter(FortCharacter:fort_character)<suspends>:void= Logger.Print("Spawned FollowCharacter function") race: loop: Transform := FortCharacter.GetTransform() spawn{CaptureItemIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(Transform.Translation + vector3{Z := VerticalOffset}, Transform.Rotation, UpdateRateSeconds)} # Nous voulons nous assurer que cette boucle ne s'exécute qu'une seule fois par mise à jour de simulation et entrons donc en veille pendant un tick de jeu. Sleep(0.0) CaptureItemSpawner.ItemCapturedEvent.Await() CaptureItemSpawner.ItemDroppedEvent.Await() FortCharacter.EliminatedEvent().Await() Logger.Print("Objective dropped or captured")Réinitialisation des indicateurs
- Lorsque l'objet à capturer est capturé ou retourné, vous devez renvoyer les indicateurs au
CaptureItemSpawnerdans un endroit hors de vue. Dans ce cas, vous les téléporterez au-dessus duCaptureItemSpawner. Pour ce faire, ajoutez une fonction nomméeReturnIndicators()à la définition de la classeitem_capture_manager.# Renvoie les indicateurs de carte et d'objets capturés à leurs positions initiales au-dessus des générateurs. ReturnIndicators(InAgent:agent):void= - Récupérez la transformation du
CaptureItemSpawneret enregistrez-la dans une variableSpawnerTransform. Ensuite, générez unMoveTo()pour leCaptureItemIndicatoret leMapIndicatorà la transformation et la rotation duCaptureItemSpawner, en ajoutant leVerticalOffsetde la même manière que vous l'avez fait dans laloop, pour les placer au-dessus duCaptureItemSpawnwer. Si vous voulez que votre accessoire reste hors de vue, vous pouvez multiplier leVerticalOffsetpar un grand nombre, en l'occurrence 10. Votre méthodeReturnIndicators()achevée devrait ressembler à ceci :# Renvoie les indicateurs de carte et d'objets capturés à leurs positions initiales au-dessus des générateurs. ReturnIndicators():void= SpawnerTransform := CaptureItemSpawner.GetTransform() # Renvoyer au point d'apparition par téléportation, en cachant le CaptureItemIndicator et le MapIndicator au-dessus de la carte. spawn{CaptureItemIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10,0}, SpawnerTransform.Rotation, UpdateRateSeconds)} spawn{MapIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10,0}, SpawnerTransform.Rotation, UpdateRateSeconds)} Logger.Print("Returned Indicators to capture spawner")
Gestion des joueurs qui saisissent, déposent et capturent l'objectif.
- Ajoutez une nouvelle méthode,
OnItemPickedUp(), à la définition de la classeitem_capture_manager. Cette méthode nécessite unagentet génère une instance deFollowCharacter()pour ce personnage.# Signaler à chaque joueur quand un joueur s'est emparé de l'objectif OnItemPickedUp(InAgent:agent):void= Logger.Print("Objective Grabbed") - Obtenez le
FortCharacterd'InAgentet générez une fonctionFollowCharacter()utilisant ceFortCharacter. Votre méthodeOnItemPickedUp()achevée devrait ressembler à ceci :# Signaler à chaque joueur quand un joueur s'est emparé de l'objectif OnItemPickedUp(InAgent:agent):void= Logger.Print("Objective Grabbed") if(FortCharacter := InAgent.GetFortCharacter[]): ItemGrabbedMessageDevice.Show() spawn{FollowCharacter(FortCharacter)} - Ajoutez une nouvelle méthode,
OnItemCaptured(), à la définition de la classeitem_capture_manager. Cette méthode nécessite l'agentqui a capturé l'objectif.# Une fois l'objet capturé, attribuer un score à l'équipe qui l'a capturé et renvoyer les indicateurs. OnItemCaptured(CapturingAgent:agent):void= Logger.Print("Objective Captured") - Dans
OnItemCaptured(), activez leScoreManagerDevicepour attribuer le score à l'équipe du joueur qui a capturé l'objet et appelezReturnIndicators()pour renvoyer les indicateurs.# Une fois l'objet capturé, attribuer un score à l'équipe qui l'a capturé et renvoyer les indicateurs. OnItemCaptured(CapturingAgent:agent):void= Logger.Print("Objective Captured") ScoreManagerDevice.Activate() ReturnIndicators() - Ajoutez une nouvelle méthode,
OnItemDropped(), à la définition de la classeitem_capture_manager. Cette méthode nécessite l'agentqui a déposé l'objet.# Lorsqu'un joueur dépose un objet, générer une fonction WaitForReturn() # si le ReturnTime est supérieur à 0. OnItemDropped(InAgent:agent):void= Logger.Print("Objective Dropped") - Une fois l'objectif déposé, les indicateurs doivent rester près de l'objectif jusqu'à ce qu'il soit ramassé ou renvoyé au
CaptureItemSpawner. Pour savoir quand renvoyer les indicateurs, vous utiliserez la variableReturnTimeque vous avez définie plus tôt. SiReturnTimeest supérieur ou égal à0.0, vous attendez ce laps de temps avant de renvoyer les indicateurs. SiReturnTimeest négatif, l'objectif n'a pas de temps de retour et vous n'avez donc pas besoin de déplacer les indicateurs. Pour faire revenir les indicateurs, créez une nouvelle fonction d'aide nomméeWaitForReturn(), que vous définirez dans l'étape suivante.# Lorsqu'un joueur dépose un objet, générer une fonction WaitForReturn() # si le ReturnTime est supérieur à 0. OnItemDropped(InAgent:agent):void= Logger.Print("Objective Dropped") if(ReturnTime >= 0.0): spawn{WaitForReturn()} else: Logger.Print("The dropped objective does not return") - Ajoutez une nouvelle méthode,
WaitForReturn(), à la définition de la classeitem_capture_manager. Cette fonction attend pendantReturnTime, puis indique si l'objectif n'a pas été ramassé avant la fin de du délai d'attente. Ajoutez le modificateur<suspends>à cette méthode pour lui permettre deSleep()(se mettre en veille).# Attendre toute la durée de ReturnTime, puis renvoyer les indicateurs. WaitForReturn()<suspends>:void= Logger.Print("En attente du renvoi des indicateurs…") - La nécessité de renvoyer ou non les indicateurs dépend de la récupération ou non de l'objectif avant la fin de
ReturnTime. Si c'est le cas, il ne faut pas renvoyer les indicateurs, car ils se replaceraient immédiatement sur le joueur, ce qui pourrait provoquer des comportements visuels inattendus. Pour éviter ce problème, vous utiliserez une variable de logique dont la valeur est égale au résultat d'une course.# Attendre toute la durée de ReturnTime, puis renvoyer les indicateurs. WaitForReturn()<suspends>:void= Logger.Print("En attente du renvoi des indicateurs…") # Renvoyer les indicateurs CaptureItem et de carte si l'objet à capturer # n'est pas ramassé avant la fin du temps imparti. ShouldReturn:logic := race: - Votre fonction
WaitForReturn()doit faire la course entre deux conditions. LeReturnTimes'écoule et l'objectif revient auCaptureItemSpawner, auquel cas vous devez renvoyer les indicateurs etShouldReturndoit êtretrue. À moins que l'objectif soit ramassé avant l'expiration deReturnTime, auquel casShouldReturndoit êtrefalse. Chacune de ces conditions renvoyant une valeur, vous exécuterez la course en utilisant deux [blocks] (block-in-verse) distincts.ShouldReturn:logic := race: block: block: - Dans le premier bloc, appelez
Sleep()pendant toute la durée deReturnTime, puis renvoyeztrue. Dans le second bloc,Await()(attendez) l'événementCaptureItemSpawner.ItemPickedUpventet renvoyez false. La variableShouldReturnsera maintenant initialisée à celle qui se termine en premier.ShouldReturn:logic := race: block: Sleep(ReturnTime) true block: CaptureItemSpawner.ItemPickedUpEvent.Await() false - Si
ShouldReturnest true, vous devez renvoyer les indicateurs. AppelezReturnIndicators()siShouldReturnest évalué àtrue. Votre codeWaitForReturn()achevé devrait maintenant ressembler à ceci :# Attendre toute la durée de ReturnTime, puis renvoyer les indicateurs. WaitForReturn()<suspends>:void= Logger.Print("En attente du renvoi des indicateurs…") # Renvoyer les indicateurs CaptureItem et de carte si l'objet à capturer # n'est pas ramassé avant la fin du temps imparti. ShouldReturn:logic := race: block: Sleep(ReturnTime) true block: CaptureItemSpawner.ItemPickedUpEvent.Await() false if(ShouldReturn?): ReturnIndicators() - Maintenant, dans
OnBegin(), abonnez l'ItemPickedUpEventduCaptureItemSpawneràOnItemPickedUp(), l'ItemCapturedEventàOnItemCaptured()et l'ItemDroppedEventàOnItemDropped().OnBegin<override>()<suspends>:void= CaptureItemSpawner.ItemPickedUpEvent.Subscribe(OnItemPickedUp) CaptureItemSpawner.ItemCapturedEvent.Subscribe(OnItemCaptured) CaptureItemSpawner.ItemDroppedEvent.Subscribe(OnItemDropped) SpawnerTransform := CaptureItemSpawner.GetTransform() - Enfin, dans
OnBegin(), placez les indicateurs dans leurs positions de départ lorsque le script s'exécute en appelantMoveTo()surCaptureItemIndicatoretMapIndicator. Votre codeOnBegin()devrait maintenant être similaire à celui-ci :OnBegin<override>()<suspends>:void= CaptureItemSpawner.ItemPickedUpEvent.Subscribe(OnItemPickedUp) CaptureItemSpawner.ItemCapturedEvent.Subscribe(OnItemCaptured) CaptureItemSpawner.ItemDroppedEvent.Subscribe(OnItemDropped) SpawnerTransform := CaptureItemSpawner.GetTransform() # Renvoyer au point d'apparition par téléportation, en cachant le CaptureItemIndicator sous la carte. CaptureItemIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10,0}, SpawnerTransform.Rotation, UpdateRateSeconds) MapIndicator.MoveTo(SpawnerTransform.Translation + vector3{Z := VerticalOffset * 10,0}, SpawnerTransform.Rotation, UpdateRateSeconds) -
De retour dans l'éditeur, enregistrez le script, générez-le et faites glisser l'appareil dans le niveau. Choisissez un accessoire approprié que vous souhaitez utiliser comme
CaptureItemIndicatordans votre niveau. Il peut s'agir de n'importe quel accessoire, à condition qu'il soit suffisamment visible. Dans cet exemple, vous utiliserez un diamant. Dans le panneau Détails, assignez CaptureItemSpawner à l'InfiltratorCaptureSpawner, et CaptureItemIndicator à l'accessoire que vous avez choisi. Assignez également MapIndicator à l'indicateur de carte de l'infiltré, ItemGrabbedMessageDevice à l'appareil de message d'ATH de l'infiltré et ScoreManagerDevice au gestionnaire de score de l'infiltré. Définissez ReturnTime sur un nombre négatif, car l'objet à capturer de l'infiltré ne revient pas.Vous devez également configurer une instance d'
item_capture_managerpour les attaquants. N'oubliez pas de remplacer le CaptureItemIndicator par un accessoire différent de ceux de l'infiltré afin d'éviter toute confusion visuelle pour les équipes et assurez-vous d'assigner tous les autres appareils. Attribuez un nombre positif à ReturnTime, car l'objet à capturer des attaquants revient au terme d'un temps défini. - Cliquez sur Lancer la session dans la barre d'outils de l'UEFN pour tester le niveau. Lorsque vous testez votre niveau, un joueur doit avoir un accessoire au-dessus de sa tête lorsqu'il s'empare d'un objectif. L'accessoire doit se déplacer avec le joueur et retourner au générateur d'objets de capture lorsque le joueur laisse tomber l'objectif ou le capture.

Étape suivante
À l'étape suivante de ce tutoriel, vous apprendrez à indiquer rapidement aux joueurs ce qu'ils doivent faire et sur quoi ils doivent se concentrer, pour améliorer leur expérience de jeu.