FiveM resmon ms élevé : comment trouver et corriger les scripts lents

Une ressource affiche un ms élevé dans resmon ? Comment lire resmon 1, pourquoi les boucles Wait(0) coûtent autant, et comment dormir loin, mettre en cache le ped et utiliser les points et zones ox_lib.

Vous ouvrez le moniteur de ressources et un script affiche ceci :

text
my_script        0.35 ms

Un script au repos devrait être près de zéro. Un script qui mange un tiers d'une milliseconde, ou bien plus, sur chaque image rend votre jeu saccadé, et les joueurs avec des ordinateurs plus faibles le ressentent en premier. Ce guide montre comment voir quelle ressource est le problème et les changements qui le réduisent.

Ouvrir le moniteur de ressources

Dans la console F8 du jeu, tapez :

text
resmon 1

Une superposition affiche chaque ressource client avec son temps CPU (ms) par image et sa mémoire. Tapez resmon 0 pour le fermer. Vérifiez ces choses :

  • Restez immobile, dans un endroit calme, et lisez la liste. Les nombres qui comptent sont ceux qui restent élevés quand vous ne faites rien.
  • Regardez qui est au top. Une ressource qui monte seulement près de son propre marqueur ou boutique est normal. Une qui est élevée partout ne l'est pas.
  • Regardez pendant quelques secondes. Un pic unique quand un script démarre est inoffensif ; une valeur constante est le problème.

Le ms est le temps sur le client. Les performances du serveur sont un sujet séparé : consultez avertissement de scintillement du thread serveur.

Cause 1 : une boucle avec Wait(0)

La raison la plus courante d'une valeur élevée est une boucle qui s'exécute chaque image, tout le temps :

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)

Cela exécute les natives 60 fois par seconde, même quand le joueur est de l'autre côté de la carte. La plupart du temps la réponse est "rien à faire", et ce coût est gaspillé.

Correction 1 : dormir quand vous êtes loin

Laissez la boucle dormir plus longtemps quand rien n'est proche, et exécutez seulement chaque image quand le joueur est près :

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)

La boucle vérifie une fois par seconde quand vous êtes loin, ce qui coûte presque rien, et s'exécute chaque image uniquement dans la zone de 10 mètres où elle se dessine. Utilisez #(a - b) avec des valeurs vec3 pour la distance : c'est plus rapide que la native GetDistanceBetweenCoords plus ancienne.

Correction 2 : mettre en cache les valeurs que vous réutilisez

Appeler une native à chaque image pour obtenir une valeur qui change rarement est un gaspillage. PlayerPedId() est le classique. Enregistrez-le une fois et rafraîchissez-le seulement quand cela peut changer :

lua
local ped = PlayerPedId()

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

Si vous utilisez ox_lib, il le fait pour vous. cache.ped est tenu à jour, et cache.vehicle et cache.serverId fonctionnent de la même façon :

lua
local coords = GetEntityCoords(cache.ped)

lib.onCache vous permet de réagir quand une valeur en cache change, sans vérifier dans une boucle.

Correction 3 : arrêter d'appeler les natives chaque image

Vérifiez le corps de la boucle et demandez pour chaque ligne : est-ce que cela doit vraiment s'exécuter chaque image ? Déplacez ce qui ne le fait pas.

  • Dessin (texte, marqueurs, sprites) doit s'exécuter chaque image, mais seulement pendant qu'il est visible.
  • Lire les données (travail, argent, inventaire) ne le fait pas : lisez-le sur un événement, et gardez-le dans une variable.
  • Chercher (GetClosestVehicle, GetGamePool, boucles sur tous les joueurs) est coûteux. Exécutez-le une fois par seconde ou deux, pas chaque image.
  • Ne créez pas de choses dans une boucle : créer des blips, des entrées de texte ou des tables chaque image remplit la mémoire et fait travailler le collecteur de déchets.
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)

Correction 4 : utiliser les points et zones ox_lib à la place des boucles

La plupart des boucles "suis-je près de ce point" ne sont pas nécessaires. ox_lib peut faire le travail de distance pour vous, et n'exécute votre code que quand cela compte.

Un point appelle une fonction quand vous entrez ou quittez un rayon, et une chaque image uniquement pendant que vous êtes à l'intérieur :

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

Les zones font la même chose pour les formes comme une sphère, une boîte ou un polygone :

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

Pour l'interaction avec les entités et les spots, une ressource cible (ox_target, par exemple) remplace la boucle "appuyez sur E" de la même façon. Vérifiez la documentation ox_lib pour les options exactes de chacun.

Vérifiez le résultat

Exécutez resmon 1 à nouveau. Un script corrigé devrait s'asseoir près de 0,00 ms quand vous restez loin de ses spots, et augmenter seulement quand vous êtes près d'eux. S'il est toujours élevé, cherchez une deuxième boucle dans la même ressource : un Wait(0) n'est souvent pas le seul.

Attention : n'utilisez pas une boucle de sommeil longue qui gère une pression de touche ou un dessin. Si vous dormez 500 ms et que le joueur appuie sur la touche, le script la ratera. Dormez seulement quand vous savez que rien ne se passe, et descendez à Wait(0) quand quelque chose l'est.

Liste de contrôle

Symptôme Correction
Ms élevé quand inactif Trouvez la boucle while true do Wait(0) et ajoutez une mise en veille basée sur la distance
PlayerPedId() dans chaque image Mettez-le en cache, ou utilisez cache.ped d'ox_lib
Vérifications de distance dans une boucle Remplacez avec lib.points.new ou lib.zones
Recherche d'entités chaque image Exécutez-la une fois par seconde et gardez le résultat
Lecture des données du joueur dans une boucle Lisez-la sur l'événement du framework et enregistrez-la
Pressions de touches manquées après l'ajout d'une mise en veille Utilisez Wait(0) uniquement pendant que le joueur est près

Réponses rapides

Quelle est une bonne valeur resmon pour un script ?

Un script qui est au repos devrait s'asseoir autour de 0,00 à 0,01 ms. Tout ce qui reste bien au-dessus cela quand vous ne l'utilisez pas a une boucle qui fonctionne trop fort.

Qu'est-ce que Wait(0) fait et pourquoi c'est coûteux ?

Wait(0) exécute la boucle une fois par image. À 60 images par seconde, cela représente 60 exécutions par seconde, et chaque native que vous appelez est appelée 60 fois par seconde.

Ai-je besoin d'ox_lib pour corriger le ms élevé ?

Non. Les corrections fonctionnent en Lua simple. ox_lib seulement les rend plus courts, avec cache.ped, lib.points et lib.zones.

Des scripts sans ce problème

CCTV Security CamerasDes caméras à placer, une tablette multi-vues en direct et des photos imprimées comme preuves.Voir le script →Advanced BoostingDu boosting de véhicules piloté par tablette : contrats de classe D à S+, crews et file d’attente en direct.Voir le script →Arcade MachinesSept jeux d’arcade jouables dans de vraies bornes, avec classements et paris.Voir le script →

À lire aussi