Cómo determinar si un jugador está inactivo
En esta sección, aprenderás a comprobar si un jugador se desplazó una distancia determinada desde la última actualización de la simulación. Si es así, se guarda la posición actual del jugador y se vuelve a comprobar. Si no, el bucle se rompe, y el método finaliza. Este método usa GetFortCharacter[], GetTransform() y Translation para obtener la ubicación del jugador. Puedes obtener más información al respecto en las páginas de referencia de la API.
En esta página, se incluyen fragmentos de Verse que muestran cómo ejecutar las mecánicas de juego que son necesarias en este. Sigue los pasos que aparecen a continuación y copia la secuencia completa de comandos en el paso 6 de este tutorial.
Sigue estos pasos para determinar si un jugador está inactivo.
-
Crea un método de extensión para la clase de agente denominado
AwaitStopMoving(). Esto significa que estás añadiendo un método personalizado a una clase ya definida.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se ha movido menos de la distancia mínima.") -
Obtén la posición inicial del jugador.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente por medio de la posición del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation -
Obtén la siguiente posición del jugador en la actualización de simulación siguiente.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente por medio de la posición del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Obtén la posición del agente en el siguiente tic de juego. NewPosition := Tracked.GetTransform().Translation - Comprueba si la distancia entre la posición inicial y la última posición está dentro de un umbral aceptable, pasado a la función como parámetro
MinimumDistance.(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente por medio de la posición del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation Sleep(0.0) # Obtén la posición del agente en el siguiente tic de juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición a la posición inicial es menor que MinimumDistance, el agente no se movió, y rompemos el bucle. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("El agente se ha movido menos de la distancia mínima.") # En caso contrario, reiniciamos StartPosition para asegurarnos de que el jugador se mueva desde la nueva posición. else: set StartPosition = NewPosition -
Ahora queremos hacer un bucle de comprobación entre la posición inicial y la última, y salir del bucle cuando la distancia entre las posiciones esté por encima del umbral
MinimumDistance.# Hace un bucle hasta que el agente se mueva menos que la MinimumDistance. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente por medio de la posición del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Obtén la posición del agente en el siguiente tic de juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición a la posición inicial es menor que MinimumDistance, el agente no se movió, y rompemos el bucle. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("El agente se movido una distancia mayor o equivalente a la distancia mínima.") break # En caso contrario, reiniciamos StartPosition para asegurarnos de que el jugador se mueva desde la nueva posición. else: set StartPosition = NewPosition
Cuenta regresiva antes del latido
Sigue estos pasos para esperar una cantidad de tiempo igual a HeartBeat.MoveTime - HeartBeat.WarningTime antes de mostrar un aviso y un cronómetro de cuenta regresiva hasta que el tiempo se agote, y luego, borra el texto de aviso y cuenta regresiva.
- Crea una función llamada CountdownTimer().
# Retrasa hasta que HeartBeatWarningTime debe comenzar. A continuación, realiza una cuenta regresiva según HeartBeatWarningTime y establece el texto de la cuenta regresiva. Borra el texto cuando se difiere. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Se está iniciando la cuenta regresiva.") -
Primero tienes que intentar obtener el
heartbeat_warning_uipara el jugador asociado desde el mapa que configuraste en heartbeat.verse. Si tiene éxito, tendrás que iniciar el retraso entre que el jugador se detiene y se muestra el cronómetro de cuenta regresiva.# Retrasa hasta que HeartBeatWarningTime debe comenzar. A continuación, realiza una cuenta regresiva según HeartBeatWarningTime y establece el texto de la cuenta regresiva. Borra el texto cuando se difiere. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Se está iniciando la cuenta regresiva.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Duerme el tiempo necesario antes de que aparezca el aviso. Logger.Print("Aviso de latido iniciado.") else: Logger.Print("No se encontró UIData.") -
Ahora crea la variable que aparecerá en la pantalla, y se reducirá en uno cada segundo. Nómbrala
WarningTimeRemaining. Configúrala comoWarningTimede heartbeat.verse. ComoWarningTimeRemaininges unint, yWarningTimees unfloat, tendrás que usar la funciónCeil[]para crear unint.# Retrasa hasta que HeartBeatWarningTime debe comenzar. A continuación, realiza una cuenta regresiva según HeartBeatWarningTime y establece el texto de la cuenta regresiva. Borra el texto cuando se difiere. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Se está iniciando la cuenta regresiva.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Duerme el tiempo necesario antes de que aparezca el aviso. Logger.Print("Aviso de latido iniciado.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("No se encontró UIData.") -
Antes de comenzar el bucle de cuenta regresiva, usa la expresión
deferpara borrar el temporizador de cuenta regresiva de la IU del jugador cada vez que se complete la funciónCountdownTimer(). Solo se completará cuando el cronómetro finalice o cuando el jugador comience a moverse de nuevo. Consulta Diferir para obtener más información.# Retrasa hasta que HeartBeatWarningTime debe comenzar. A continuación, realiza una cuenta regresiva según HeartBeatWarningTime y establece el texto de la cuenta regresiva. Borra el texto cuando se difiere. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Se está iniciando la cuenta regresiva.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Duerme el tiempo necesario antes de que aparezca el aviso. Logger.Print("Aviso de latido iniciado.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Diferir ocurre cuando la función se completa o se cancela, por ejemplo, si pierde una carrera. # Así que, en este caso, el texto de aviso se borra cuando termina la cuenta regresiva o si el agente de utilería se mueve antes de que esta termine. defer: UIData.Text.SetText(HeartBeatWarningClear) # Establece el texto de aviso en el tiempo restante, espera un segundo y, luego, descuenta el tiempo restante. Si se completa la cuenta regresiva, rompe el bucle. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("No se encontró UIData.") -
Finalmente, crea el loop que disminuye el temporizador de cuenta regresiva. Usa la función
SetText()para mostrarHeartBeatWarningMessagecon elWarningTimeRemaining. Luego espera un segundo conSleep(), antes de disminuir el tiempo restante. SiWarningTimeRemaininges 0 o menos, la cuenta regresiva está completa y puedes romper el loop.# Retrasa hasta que HeartBeatWarningTime debe comenzar. A continuación, realiza una cuenta regresiva según HeartBeatWarningTime y establece el texto de la cuenta regresiva. Borra el texto cuando se difiere. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Se está iniciando la cuenta regresiva.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Duerme el tiempo necesario antes de que aparezca el aviso. Logger.Print("Aviso de latido iniciado.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Diferir ocurre cuando la función se completa o se cancela, por ejemplo, si pierde una carrera. # Así que, en este caso, el texto de aviso se borra cuando termina la cuenta regresiva o si el agente de utilería se mueve antes de que esta termine. defer: UIData.Text.SetText(HeartBeatWarningClear) # Establece el texto de aviso en el tiempo restante, espera un segundo y, luego, descuenta el tiempo restante. Si se completa la cuenta regresiva, rompe el bucle. loop: Logger.Print("Latido en {WarningTimeRemaining} segundos.") UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) Sleep(1.0) set WarningTimeRemaining -= 1 if (WarningTimeRemaining <= 0): break else: Logger.Print("No se encontró UIData.")
Cómo reproducir efectos en jugadores inactivos
Cuando AwaitStopMoving() se completa, sabes que es el momento de iniciar el cronómetro de cuenta regresiva del jugador, y luego, sus efectos de latido. Pero tan pronto como empiece a moverse de nuevo, deberás cancelar el cronómetro o el latido del corazón, cualquiera que se esté ejecutando en ese momento. Para ello, necesitas una expresión race, donde las dos expresiones de carrera son las siguientes:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance). -
blockdonde hay una cuenta regresiva antes de que se reproduzcan los efectos de latido.
Se necesita AwaitStartMoving() para ganar la carrera y detener el cronómetro de cuenta regresiva o los efectos de latido.
La expresión de bloque se utiliza para garantizar que las dos funciones que contiene, CountdownTimer() y StartHeartbeart(), se ejecuten de forma secuencial y no compitan entre sí. El cronómetro de cuenta regresiva sirve para que el jugador de utilería sepa que sus efectos de latido comenzarán después de que se complete el cronómetro, por lo que no tendría sentido iniciar el cronómetro y el latido al mismo tiempo.
Realiza lo siguiente para reproducir los efectos cuando el jugador no se haya movido por mucho tiempo.
- Crea un método de extensión denominado
AwaitStartMoving()donde la implementación es la misma excepto por lo siguiente:
-
Comprueba si el jugador se movió una
MinimumDistanceo más desde la última actualización de la simulación, en lugar de ser menor que laMinimumDistancecomo enAwaitStopMoving(). -
No restablece la
StartPositiondespués de cada bucle. SiStartPositionse reseteara al final de cada bucle, el jugador tendría que moverse toda laMinimumDistanceo más en el tiempo que tarda en actualizarse la simulación, lo que sería imposible.# Hace un bucle hasta que el agente se mueva más que la MinimumDistance. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Se está comprobando si el agente se mueve más lejos que la distancia mínima.") # Obtén la posición inicial del agente por medio de la posición del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): StartPosition:vector3 = Tracked.GetTransform().Translation loop: Sleep(0.0) # Obtén la posición del agente en el siguiente tic de juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición a la posición inicial es mayor o igual que MinimumDistance, el agente se movió, y rompemos el bucle. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("El agente se movido una distancia mayor o equivalente a la distancia mínima.") break
-
Crea una función llamada
RunPropGameLoop()que logre reproducir el efecto de latido cuando el jugador está inactivo demasiado tiempo.# Si el agente de utilería se deja de mover, entonces corre a ver si el agente de utilería se mueve más allá de MinimumMoveDistance, el cronómetro de latido de corazón se completa o el agente de utilería se elimina. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Se está iniciando el bucle de juego de agente de utilería.") -
Espera hasta que el agente de utilería se mueva menos que la distancia mínima; luego, avanza.
# Si el agente de utilería se deja de mover, entonces corre a ver si el agente de utilería se mueve más allá de MinimumMoveDistance, el cronómetro de latido de corazón se completa o el agente de utilería se elimina. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Se está iniciando el bucle de juego de agente de utilería.") # Muévete en bucle a través del comportamiento de utilería hasta que el agente de utilería se elimine o hasta que el jugador abandone la sesión. loop: # Espera hasta que el agente de utilería se mueva menos que la distancia mínima; luego, avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0) -
Añade la expresión
racepara competir entre la finalización deAwaitStartMoving(), lo que significa que el jugador comenzó a moverse, y una expresiónblockconCountdownTimer()y, luego,StartHeartbeat()en ejecución.# Si el agente de utilería se deja de mover, entonces corre a ver si el agente de utilería se mueve más allá de MinimumMoveDistance, el cronómetro de latido de corazón se completa o el agente de utilería se elimina. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Se está iniciando el bucle de juego de agente de utilería.") # Muévete en bucle a través del comportamiento de utilería hasta que el agente de utilería sea eliminado o hasta que el jugador abandone la sesión. loop: # Espera hasta que el agente de utilería se mueva menos que la distancia mínima; luego, avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Hasta que el agente de utilería se mueva más allá que la distancia mínima, haz la cuenta regresiva del latido de corazón y, luego, reprodúcelo indefinidamente. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Una vez que la carrera se completa (el agente de utilería se mueve), inicia el bucle nuevamente.