FiveM resmon alto ms: cómo encontrar y reparar scripts lentos
¿Un recurso muestra ms alto en resmon? Cómo leer resmon 1, por qué los bucles Wait(0) cuestan tanto, y cómo dormir cuando estás lejos, cachear el ped y usar puntos y zonas de ox_lib.
Abres el monitor de recursos y un script muestra esto:
my_script 0.35 msUn script inactivo debe estar cerca de cero. Un script que come un tercio de un milisegundo, o mucho más, en cada frame hace que tu juego se entrecorte, y los jugadores con computadoras más débiles lo sienten primero. Esta guía muestra cómo ver qué recurso es el problema y los cambios que lo reducen.
Abre el monitor de recursos
En la consola F8 del juego, escribe:
resmon 1Una superposición muestra cada recurso del cliente con su tiempo de CPU (ms) por frame y su memoria. Escribe resmon 0 para cerrarlo. Comprueba estas cosas:
- Permanece quieto, en un lugar tranquilo, y lee la lista. Los números que importan son los que permanecen altos cuando no haces nada.
- Mira quién está en la parte superior. Un recurso que solo sube cerca de su propio marcador o tienda es normal. Uno que es alto en todas partes no lo es.
- Obsérvalo unos segundos. Un solo pico cuando un script se inicia es inofensivo; un valor constante es el problema.
El ms es tiempo en el cliente. El rendimiento del servidor es un tema separado: consulta advertencia de bloqueo de thread del servidor.
Causa 1: un bucle con Wait(0)
La razón más común para un valor alto es un bucle que se ejecuta cada frame, todo el tiempo:
CreateThread(function()
while true do
Wait(0)
local ped = PlayerPedId()
local coords = GetEntityCoords(ped)
local dist = #(coords - vec3(215.0, -810.0, 30.7))
if dist < 3.0 then
DrawText3D(215.0, -810.0, 30.7, 'Press E')
end
end
end)Esto ejecuta los nativos 60 veces por segundo, incluso cuando el jugador está del otro lado del mapa. La mayoría del tiempo la respuesta es «nada que hacer», y ese costo se desperdicia.
Solución 1: duerme cuando estés lejos
Deja que el bucle duerma más tiempo cuando nada está cerca, y solo se ejecute cada frame cuando el jugador esté cerca:
CreateThread(function()
local target = vec3(215.0, -810.0, 30.7)
while true do
local sleep = 1000
local coords = GetEntityCoords(PlayerPedId())
local dist = #(coords - target)
if dist < 10.0 then
sleep = 0
if dist < 3.0 then
DrawText3D(target.x, target.y, target.z, 'Press E')
end
elseif dist < 50.0 then
sleep = 250
end
Wait(sleep)
end
end)El bucle comprueba una vez por segundo cuando estás lejos, que cuesta casi nada, y se ejecuta cada frame solo dentro del área de 10 metros donde dibuja. Usa #(a - b) con valores vec3 para la distancia: es más rápido que el nativo antiguo GetDistanceBetweenCoords.
Solución 2: cachea valores que reutilizas
Llamar a un nativo cada frame para obtener un valor que rara vez cambia es un desperdicio. PlayerPedId() es el clásico. Almacénalo una vez y actualízalo solo cuando pueda cambiar:
local ped = PlayerPedId()
CreateThread(function()
while true do
Wait(500)
ped = PlayerPedId()
end
end)Si usas ox_lib, lo hace por ti. cache.ped se mantiene actualizado, y cache.vehicle y cache.serverId funcionan de la misma manera:
local coords = GetEntityCoords(cache.ped)lib.onCache te permite reaccionar cuando un valor cacheado cambia, sin comprobar en un bucle.
Solución 3: deja de llamar nativos cada frame
Comprueba el cuerpo del bucle y pregunta por cada línea: ¿esto realmente tiene que ejecutarse cada frame? Mueve lo que no lo hace.
- Dibujar (texto, marcadores, sprites) tiene que ejecutarse cada frame, pero solo mientras sea visible.
- Leer datos (trabajo, dinero, inventario) no: léelo en un evento, y mantenlo en una variable.
- Buscar (
GetClosestVehicle,GetGamePool, bucles sobre todos los jugadores) es caro. Ejecútalo una vez cada segundo o dos, no cada frame. - No crees cosas en un bucle: crear blips, entradas de texto o tablas cada frame llena la memoria y hace que el recolector de basura funcione.
-- run once per second
local closest = nil
CreateThread(function()
while true do
closest = GetClosestVehicle(GetEntityCoords(cache.ped), 5.0, 0, 70)
Wait(1000)
end
end)Solución 4: usa puntos y zonas de ox_lib en lugar de bucles
La mayoría de los bucles «¿estoy cerca de este lugar?» no son necesarios. ox_lib puede hacer el trabajo de distancia por ti, y solo ejecuta tu código cuando importa.
Un punto llama a una función cuando entras o sales de un radio, y uno cada frame solo mientras estés dentro:
local point = lib.points.new({
coords = vec3(215.0, -810.0, 30.7),
distance = 10.0,
})
function point:onEnter()
print('entered')
end
function point:onExit()
print('left')
end
function point:nearby()
DrawText3D(self.coords.x, self.coords.y, self.coords.z, 'Press E')
if self.currentDistance < 2.0 and IsControlJustReleased(0, 38) then
print('used')
end
endLas zonas hacen lo mismo para formas como una esfera, una caja o un polígono:
local zone = lib.zones.sphere({
coords = vec3(215.0, -810.0, 30.7),
radius = 3.0,
onEnter = function() print('in') end,
onExit = function() print('out') end,
})Para interacción con entidades y lugares, un recurso objetivo (ox_target, por ejemplo) reemplaza el bucle «presiona E» de la misma manera. Comprueba la documentación de ox_lib para las opciones exactas de cada uno.
Comprueba el resultado
Ejecuta resmon 1 nuevamente. Un script arreglado debe sentarse cerca de 0.00 ms cuando te paras lejos de sus lugares, y subir solo cuando estés cerca de ellos. Si sigue siendo alto, busca un segundo bucle en el mismo recurso: a menudo un Wait(0) no es el único.
Cuidado: no establezcas un sueño largo en un bucle que maneja una pulsación de tecla o un dibujo. Si duermes 500 ms y el jugador presiona la tecla, el script la perderá. Duerme solo cuando sepas que nada está pasando, y baja a
Wait(0)cuando algo esté.
Lista de verificación
| Síntoma | Solución |
|---|---|
| Ms alto cuando está inactivo | Encuentra el bucle while true do Wait(0) y añade un sueño basado en distancia |
PlayerPedId() en cada frame |
Cachéalo, o usa cache.ped de ox_lib |
| Comprobaciones de distancia en un bucle | Reemplaza con lib.points.new o lib.zones |
| Búsqueda de entidades cada frame | Ejecútalo una vez por segundo y guarda el resultado |
| Leer datos del jugador en un bucle | Léelo en el evento del framework y almacénalo |
| Pulsaciones de tecla perdidas después de añadir un sueño | Usa Wait(0) solo mientras el jugador esté cerca |
Respuestas rápidas
¿Cuál es un buen valor de resmon para un script?
Un script que está inactivo debe sentarse alrededor de 0.00 a 0.01 ms. Cualquier cosa que permanezca bien por encima de eso cuando no la estés usando tiene un bucle que funciona demasiado duro.
¿Qué hace Wait(0) y por qué es costoso?
Wait(0) ejecuta el bucle una vez cada frame. A 60 frames por segundo eso es 60 ejecuciones por segundo, y cualquier nativo que llames en él es llamado 60 veces por segundo.
¿Necesito ox_lib para reparar ms alto?
No. Las soluciones funcionan en Lua simple. ox_lib solo las acorta, con cache.ped, lib.points y lib.zones.
Scripts que evitan este problema
CCTV Security CamerasCámaras colocables, una tablet con vista múltiple en vivo y fotos como prueba.Ver script →
Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →
Arcade MachinesSiete juegos arcade jugables en máquinas reales, con clasificaciones y apuestas.Ver script →