Bestimmen, ob ein Spieler inaktiv ist
In diesem Abschnitt lernst du, wie du überprüfen kannst, ob sich ein Spieler seit der letzten Simulationsaktualisierung eine bestimmte Strecke bewegt hat. Ist dies der Fall, wird die aktuelle Position des Spielers gespeichert und erneut überprüft. Ist dies nicht der Fall, bricht die Schleife ab und die Methode wird beendet. Diese Methode verwendet GetFortCharacter[], GetTransform() und Verschiebung, um die Position des Spielers zu holen. Mehr darüber erfährst du auf den jeweiligen API-Referenzseiten.
Diese Seite enthält Verse-Snippets, die zeigen, wie die in diesem Spiel benötigten Gameplay-Mechaniken ausgeführt werden. Befolge die folgenden Schritte und kopiere das vollständige Script in Schritt 6 dieses Tutorials.
Befolge diese Schritte, um festzustellen, ob ein Spieler inaktiv ist.
-
Erstelle eine Erweiterungsmethode für die Agent-Klasse mit dem Namen
AwaitStopMoving(). Das bedeutet, dass du eine benutzerdefinierte Methode zu einer bereits definierten Klasse hinzufügst.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich weniger als die Mindestdistanz bewegt hat") -
Hole die anfängliche Position des Spielers.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich weniger als die Mindestdistanz bewegt hat") # Ruft die Anfangsposition des Agent vom Charakter des Agent in der Szene ab if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation -
Hole die nächste Position des Spielers in der nächsten Simulationsaktualisierung.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich weniger als die Mindestdistanz bewegt hat") # Ruft die Anfangsposition des Agent vom Charakter des Agent in der Szene ab if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Ermittelt die Position des Agent im nächsten Spieltick. NewPosition := Tracked.GetTransform().Translation - Prüfe, ob die Entfernung zwischen der anfänglichen Position und der letzten Position innerhalb eines akzeptablen Schwellenwerts liegt, welcher der Funktion als Parameter
MinimumDistanceübergeben wird.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich weniger als die Mindestdistanz bewegt hat") # Ruft die Anfangsposition des Agent vom Charakter des Agent in der Szene ab if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Ermittelt die Position des Agent im nächsten Spieltick. NewPosition := Tracked.GetTransform().Translation # Wenn der Abstand der neuen Position von der Startposition kleiner als MinimumDistance ist, hat sich der Agent nicht bewegt und wir brechen die Schleife ab. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Der Agent hat sich weniger als den Mindestabstand bewegt.") # Andernfalls setzen wir StartPosition zurück, um sicherzustellen, dass sich der Spieler von der neuen Position aus bewegt. else: set StartPosition = NewPosition -
Nun wollen wir die Prüfung zwischen der Anfangs- und der Endposition in einer Schleife durchführen und die Schleife verlassen, wenn der Abstand zwischen den Positionen über dem Schwellenwert
MinimumDistanceliegt.# Schleife, bis der Agent sich weniger als MinimumDistance bewegt (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich weniger als die Mindestdistanz bewegt hat") # Ruft die Anfangsposition des Agent vom Charakter des Agent in der Szene ab if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Ermittelt die Position des Agent im nächsten Spieltick. NewPosition := Tracked.GetTransform().Translation # Wenn der Abstand der neuen Position von der Startposition kleiner als MinimumDistance ist, hat sich der Agent nicht bewegt und wir brechen die Schleife ab. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("Der Agent hat sich weniger als den Mindestabstand bewegt.") break # Andernfalls setzen wir StartPosition zurück, um sicherzustellen, dass sich der Spieler von der neuen Position aus bewegt. else: set StartPosition = NewPosition
Countdown vor dem Heartbeat
Befolge diese Schritte, um eine Zeitspanne von HeartBeat.MoveTime - HeartBeat.WarningTime abzuwarten, bevor eine Warnung und ein Countdown-Timer angezeigt werden, bis die Countdown-Zeit abgelaufen ist, und lösche dann den Warn- und Countdown-Text.
- Erstelle eine Funktion namens CountdownTimer().
# Verzögert, bis HeartBeatWarningTime beginnen soll. Zählt dann um HeartBeatWarningTime herunter und setzt den Countdown-Text. Löscht den Text, wenn zurückgestellt. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Herzschlag-Countdown beginnt.") -
Du musst zuerst versuchen, die
heartbeat_warning_uifür den zugehörigen Spieler von der Karte zu holen, die du in heartbeat.verse eingerichtet hast. Wenn das gelingt, musst du die Verzögerung zwischen dem Anhalten des Spielers und der Anzeige des Countdown-Timers starten.# Verzögert, bis HeartBeatWarningTime beginnen soll. Zählt dann um HeartBeatWarningTime herunter und setzt den Countdown-Text. Löscht den Text, wenn zurückgestellt. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Herzschlag-Countdown beginnt.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Schläft so lange, bis die Warnung erscheint. Logger.Print("Starte Herzschlag-Warnung.") else: Logger.Print("UIData nicht gefunden.") -
Erstelle nun die Variable, die auf dem Bildschirm erscheinen und jede Sekunde um eins verringert werden soll. Benenne sie
WarningTimeRemaining. Lege sie aufWarningTimeaus Heartbeat.Verse fest. DaWarningTimeRemainingeinintundWarningTimeeinfloatist, musst duCeil[]verwenden, um einenintzu erzeugen.# Verzögert, bis HeartBeatWarningTime beginnen soll. Zählt dann um HeartBeatWarningTime herunter und setzt den Countdown-Text. Löscht den Text, wenn zurückgestellt. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Herzschlag-Countdown beginnt.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Schläft so lange, bis die Warnung erscheint. Logger.Print("Starte Herzschlag-Warnung.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("UIData nicht gefunden.") -
Vor dem Start der Countdown-Schleife muss der Ausdruck
deferverwendet werden, um den Countdown-Timer aus der Benutzeroberfläche des Spielers zu löschen, sobald die FunktionCountdownTimer()abgeschlossen ist. Sie wird erst abgeschlossen, wenn der Timer abläuft oder wenn der Spieler sich wieder in Bewegung setzt. Weitere Informationen findest du unter Defer um mehr zu erfahren.# Verzögert, bis HeartBeatWarningTime beginnen soll. Zählt dann um HeartBeatWarningTime herunter und setzt den Countdown-Text. Löscht den Text, wenn zurückgestellt. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Herzschlag-Countdown beginnt.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Schläft so lange, bis die Warnung erscheint. Logger.Print("Herzschlag-Warnung beginnt.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Eine Zurückstellung erfolgt, wenn die Funktion abgeschlossen ist oder wenn sie abgebrochen wird, z. B. wenn sie ein Rennen verliert. # In diesem Fall wird der Warntext gelöscht, wenn der Countdown abgelaufen ist oder wenn sich der Prop-Agent bewegt, bevor der Countdown abgelaufen ist. defer: UIData.Text.SetText(HeartBeatWarningClear) # Setzt den Warntext auf die verbleibende Zeit, wartet eine Sekunde und dekrementiert dann die verbleibende Zeit. Wenn der Countdown beendet ist, wird die Schleife unterbrochen. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("UIData nicht gefunden.") -
Erstelle schließlich die Schleife, die den Countdown-Timer dekrementiert. Verwende die Funktion
SetText(), umHeartBeatWarningMessagemit derWarningTimeRemaininganzuzeigen. Dann warte eine Sekunde mitSleep(), bevor du die verbleibende Zeit dekrementierst. WennWarningTimeRemaining0 oder weniger ist, dann ist der Countdown abgeschlossen und du kannst die Schleife abbrechen.# Verzögert, bis HeartBeatWarningTime beginnen soll. Zählt dann um HeartBeatWarningTime herunter und setzt den Countdown-Text. Löscht den Text, wenn zurückgestellt. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Herzschlag-Countdown beginnt.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Schläft so lange, bis die Warnung erscheint. Logger.Print("Herzschlag-Warnung beginnt.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Eine Zurückstellung erfolgt, wenn die Funktion abgeschlossen ist oder wenn sie abgebrochen wird, z. B. wenn sie ein Rennen verliert. # In diesem Fall wird der Warntext gelöscht, wenn der Countdown abgelaufen ist oder wenn sich der Prop-Agent bewegt, bevor der Countdown abgelaufen ist. defer: UIData.Text.SetText(HeartBeatWarningClear) # Setzt den Warntext auf die verbleibende Zeit, wartet eine Sekunde und dekrementiert dann die verbleibende Zeit. Wenn der Countdown beendet ist, wird die Schleife unterbrochen. loop: Logger.Print("Herzschlag in {WarningTimeRemaining} Sekunden") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("UIData nicht gefunden.")
Effekte für inaktive Spieler abspielen
Wenn AwaitStopMoving() abgeschlossen ist, weißt du, dass es Zeit ist, den Countdown-Timer des Spielers zu starten, und dann ihre Herzschlag-Effekte. Aber sobald sie sich wieder bewegen, willst du den Timer oder den Heartbeat abbrechen, je nachdem, was gerade läuft. Dazu brauchst du einen race-Ausdruck, wo diese Ausdrücke gegeneinander antreten:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance). -
block, wo es einen Countdown gibt, bevor die Heartbeat-Effekte abgespielt werden.
AwaitStartMoving() wird benötigt, um das Rennen zu gewinnen und den Countdown-Timer oder die Heartbeat-Effekte zu stoppen.
Der Blockausdruck wird verwendet, um sicherzustellen, dass die beiden darin enthaltenen Funktionen CountdownTimer() und StartHeartbeart() nacheinander ausgeführt werden und nicht gegeneinander antreten. Der Countdown-Timer soll den Prop-Spieler darauf hinweisen, dass die Herzschlag-Effekte nach Beendigung des Timers beginnen werden, es wäre also nicht sinnvoll, Timer und Herzschlag gleichzeitig zu starten.
Befolge diese Schritte, um Effekte abzuspielen, wenn sich der Spieler zu lange nicht bewegt hat.
- Erstelle eine Erweiterungsmethode mit dem Namen
AwaitStartMoving(), deren Implementierung bis auf die folgenden Punkte dieselbe ist:
-
Es wird geprüft, ob sich der Spieler seit der letzten Simulationsaktualisierung um
MinimumDistanceoder mehr bewegt hat. Anstelle von weniger als dieMinimumDistancewie inAwaitStopMoving(). -
Sie setzt die
StartPositionnicht nach jeder Schleife zurück. WennStartPositionam Ende jeder Schleife zurückgesetzt würde, müsste der Spieler die gesamteMinimumDistanceoder mehr in der Zeit bewegen, die für die Aktualisierung der Simulation benötigt wird, was unmöglich sein könnte.# Schleife, bis der Agent sich mehr als die MinimumDistance bewegt (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Überprüfung, ob der Agent sich um mehr als die Mindestdistanz bewegt hat") # Ruft die Anfangsposition des Agent vom Charakter des Agent in der Szene ab if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Ermittelt die Position des Agent im nächsten Spieltick. NewPosition := Tracked.GetTransform().Translation # Wenn der Abstand der neuen Position von der Startposition größer oder gleich MinimumDistance ist, hat sich der Agent bewegt und wir unterbrechen die Schleife. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("Der Agent hat sich mehr als oder gleich der Mindestdistanz bewegt.") break
-
Erstelle eine Funktion namens
RunPropGameLoop(), die den Heartbeat-Effekt abspielt, wenn der Spieler zu lange inaktiv ist.# Wenn der Prop-Agent sich nicht mehr bewegt, wird eine Race-Bedingung gestartet, ob der Prop-Agent sich über MinimumMoveDistance hinaus bewegt, der Herzschlag-Timer abläuft oder der Prop-Agent eliminiert wird. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starten der Spielschleife für den Prop-Agent.") -
Warte, bis sich der Prop-Agent weniger als die Mindestdistanz bewegt, und fahre dann fort.
# Wenn der Prop-Agent sich nicht mehr bewegt, wird eine Race-Bedingung gestartet, ob der Prop-Agent sich über MinimumMoveDistance hinaus bewegt, der Herzschlag-Timer abläuft oder der Prop-Agent eliminiert wird. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starten der Spielschleife für den Prop-Agent.") # Ewige Schleife durch das Prop-Verhalten, bis der Prop-Agent eliminiert wird oder der Spieler die Sitzung verlässt loop: # Warte, bis sich der Prop-Agent weniger als die Mindestdistanz bewegt, und fahre dann fort. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0) -
Füge den
race-Ausdruck hinzu, um ein Rennen zwischen der Beendigung vonAwaitStartMoving(), was bedeutet, dass der Spieler begonnen hat, sich zu bewegen, und einemblock-Ausdruck mitCountdownTimer()und dannStartHeartbeat()zu machen.# Wenn der Prop-Agent sich nicht mehr bewegt, wird eine Race-Bedingung gestartet, ob der Prop-Agent sich über MinimumMoveDistance hinaus bewegt, der Herzschlag-Timer abläuft oder der Prop-Agent eliminiert wird. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Starten der Spielschleife für den Prop-Agent.") # Ewige Schleife durch das Prop-Verhalten, bis der Prop-Agent eliminiert wird oder der Spieler die Sitzung verlässt loop: # Warte, bis sich der Prop-Agent weniger als die Mindestdistanz bewegt, und fahre dann fort. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Bis sich der Prop-Agent über die Mindestdistanz hinaus bewegt, wird der Countdown bis zum Heartbeat heruntergezählt und dann der Heartbeat auf unbestimmte Zeit abgespielt. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Sobald der Race-Ausdruck abgeschlossen ist (der Prop-Agent bewegt sich), startet die Schleife erneut.