FiveM resmon high ms: como encontrar e corrigir scripts lentos
Um recurso mostra high ms em resmon? Como ler resmon 1, por que Wait(0) loops custam tanto, e como dormir quando longe, cache do ped e usar ox_lib points e zones.
Você abre o resource monitor e um script mostra isso:
my_script 0.35 msUm script idle deve estar perto de zero. Um script que come um terço de um milissegundo, ou muito mais, em cada frame faz seu jogo stutterar, e os jogadores com computadores mais fracos sentem primeiro. Este guia mostra como ver qual recurso é o problema e as mudanças que o trazem para baixo.
Abra o resource monitor
No console F8 do jogo, digite:
resmon 1Uma overlay mostra cada recurso do cliente com seu tempo de CPU (ms) por frame e sua memória. Digite resmon 0 para fechá-la. Verifique essas coisas:
- Fica em pé, em um lugar quiet, e leia a lista. Os números que importam são os que ficam altos quando você não faz nada.
- Olhe para quem está no topo. Um recurso que sobe apenas perto de seu próprio marker ou shop é normal. Um que é alto em todos os lugares não é.
- Assista alguns segundos. Um único pico quando um script começa é inofensivo; um valor constante é o problema.
O ms é tempo no cliente. Performance do server é um tópico separado: veja server thread hitch warning.
Causa 1: um loop com Wait(0)
A razão mais comum para um valor alto é um loop que roda cada frame, o tempo todo:
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)Isso roda os natives 60 vezes por segundo, mesmo quando o jogador está no outro lado do mapa. A maioria do tempo a resposta é "nada a fazer", e aquele custo é desperdiçado.
Solução 1: durma quando você está longe
Deixe o loop dormir mais quando nada está perto, e roda cada frame apenas quando o jogador está perto:
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)O loop checa uma vez por segundo quando você está longe, que custa quase nada, e roda cada frame apenas dentro da área de 10 metro onde desenha. Use #(a - b) com valores vec3 para a distância: é mais rápido que o native antigo GetDistanceBetweenCoords.
Solução 2: cache valores que você reutiliza
Chamar um native cada frame para pegar um valor que raramente muda é um desperdício. PlayerPedId() é o clássico. Armazene uma vez e atualize apenas quando pode mudar:
local ped = PlayerPedId()
CreateThread(function()
while true do
Wait(500)
ped = PlayerPedId()
end
end)Se você usa ox_lib, ele faz isso para você. cache.ped é mantido atualizado, e cache.vehicle e cache.serverId funcionam da mesma forma:
local coords = GetEntityCoords(cache.ped)lib.onCache deixa você reagir quando um valor em cache muda, sem checar em um loop.
Solução 3: pare de chamar natives cada frame
Verifique o corpo do loop e pergunte para cada linha: isso realmente tem que rodar cada frame? Mova o que não.
- Drawing (texto, markers, sprites) tem que rodar cada frame, mas apenas enquanto é visível.
- Lendo dados (job, dinheiro, inventory) não: leia em um evento, e mantenha em uma variável.
- Procurando (
GetClosestVehicle,GetGamePool, loops sobre todos os jogadores) é caro. Execute uma vez por segundo ou dois, não cada frame. - Não crie coisas em um loop: criar blips, text entries ou tabelas cada frame preenche memória e faz o garbage collector trabalhar.
-- 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)Solução 4: use ox_lib points e zones em vez de loops
A maioria dos loops "estou perto deste spot" não são necessários. ox_lib pode fazer o trabalho de distância para você, e apenas roda seu código quando importa.
Um point chama uma função quando você entra ou deixa um raio, e um cada frame apenas enquanto você está 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
endZones fazem o mesmo para formas como uma esfera, uma box ou um 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 interação com entidades e spots, um recurso de target (ox_target, por exemplo) substitui o loop "press E" do mesmo jeito. Verifique a documentação do ox_lib para as opções exatas de cada um.
Verifique o resultado
Execute resmon 1 novamente. Um script consertado deve ficar perto de 0.00 ms quando você fica longe de seus spots, e suba apenas quando você está perto deles. Se ainda está alto, procure por um segundo loop no mesmo recurso: um Wait(0) frequentemente não é o único.
Atenção: não defina um sleep longo em um loop que lida com uma key press ou um drawing. Se você dorme 500 ms e o jogador pressiona a key, o script a perderá. Durma apenas quando você sabe que nada está acontecendo, e caia para
Wait(0)quando algo está.
Checklist
| Sintoma | Solução |
|---|---|
| High ms quando idle | Encontre o loop while true do Wait(0) e adicione um sleep baseado em distância |
PlayerPedId() em cada frame |
Cache-o, ou use cache.ped de ox_lib |
| Verificações de distância em um loop | Substitua com lib.points.new ou lib.zones |
| Procurando entidades cada frame | Execute uma vez por segundo e mantenha o resultado |
| Lendo dados do jogador em um loop | Leia no evento do framework e armazene |
| Key presses faltando depois de adicionar um sleep | Use Wait(0) apenas enquanto o jogador está perto |
Respostas rápidas
Qual é um bom valor de resmon para um script?
Um script que está idle deve ficar ao redor de 0.00 a 0.01 ms. Qualquer coisa que fica bem acima disso quando você não está usando tem um loop que funciona muito.
O que Wait(0) faz e por que é custoso?
Wait(0) roda o loop uma vez cada frame. A 60 frames por segundo são 60 runs por segundo, e qualquer native que você chama nele é chamado 60 vezes por segundo.
Preciso de ox_lib para corrigir high ms?
Não. As correções funcionam em Lua puro. ox_lib apenas as torna mais curtas, com cache.ped, lib.points e lib.zones.
Scripts sem esse problema
CCTV Security CamerasCâmeras posicionáveis, um tablet com várias telas ao vivo e fotos impressas como prova.Ver script →
Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →
Arcade MachinesSete jogos de fliperama jogáveis em máquinas de verdade, com rankings e apostas.Ver script →