Cómo determinar si un jugador está inactivo
En esta sección, obtendrás más información sobre cómo comprobar si un jugador se ha movido una determinada distancia desde la última actualización de la simulación. Si lo ha hecho, se guarda la posición actual del jugador y se vuelve a comprobar. En caso contrario, el bucle se interrumpe y el método finaliza. Este método utiliza GetFortCharacter[], GetTransform() y Translation para obtener la ubicación del jugador. Puedes obtener más información sobre estas API en sus páginas de referencia correspondientes.
Esta página incluye fragmentos de Verse que muestran cómo ejecutar las mecánicas de juego necesarias. Sigue los pasos que se indican a continuación y copia la secuencia de comandos completa del 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 nombrado
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("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("Comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente a partir del personaje del agente en la escena. if (Tracked := PropAgent.GetFortCharacter[]): var StartPosition:vector3 = Tracked.GetTransform().Translation -
Obtén la próxima posición del jugador en la siguiente actualización de la simulación.
(PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente a partir 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 del 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("Comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente a partir 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 del juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición respecto a la posición inicial es menor que MinimumDistance, significa que el agente no se ha movido, por lo que interrumpimos el bucle. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("El agente se ha movido menos de la distancia mínima.") # En caso contrario, restablecemos StartPosition para asegurarnos de que el jugador se mueve 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 supere el umbral de la
MinimumDistance.# Realiza un bucle hasta que el agente se mueve menos de la MinimumDistance. (PropAgent:agent).AwaitStopMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Comprobando si el agente se ha movido menos de la distancia mínima.") # Obtén la posición inicial del agente a partir 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 del juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición respecto a la posición inicial es menor que MinimumDistance, significa que el agente no se ha movido, por lo que interrumpimos el bucle. if (Distance(StartPosition, NewPosition) < MinimumDistance): Logger.Print("El agente se ha movido menos de la distancia mínima.") break # En caso contrario, restablecemos StartPosition para asegurarnos de que el jugador se mueve desde la nueva posición. else: set StartPosition = NewPosition
Cuenta atrás 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 atrás hasta que se agote el tiempo, y luego borra el texto del aviso y de la cuenta atrás.
- Crea una función nombrada CountdownTimer().
# Se retrasa hasta que se inicie HeartBeatWarningTime. A continuación, realiza una cuenta atrás según HeartBeatWarningTime y establece el texto de la cuenta atrás. Borra el texto cuando se aplaza. CountdownTimer(PropAgent:agent)<suspends>:void = Logger.Print("Iniciando cuenta atrás de latido.") -
Primero tienes que intentar obtener el
heartbeat_warning_uidel jugador asociado desde el mapa que configuraste en heartbeat.verse. Si lo consigues, entonces tienes que iniciar el retraso entre que el jugador se detiene y se muestra el cronómetro de cuenta atrás.# Se retrasa hasta que se inicie HeartBeatWarningTime. A continuación, realiza una cuenta atrás según HeartBeatWarningTime y establece el texto de la cuenta atrás. Borra el texto cuando se aplaza. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Iniciando cuenta atrás de latido.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Permanece inactivo el tiempo necesario antes de que aparezca el aviso. Logger.Print("Iniciando aviso de latido.") else: Logger.Print("UIData no encontrados.") -
Ahora crea la variable que aparecerá en la pantalla y que disminuirá en uno cada segundo. Nómbrala
WarningTimeRemaining. Ajústala enWarningTimedesde heartbeat.verse. ComoWarningTimeRemaininges unintyWarningTimees unfloat, tendrás que utilizar la funciónCeil[]para crear unint.# Se retrasa hasta que se inicie HeartBeatWarningTime. A continuación, realiza una cuenta atrás según HeartBeatWarningTime y establece el texto de la cuenta atrás. Borra el texto cuando se aplaza. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Iniciando cuenta atrás de latido.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Permanece inactivo el tiempo necesario antes de que aparezca el aviso. Logger.Print("Iniciando aviso de latido.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} else: Logger.Print("UIData no encontrados.") -
Antes de iniciar el bucle de cuenta atrás, utiliza la expresión
deferpara borrar el cronómetro de cuenta atrás de la interfaz de usuario del jugador cuando finalice la funciónCountdownTimer(). Solo se completará cuando se agote el cronómetro o cuando el jugador comience a moverse de nuevo. Consulta Defer para obtener más información.# Se retrasa hasta que se inicie HeartBeatWarningTime. A continuación, realiza una cuenta atrás según HeartBeatWarningTime y establece el texto de la cuenta atrás. Borra el texto cuando se aplaza. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Iniciando cuenta atrás de latido.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Permanece inactivo el tiempo necesario antes de que aparezca el aviso. Logger.Print("Iniciando aviso de latido.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un aplazamiento se produce cuando la función finaliza o si se cancela, como por ejemplo si pierde una carrera. # En este caso, el texto del aviso se borra cuando termina la cuenta atrás o si el agente de elementos se mueve antes de que termine la cuenta atrás. defer: UIData.Text.SetText(HeartBeatWarningClear) # Establece el texto de aviso en el tiempo restante, espera un segundo y luego reduce el tiempo restante. Si se completa la cuenta atrás, interrumpe el bucle. UIData.Text.SetText(HeartBeatWarningMessage(WarningTimeRemaining)) else: Logger.Print("UIData no encontrados.") -
Por último, crea el bucle que disminuye el cronómetro de cuenta atrás. Utiliza la función
SetText()para mostrarHeartBeatWarningMessageconWarningTimeRemaining. A continuación, espera un segundo conSleep(), antes de disminuir el tiempo restante. SiWarningTimeRemaininges 0 o menos, la cuenta atrás se ha completado y puedes interrumpir el bucle.# Se retrasa hasta que se inicie HeartBeatWarningTime. A continuación, realiza una cuenta atrás según HeartBeatWarningTime y establece el texto de la cuenta atrás. Borra el texto cuando se aplaza. CountdownTimer(PropAgent:agent)<suspends>:void= Logger.Print("Iniciando cuenta atrás de latido.") if (UIData := HeartBeat.WarningUI[PropAgent]): Sleep(HeartBeat.MoveTime - HeartBeat.WarningTime) # Permanece inactivo el tiempo necesario antes de que aparezca el aviso. Logger.Print("Iniciando aviso de latido.") var WarningTimeRemaining:int = 0 if (set WarningTimeRemaining = Ceil[HeartBeat.WarningTime]) {} # Un aplazamiento se produce cuando la función finaliza o si se cancela, como por ejemplo si pierde una carrera. # Así que, en este caso, el texto de aviso se borra cuando termina la cuenta atrás o si el agente elemento se mueve antes de que la cuenta atrás finalice. defer: UIData.Text.SetText(HeartBeatWarningClear) # Establece el texto de aviso en el tiempo restante, espera un segundo y luego reduce el tiempo restante. Si se completa la cuenta atrás, interrumpe 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("UIData no encontrados.")
Cómo reproducir efectos en jugadores inactivos
Cuando se complete AwaitStopMoving(), sabrás que es el momento de iniciar el cronómetro de cuenta atrás del jugador, y a continuación sus efectos de latido. No obstante, en cuanto empiece a moverse de nuevo, cancela el cronómetro o el latido, lo que esté en marcha en ese momento. Para ello, necesitas una expresión race en la que las dos expresiones de carrera son:
-
PropAgent.AwaitStartMoving(MinimumMoveDistance). -
blockdonde hay una cuenta atrás antes de que se reproduzcan los efectos de latido.
Se necesita AwaitStartMoving() para ganar la carrera y detener el cronómetro de cuenta atrás 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 secuencialmente y no compitan entre sí. El cronómetro de cuenta atrás sirve para que el jugador del equipo de elementos sepa que sus efectos de latido empezará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.
Sigue estos pasos para reproducir efectos cuando el jugador no se haya movido durante mucho tiempo.
- Crea un método de extensión nombrado
AwaitStartMoving(), cuya implementación sea la misma excepto por lo siguiente:
-
Comprueba si el jugador se ha movido la
MinimumDistanceo más desde la última actualización de la simulación en lugar de menos de laMinimumDistancecomo enAwaitStopMoving(). -
No restablece la
StartPositiondespués de cada bucle. SiStartPositionse restableciese al final de cada bucle, el jugador tendría que moverse toda laMinimumDistanceo más en el tiempo que tarda en hacerse la actualización de la simulación, lo que sería prácticamente imposible.# Realiza un bucle hasta que el agente se mueve más de la MinimumDistance. (PropAgent:agent).AwaitStartMoving(MinimumDistance:float)<suspends>:void= Logger.Print("Comprobando si el agente se mueve más allá de la distancia mínima.") # Obtén la posición inicial del agente a partir 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 del juego. NewPosition := Tracked.GetTransform().Translation # Si la distancia de la nueva posición respecto a la posición inicial es mayor o igual que MinimumDistance, significa que el agente se ha movido, por lo que interrumpimos el bucle. if (Distance(StartPosition, NewPosition) >= MinimumDistance): Logger.Print("El agente se ha movido más o igual que la distancia mínima.") break
-
Crea una función nombrada
RunPropGameLoop()que consiga reproducir el efecto de latido cuando el jugador esté inactivo demasiado tiempo.# Si el agente de elementos deja de moverse, entonces corre para ver si el agente de elementos se mueve más allá de la MinimumMoveDistance, si se completa el cronómetro de latido o si el agente de elementos es eliminado. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Iniciando bucle de juego del agente de elementos.") -
Espera a que el agente de elementos se mueva menos de la distancia mínima y, a continuación, avanza.
# Si el agente elemento deja de moverse entonces corre para ver si este se mueve más allá de la MinimumMoveDistance, el cronómetro de latidos se agota, o el agente elemento es eliminado. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Iniciando bucle de juego del agente de elementos.") # Realiza un bucle eterno por el comportamiento del elemento hasta que el agente de elementos sea eliminado o el jugador abandone la sesión. loop: # Espera a que el agente de elementos se mueva menos de la distancia mínima y luego avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) Sleep(0.0) -
Añade la expresión
racepara competir entreAwaitStartMoving(), lo que significa que el jugador ha empezado a moverse, y se está ejecutando una expresiónblockconCountdownTimer()yStartHeartbeat().# Si el agente elemento deja de moverse entonces corre para ver si este se mueve más allá de la MinimumMoveDistance, el cronómetro de latidos se agota, o el agente elemento es eliminado. RunPropGameLoop(PropAgent:agent)<suspends>:void = Logger.Print("Iniciando bucle de juego del agente de elementos.") # Realiza un bucle infinito por el comportamiento del elemento hasta que el agente elemento sea eliminado o el jugador abandone la sesión. loop: # Espera hasta que el agente elemento se mueva menos que la distancia mínima, y entonces avanza. PropAgent.AwaitStopMoving(MinimumMoveDistance) # Hasta que el agente de elementos se desplace más allá de la distancia mínima, inicia la cuenta atrás hasta el latido y luego reproduce el latido indefinidamente. race: PropAgent.AwaitStartMoving(MinimumMoveDistance) block: CountdownTimer(PropAgent) PropAgent.StartHeartbeat() Sleep(0.0) # Una vez finalizada la carrera (el agente de elementos se mueve), vuelve a iniciar el bucle.