Determinare se un giocatore è inattivo
In questa sezione imparerai a verificare se un giocatore si è mosso di una certa distanza dall'ultimo aggiornamento della simulazione. In caso affermativo, la posizione attuale del giocatore viene salvata e ricontrollata. In caso contrario, il loop si interrompe e il metodo viene completato. Questo metodo utilizza GetFortCharacter[]
, GetTransform()
, e Translation
per ottenere la posizione del giocatore. Per saperne di più, consulta le pagine di riferimento API.
Questa pagina include snippet di Verse che mostrano come eseguire le meccaniche di gameplay necessarie in questo gameplay. Segui i passaggi seguenti e copia lo script completo al passaggio 6 di questo tutorial.
Segui questi passaggi per determinare se un giocatore è inattivo.
-
Crea un metodo di estensione per la classe agente denominato
AwaitStopMoving()
. Ciò significa che stai aggiungendo un metodo personalizzato a una classe già definita.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si è mosso di una distanza inferiore a quella minima.")
-
Ottieni la posizione iniziale del giocatore.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si è mosso di una distanza inferiore a quella minima.") # Ottieni la posizione iniziale dell'agente dal personaggio dell'agente nella scena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation
-
Ottieni la posizione successiva del giocatore nel successivo aggiornamento della simulazione.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si è mosso di una distanza inferiore a quella minima.") # Ottieni la posizione iniziale dell'agente dal personaggio dell'agente nella scena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Ottieni la posizione dell'agente nel prossimo tick di gioco. NewPosition := Tracked.GetTransform().Translation
- Controlla se la distanza tra la posizione iniziale e l'ultima posizione rientra in una soglia accettabile, passata alla funzione come parametro
MinimumDistance
.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si è mosso di una distanza inferiore a quella minima.") # Ottieni la posizione iniziale dell'agente dal personaggio dell'agente nella scena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Ottieni la posizione dell'agente nel prossimo tick di gioco. NewPosition := Tracked.GetTransform().Translation # Se la distanza della nuova posizione dalla posizione di partenza è inferiore a MinimumDistance, l'agente non si è mosso e si interrompe il loop. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("L'agente si è mosso di una distanza inferiore a quella minima.") # Altrimenti, reimpostiamo StartPosition per assicurarci che il giocatore si muova dalla nuova posizione. else: set StartPosition = NewPosition
-
Ora vogliamo eseguire il controllo in loop tra la posizione iniziale e quella più recente e uscire dal loop quando la distanza tra le posizioni è superiore alla soglia
MinimumDistance
.# Esegue un loop finché l'agente non si muove a una distanza inferiore alla MinimumDistance. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si è mosso di una distanza inferiore a quella minima.") # Ottieni la posizione iniziale dell'agente dal personaggio dell'agente nella scena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Ottieni la posizione dell'agente nel prossimo tick di gioco. NewPosition := Tracked.GetTransform().Translation # Se la distanza della nuova posizione dalla posizione di partenza è inferiore a MinimumDistance, l'agente non si è mosso e si interrompe il loop. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("L'agente si è mosso di una distanza inferiore a quella minima.") break # Altrimenti, reimpostiamo StartPosition per assicurarci che il giocatore si muova dalla nuova posizione. else: set StartPosition = NewPosition
Conto alla rovescia prima del battito cardiaco
Segui questi passaggi per attendere un tempo pari a HeartBeat.MoveTime - HeartBeat.WarningTime
prima di visualizzare un avviso e un timer per il conto alla rovescia. Allo scadere del conto alla rovescia, viene cancellato il testo dell'avviso e del conto alla rovescia.
- Crea una funzione denominata CountdownTimer().
# Ritarda fino a quando HeartBeatWarningTime deve avviarsi. Quindi esegui il conto alla rovescia per HeartBeatWarningTime e imposta il testo del conto alla rovescia. Cancella il testo in caso di differita. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Inizio del conto alla rovescia del battito cardiaco.")
-
Per prima cosa devi cercare di ottenere
heartbeat_warning_ui
per il giocatore associato dalla mappa che hai impostato in heartbeat.verse. Se questa operazione ha esito positivo, devi avviare il ritardo tra l'arresto del giocatore e la visualizzazione del timer del conto alla rovescia.# Ritarda fino a quando HeartBeatWarningTime deve avviarsi. Quindi esegui il conto alla rovescia per HeartBeatWarningTime e imposta il testo del conto alla rovescia. Cancella il testo in caso di differita. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Avvio del conto alla rovescia del battito cardiaco.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Sospendi per il tempo necessario a far visualizzare l'avviso. Logger.Print("Avvio dell'avviso del battito cardiaco.") else: Logger.Print("UIData non trovato.")
-
Adesso crea la variabile che verrà visualizzata sullo schermo e che verrà diminuita di uno a ogni secondo che passa. Denominala
WarningTimeRemaining
. Impostala suWarningTime
da heartbeat.verse. PoichéWarningTimeRemaining
è unint
eWarningTime
è unfloat
, dovrai utilizzare la funzioneCeil[]
per creare una funzioneint
.# Ritarda fino a quando HeartBeatWarningTime deve avviarsi. Quindi esegui il conto alla rovescia per HeartBeatWarningTime e imposta il testo del conto alla rovescia. Cancella il testo in caso di differita. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Avvio del conto alla rovescia del battito cardiaco.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Sospendi per il tempo necessario a far visualizzare l'avviso. Logger.Print("Avvio dell'avviso del battito cardiaco.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("UIData non trovato.")
-
Prima di avviare il loop del conto alla rovescia, utilizza l'espressione
defer
per cancellare il timer del conto alla rovescia dall'UI del giocatore ogni volta che viene completata la funzioneCountdownTimer()
. Si completerà solo quando il timer si esaurirà o quando il giocatore ricomincerà a muoversi. Per saperne di più, vedi Defer.# Ritarda fino a quando HeartBeatWarningTime deve avviarsi. Quindi esegui il conto alla rovescia per HeartBeatWarningTime e imposta il testo del conto alla rovescia. Cancella il testo in caso di differita. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Avvio del conto alla rovescia del battito cardiaco.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Sospendi per il tempo necessario a far visualizzare l'avviso. Logger.Print("Avvio dell'avviso del battito cardiaco.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un'espressione defer avviene quando la funzione viene completata o se viene annullata, ad esempio se risulta un'espressione perdente. # Quindi, in questo caso, il testo di avviso viene cancellato quando il conto alla rovescia termina o se l'agente oggetto scenografico si muove prima del termine del conto alla rovescia. defer: UIData.Text.SetText(HeartBeatWarningClear) # Imposta il testo di avviso sul tempo rimanente, attendi un secondo e poi riduci il tempo rimanente. Se il conto alla rovescia viene completato, interrompi il loop. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("UIData non trovato.")
-
Infine, crea il loop che diminuisce il timer del conto alla rovescia. Utilizza la funzione
SetText()
per visualizzareHeartBeatWarningMessage
conWarningTimeRemaining
. Quindi attendi un secondo conSleep()
prima di diminuire il tempo rimanente. SeWarningTimeRemaining
è pari o inferiore a 0, allora il conto alla rovescia è completo e puoi interrompere il loop.# Ritarda fino a quando HeartBeatWarningTime deve avviarsi. Quindi esegui il conto alla rovescia per HeartBeatWarningTime e imposta il testo del conto alla rovescia. Cancella il testo in caso di differita. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Avvio del conto alla rovescia del battito cardiaco.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Sospendi per il tempo necessario a far visualizzare l'avviso. Logger.Print("Avvio dell'avviso del battito cardiaco.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un'espressione defer avviene quando la funzione viene completata o se viene annullata, ad esempio se risulta un'espressione perdente. # Quindi, in questo caso, il testo di avviso viene cancellato quando il conto alla rovescia termina o se l'agente oggetto scenografico si muove prima del termine del conto alla rovescia. defer: UIData.Text.SetText(HeartBeatWarningClear) # Imposta il testo di avviso sul tempo rimanente, attendi un secondo e poi riduci il tempo rimanente. Se il conto alla rovescia viene completato, interrompi il loop. loop: Logger.Print("Battito cardiaco tra {WarningTimeRemaining} secondi.") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("UIData non trovato.")
Riproduzione di effetti sui giocatori inattivi
Quando si completa AwaitStopMoving()
, sai che è il momento di avviare il timer del conto alla rovescia del giocatore e dopo gli effetti del suo battito cardiaco. Ma non appena ricomincia a muoversi, devi annullare il timer o il battito cardiaco, a seconda di quale sia in corso. Per eseguire questa operazione, è necessaria un'espressione race
, in cui le due espressioni race sono:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance)
. -
block
, che contiene un conto alla rovescia prima che inizi la riproduzione degli effetti del battito cardiaco.
L'espressione AwaitStartMoving()
è necessaria per ottenere un'espressione vincente e interrompere il timer del conto alla rovescia o gli effetti del battito cardiaco.
L'espressione block viene utilizzata per garantire che le due funzioni al suo interno, CountdownTimer()
e StartHeartbeart()
, vengano eseguite in modo sequenziale e non in concorrenza tra loro. Il timer del conto alla rovescia serve a far sapere al giocatore oggetto scenografico che gli effetti del battito cardiaco inizieranno dopo il completamento del timer, quindi non avrebbe senso far partire in contemporanea sia il timer che il battito cardiaco.
Segui questi passaggi per riprodurre gli effetti quando il giocatore non si muove per troppo tempo.
- Crea un metodo di estensione denominato
AwaitStartMoving()
dove l'implementazione è la stessa tranne per quanto segue:
-
Controlla se il giocatore si è mosso almeno di una
MinimumDistance
o più dall'ultimo aggiornamento della simulazione. Si tratto del caso opposto a quando doveva muoversi di una distanza inferiore allaMinimumDistance
, come avveniva inAwaitStopMoving()
. -
Non reimposta la
StartPosition
dopo ogni loop. SeStartPosition
fosse reimpostata alla fine di ogni loop, il giocatore dovrebbe muoversi per l'interaMinimumDistance
o più nel tempo necessario per aggiornare la simulazione, il che potrebbe essere impossibile.# Esegue un loop finché l'agente non si muove più della MinimumDistance. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Verifica se l'agente si muove oltre la distanza minima.") # Ottieni la posizione iniziale dell'agente dal personaggio dell'agente nella scena. if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Ottieni la posizione dell'agente nel prossimo tick di gioco. NewPosition := Tracked.GetTransform().Translation # Se la distanza della nuova posizione dalla posizione di partenza è maggiore o uguale alla MinimumDistance, l'agente si è mosso e si interrompe il loop. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("L'agente si è mosso per una distanza pari o superiore a quella minima.") break
-
Crea una funzione denominata
RunPropGameLoop()
che riesca a riprodurre l'effetto del battito cardiaco quando il giocatore rimane inattivo per troppo tempo.# Se l'agente oggetto scenografico smette di muoversi, allora esegui un'espressione race per vedere se l'agente oggetto scenografico si muove oltre la MinimumMoveDistance, se il timer del battito cardiaco viene completato o se l'agente oggetto scenografico viene eliminato. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Avvio loop di gioco dell'agente oggetto scenografico.")
-
Attendi che l'agente oggetto scenografico si muova a una distanza inferiore a quella minima, quindi avanza.
# Se l'agente oggetto scenografico smette di muoversi, allora esegui un'espressione race per vedere se l'agente oggetto scenografico si muove oltre la MinimumMoveDistance, se il timer del battito cardiaco viene completato o se l'agente oggetto scenografico viene eliminato. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Avvio loop di gioco dell'agente oggetto scenografico.") # Esegui un loop infinito del comportamento dell'oggetto scenografico fino a quando l'agente oggetto scenografico viene eliminato o il giocatore abbandona la sessione. loop: # Attendi che l'agente oggetto scenografico si muova a una distanza inferiore a quella minima, quindi avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0)
-
Aggiungi l'espressione
race
per gareggiare tra il completamento diAwaitStartMoving()
, a significare che il giocatore ha iniziato a muoversi, e un'espressioneblock
conCountdownTimer()
e poiStartHeartbeat()
in esecuzione.# Se l'agente oggetto scenografico smette di muoversi, allora esegui un'espressione race per vedere se l'agente oggetto scenografico si muove oltre la MinimumMoveDistance, se il timer del battito cardiaco viene completato o se l'agente oggetto scenografico viene eliminato. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Avvio loop di gioco dell'agente oggetto scenografico.") # Esegui un loop infinito del comportamento dell'oggetto scenografico fino a quando l'agente oggetto scenografico viene eliminato o il giocatore abbandona la sessione. loop: # Attendi che l'agente oggetto scenografico si muova a una distanza inferiore a quella minima, quindi avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Finché l'agente oggetto scenografico non si muove oltre la distanza minima, esegui il conto alla rovescia fino al battito cardiaco e poi lo riproduci all'infinito. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Una volta completata l'espressione race (l'agente oggetto scenografico si muove), ricomincia il loop.