Déterminer si un joueur est inactif
Dans cette section, vous apprendrez à déterminer si un joueur s'est déplacé d'une certaine distance depuis la dernière mise à jour de la simulation. Si c'est le cas, la position actuelle du joueur est enregistrée et vérifiée à nouveau. Si ce n'est pas le cas, la boucle est interrompue et la méthode prend fin. Cette méthode utilise GetFortCharacter[], GetTransform(), et Translation pour obtenir l'emplacement du joueur. Consultez les pages de référence d'API pour en savoir plus.
Ce tutoriel comprend des extraits de code Verse qui vous expliquent comment exécuter les mécaniques de jeu nécessaires dans ce jeu. Suivez les étapes ci-dessous et copiez le script complet à l'étape 6 de ce tutoriel.
Procédez comme suit pour déterminer si un joueur est inactif.
-
Créez une méthode d'extension pour la classe d'agent nommée
AwaitStopMoving(). Cela signifie que vous ajoutez une méthode personnalisée à une classe déjà définie.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent has moved less than the minimum distance.") -
Obtenez la position initiale du joueur.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent has moved less than the minimum distance.") # Obtenir la position initiale de l'agent à partir du personnage de l'agent dans la scène. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation -
Obtenez la position suivante du joueur lors de la prochaine mise à jour de la simulation.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent has moved less than the minimum distance.") # Obtenir la position initiale de l'agent à partir du personnage de l'agent dans la scène. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Obtenir la position de l'agent au prochain tick de jeu. NewPosition := Tracked.GetTransform().Translation - Vérifiez si la distance entre la position initiale et la dernière position est inférieure au seuil défini, transmis à la fonction en tant que paramètre
MinimumDistance.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent has moved less than the minimum distance.") # Obtenir la position initiale de l'agent à partir du personnage de l'agent dans la scène. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Obtenir la position de l'agent au prochain tick de jeu. NewPosition := Tracked.GetTransform().Translation # Si la distance entre la nouvelle position et la position de départ est inférieure au paramètre MinimumDistance, l'agent n'a pas bougé et la boucle est interrompue. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Agent has moved less than the minimum distance.") # Sinon, réinitialiser StartPosition pour s'assurer que le joueur part de la nouvelle position. else: set StartPosition = NewPosition -
Il faut maintenant exécuter une vérification en boucle entre la position initiale et la dernière position, et interrompre la boucle lorsque la distance entre les positions est supérieure au seuil
MinimumDistance.# Mettre en boucle jusqu'à ce que l'agent se déplace à une distance inférieure à la distance minimale. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent has moved less than the minimum distance.") # Obtenir la position initiale de l'agent à partir du personnage de l'agent dans la scène. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Obtenir la position de l'agent au prochain tick de jeu. NewPosition := Tracked.GetTransform().Translation # Si la distance entre la nouvelle position et la position de départ est inférieure au paramètre MinimumDistance, l'agent n'a pas bougé et la boucle est interrompue. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Agent has moved less than the minimum distance.") break # Sinon, réinitialiser StartPosition pour s'assurer que le joueur part de la nouvelle position. else: set StartPosition = NewPosition
Compte à rebours avant le déclenchement du battement de cœur
Procédez comme suit pour observer un délai égal à HeartBeat.MoveTime - HeartBeat.WarningTime avant d'afficher un avertissement et un compte à rebours jusqu'à la fin du compte à rebours, puis pour effacer le texte d'avertissement et du compte à rebours.
- Créez une fonction nommée CountdownTimer().
# Retarder jusqu'au déclenchement de HeartBeatWarningTime. Puis compte à rebours selon HeartBeatWarningTime et définition du texte de compte à rebours. Effacer le texte en cas de report. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Starting heartbeat countdown.") -
Vous devez d'abord essayer d'obtenir la
heartbeat_warning_uipour le joueur associé à partir du mappage configuré dans heartbeat.verse. En cas de réussite, vous devez lancer le délai entre l'arrêt du joueur et l'affichage du compte à rebours.# Retarder jusqu'au déclenchement de HeartBeatWarningTime. Puis compte à rebours selon HeartBeatWarningTime et définition du texte de compte à rebours. Effacer le texte en cas de report. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Starting heart beat countdown.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Veille pendant la durée précédant l'affichage de l'avertissement. Logger.Print("Starting heartbeat warning.") else: Logger.Print("UIData not found.") -
Créez maintenant la variable qui apparaîtra à l'écran et qui sera réduite d'une unité par seconde. Nommez-la
WarningTimeRemaining. Définissez-la surWarningTimeà partir de heartbeat.verse. Dans la mesure oùWarningTimeRemainingest unintet oùWarningTimeest unfloat, vous devez utiliser la fonctionCeil[]pour créer unint.# Retarder jusqu'au déclenchement de HeartBeatWarningTime. Puis compte à rebours selon HeartBeatWarningTime et définition du texte de compte à rebours. Effacer le texte en cas de report. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Starting heart beat countdown.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Veille pendant la durée précédant l'affichage de l'avertissement. Logger.Print("Starting heartbeat warning.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("UIData not found.") -
Avant de lancer la boucle du compte à rebours, utilisez l'expression
deferpour effacer le compte à rebours de l'interface utilisateur du joueur au terme de la fonctionCountdownTimer(). Elle ne s'achève qu'à l'expiration du chronomètre ou lorsque le joueur recommence à se déplacer. Consultez la rubrique de l'expression defer pour en savoir plus.# Retarder jusqu'au déclenchement de HeartBeatWarningTime. Puis compte à rebours selon HeartBeatWarningTime et définition du texte de compte à rebours. Effacer le texte en cas de report. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Starting heart beat countdown.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Veille pendant la durée précédant l'affichage de l'avertissement. Logger.Print("Starting heart beat warning.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un report (defer) a lieu à la fin ou à l'annulation de la fonction, par exemple si elle perd une course (race). # Le texte d'avertissement est alors effacé à la fin du compte à rebours ou si l'agent d'accessoire se déplace avant la fin du compte à rebours. defer: UIData.Text.SetText(HeartBeatWarningClear) # Définir le texte d'avertissement sur le temps restant, attendre une seconde, puis réduire le temps restant. Si le compte à rebours se termine, interrompre la boucle. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("UIData not found.") -
Enfin, créez la boucle qui diminue le compte à rebours. Utilisez la fonction
SetText()pour afficherHeartBeatWarningMessageavec leWarningTimeRemaining. Attendez ensuite une seconde avecSleep()avant de réduire le temps restant. SiWarningTimeRemainingest égal ou inférieur à 0, le compte à rebours se termine et vous pouvez interrompre la boucle.# Retarder jusqu'au déclenchement de HeartBeatWarningTime. Puis compte à rebours selon HeartBeatWarningTime et définition du texte de compte à rebours. Effacer le texte en cas de report. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Starting heart beat countdown.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Veille pendant la durée précédant l'affichage de l'avertissement. Logger.Print("Starting heart beat warning.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un report (defer) a lieu à la fin ou à l'annulation de la fonction, par exemple si elle perd une course (race). # Le texte d'avertissement est alors effacé à la fin du compte à rebours ou si l'agent d'accessoire se déplace avant la fin du compte à rebours. defer: UIData.Text.SetText(HeartBeatWarningClear) # Définir le texte d'avertissement sur le temps restant, attendre une seconde, puis réduire le temps restant. Si le compte à rebours se termine, interrompre la boucle. loop: Logger.Print("Heart beat in {WarningTimeRemaining} seconds.") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("UIData not found.")
Utiliser des effets sur les joueurs inactifs
Au terme d'AwaitStopMoving(), vous savez qu'il est temps de lancer le compte à rebours du joueur, puis ses effets de battement de cœur. Cependant, dès que le joueur recommence à se déplacer, vous devez annuler le compte à rebours ou le battement de cœur, selon le cas. Pour ce faire, vous avez besoin d'une expression race, où les deux expressions de course sont les suivantes :
-
PropAgent.AwaitStartMoving(MinimumMoveDistance); -
block, lorsqu'un compte à rebours a lieu avant le déclenchement des effets de battement de cœur.
AwaitStartMoving() est nécessaire pour gagner la course et arrêter le compte à rebours ou les effets de battement de cœur.
L'expression block est utilisée pour s'assurer que les deux fonctions qu'elle contient, CountdownTimer() et StartHeartbeart(), s'exécutent de manière séquentielle et non simultanément. Le compte à rebours est destiné à informer le joueur d'accessoire que les effets de battement de cœur commenceront après la fin du compte à rebours. Il ne serait donc pas logique de lancer le compte à rebours et le battement de cœur en même temps.
Procédez comme suit pour déclencher des effets lorsque le joueur est resté immobile trop longtemps.
- Créez une méthode d'extension nommée
AwaitStartMoving(), dont l'implémentation est identique, à l'exception de ce qui suit :
-
Cette méthode vérifie si le joueur s'est déplacé d'au moins
MinimumDistancedepuis la dernière mise à jour de la simulation et non d'une distance inférieure àMinimumDistance, comme dansAwaitStopMoving(). -
Cette méthode ne réinitialise pas la
StartPositionaprès chaque boucle. SiStartPositionétait réinitialisée à la fin de chaque boucle, le joueur devrait se déplacer au moins sur toute laMinimumDistancedurant le délai nécessaire à la mise à jour de la simulation, ce qui pourrait s'avérer impossible.# Mettre en boucle jusqu'à ce que l'agent se déplace à une distance supérieure à la distance minimale. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Checking if the agent moves further than the minimum distance.") # Obtenir la position initiale de l'agent à partir du personnage de l'agent dans la scène. if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Obtenir la position de l'agent au prochain tick de jeu. NewPosition := Tracked.GetTransform().Translation # Si la distance entre la nouvelle position et la position de départ est supérieure ou égale à MinimumDistance, l'agent a bougé et la boucle est interrompue. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("Agent has moved more than or equal to the minimum distance.") break
-
Créez une fonction nommée
RunPropGameLoop()chargée de déclencher l'effet de battement de cœur lorsque le joueur est inactif trop longtemps.# Si l'agent d'accessoire s'arrête de bouger, utiliser race pour voir si l'agent d'accessoire se déplace au-delà du paramètre MinimumMoveDistance, si le chronomètre de battement de cœur se termine, ou si l'agent d'accessoire est éliminé. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starting prop agent game loop.") -
Attendez que l'agent d'accessoire se déplace à une distance inférieure à la distance minimale, puis avance.
# Si l'agent d'accessoire s'arrête de bouger, utiliser race pour voir si l'agent d'accessoire se déplace au-delà du paramètre MinimumMoveDistance, si le chronomètre de battement de cœur se termine, ou si l'agent d'accessoire est éliminé. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starting prop agent game loop.") # Mettre le comportement de l'accessoire en boucle infinie jusqu'à ce que l'agent d'accessoire soit éliminé ou que le joueur quitte la session. loop: # Attendre que l'agent d'accessoire se déplace à une distance inférieure à la distance minimale, puis avancer. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0) -
Ajoutez l'expression
racepour définir la course entre la fin d'AwaitStartMoving(), ce qui signifie que le joueur a commencé à se déplacer, et une expressionblockdans laquelleCountdownTimer()puisStartHeartbeat()s'exécutent.# Si l'agent d'accessoire s'arrête de bouger, utiliser race pour voir si l'agent d'accessoire se déplace au-delà du paramètre MinimumMoveDistance, si le chronomètre de battement de cœur se termine, ou si l'agent d'accessoire est éliminé. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starting prop agent game loop.") # Mettre le comportement de l'accessoire en boucle infinie jusqu'à ce que l'agent d'accessoire soit éliminé ou que le joueur quitte la session. loop: # Attendre que l'agent d'accessoire se déplace à une distance inférieure à la distance minimale, puis avancer. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Compte à rebours jusqu'au battement de cœur en attendant que l'agent d'accessoire dépasse la distance minimale, puis déclenchement indéfini du battement de cœur. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Une fois la fonction race terminée (déplacement de l'agent d'accessoire), relancer la boucle.