FiveM resmon ms alto: come trovare e correggere gli script lenti

Una risorsa mostra ms alto in resmon? Come leggere resmon 1, perché i loop Wait(0) costano così tanto, e come dormire quando lontano, cachea il ped e usa punti e zone ox_lib.

Apri il monitor delle risorse e uno script mostra questo:

text
my_script        0.35 ms

Uno script inattivo dovrebbe essere vicino a zero. Uno script che mangia un terzo di un millisecondo, o molto di più, su ogni frame fa stutter il tuo gioco, e i giocatori con computer più deboli lo sentono per primi. Questa guida mostra come vedere quale risorsa è il problema e i cambiamenti che lo riducono.

Apri il monitor delle risorse

Nella console F8 del gioco, digita:

text
resmon 1

Un overlay mostra ogni risorsa client con il suo tempo CPU (ms) per frame e la sua memoria. Digita resmon 0 per chiuderlo. Controlla queste cose:

  • Stai fermo, in un posto tranquillo, e leggi l'elenco. I numeri che contano sono quelli che rimangono alti quando non fai nulla.
  • Guarda chi è in cima. Una risorsa che sale solo vicino al suo marker o negozio è normale. Una che è alta ovunque non lo è.
  • Guardala per alcuni secondi. Un singolo picco quando uno script inizia è innocuo; un valore costante è il problema.

Il ms è il tempo sul client. Le prestazioni del server sono un argomento separato: vedi avvertimento server thread hitch.

Causa 1: un loop con Wait(0)

La ragione più comune per un valore alto è un loop che gira ogni frame, tutto il tempo:

lua
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)

Questo esegue i nativi 60 volte al secondo, anche quando il giocatore è dall'altra parte della mappa. La maggior parte del tempo la risposta è « nulla da fare », e quel costo è sprecato.

Soluzione 1: dormi quando sei lontano

Lascia che il loop dorma più a lungo quando nulla è vicino, e gira solo ogni frame quando il giocatore è vicino:

lua
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)

Il loop controlla una volta al secondo quando sei lontano, che costa quasi nulla, e gira ogni frame solo dentro l'area di 10 metri dove disegna. Usa #(a - b) con valori vec3 per la distanza: è più veloce del nativo più vecchio GetDistanceBetweenCoords.

Soluzione 2: cachea i valori che riusi

Chiamare un nativo ogni frame per ottenere un valore che raramente cambia è uno spreco. PlayerPedId() è il classico. Immagazzinalo una volta e aggiornalo solo quando può cambiare:

lua
local ped = PlayerPedId()

CreateThread(function()
    while true do
        Wait(500)
        ped = PlayerPedId()
    end
end)

Se usi ox_lib, lo fa per te. cache.ped è mantenuto aggiornato, e cache.vehicle e cache.serverId funzionano allo stesso modo:

lua
local coords = GetEntityCoords(cache.ped)

lib.onCache ti permette di reagire quando un valore cacheato cambia, senza controllare in un loop.

Soluzione 3: smetti di chiamare nativi ogni frame

Controlla il corpo del loop e chiediti per ogni riga: davvero ha bisogno di girare ogni frame? Muovi fuori quello che non lo fa.

  • Disegno (testo, marker, sprite) ha bisogno di girare ogni frame, ma solo mentre è visibile.
  • Lettura dati (job, soldi, inventario) non lo fa: leggilo su un evento, e tienilo in una variabile.
  • Ricerca (GetClosestVehicle, GetGamePool, loop su tutti i giocatori) è costosa. Eseguila una volta ogni secondo o due, non ogni frame.
  • Non creare cose in un loop: creare blip, voci di testo o tabelle ogni frame riempie la memoria e fa lavorare il garbage collector.
lua
-- 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)

Soluzione 4: usa punti e zone ox_lib invece di loop

La maggior parte dei loop « sono vicino a questo spot » non sono necessari. ox_lib può fare il lavoro di distanza per te, e esegue il tuo codice solo quando conta.

Un punto chiama una funzione quando entri o esci da un raggio, e uno ogni frame solo mentre sei dentro:

lua
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
end

Le zone fanno lo stesso per forme come una sfera, una scatola o un poligono:

lua
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,
})

Per l'interazione con entità e spot, una risorsa target (ox_target, per esempio) sostituisce il loop « premi E » nello stesso modo. Controlla la documentazione di ox_lib per le opzioni esatte di ognuno.

Controlla il risultato

Esegui resmon 1 di nuovo. Uno script corretto dovrebbe stare vicino a 0.00 ms quando stai lontano dai suoi spot, e salire solo quando sei vicino loro. Se è ancora alto, cerca un secondo loop nella stessa risorsa: un Wait(0) spesso non è l'unico.

Attenzione: non impostare un sonno lungo in un loop che gestisce una pressione di tasto o un disegno. Se dormi 500 ms e il giocatore preme il tasto, lo script lo perderà. Dormi solo quando sai che nulla sta succedendo, e scendi a Wait(0) quando qualcosa lo fa.

Checklist

Sintomo Soluzione
Ms alto quando inattivo Trova il loop while true do Wait(0) e aggiungi un sonno basato sulla distanza
PlayerPedId() in ogni frame Cachea, o usa cache.ped da ox_lib
Controlli di distanza in un loop Sostituisci con lib.points.new o lib.zones
Ricerca di entità ogni frame Eseguila una volta al secondo e tieni il risultato
Lettura dati del giocatore in un loop Leggilo sull'evento del framework e immagazzinalo
Pressioni di tasto perse dopo aver aggiunto un sonno Usa Wait(0) solo mentre il giocatore è vicino

Risposte rapide

Qual è un buon valore resmon per uno script?

Uno script che è inattivo dovrebbe stare intorno a 0.00 a 0.01 ms. Qualsiasi cosa che rimane ben sopra quello quando non la stai usando ha un loop che funziona troppo forte.

Cosa fa Wait(0) e perché è costoso?

Wait(0) esegue il loop una volta ogni frame. A 60 frame al secondo sono 60 esecuzioni al secondo, e qualsiasi nativo che chiami in esso è chiamato 60 volte al secondo.

Ho bisogno di ox_lib per correggere ms alto?

No. Le correzioni funzionano in Lua semplice. ox_lib solo le rende più corte, con cache.ped, lib.points e lib.zones.

Script senza questo problema

CCTV Security CamerasTelecamere posizionabili, un tablet multi-vista in diretta e foto stampate come prove.Vedi script →Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →Arcade MachinesSette giochi arcade giocabili in cabinati veri, con classifiche e scommesse.Vedi script →

Continua a leggere