FiveM resmon wysoki ms: jak znaleźć i naprawić wolne skrypty

Zasób pokazuje wysoki ms w resmon? Jak czytać resmon 1, dlaczego pętle Wait(0) kosztują tyle, i jak spać, gdy daleko, cache ped i używaj ox_lib points i zones.

Otwierasz monitor zasobów i jeden skrypt pokazuje to:

text
my_script        0.35 ms

Bezczynny skrypt powinien być blisko zera. Skrypt, który zjada trzecią część milisekundy, lub znacznie więcej, na każdej klatce sprawia, że gra się zacinza, a gracze z słabszymi komputerami czują to najpierw. Ten przewodnik pokazuje, jak zobaczyć, który zasób jest problemem i zmiany, które go obniżają.

Otwórz monitor zasobów

W konsoli F8 gry wpisz:

text
resmon 1

Nakładka pokazuje każdy zasób klienta z jego czasem CPU (ms) na klatkę i jego pamięcią. Wpisz resmon 0 aby go zamknąć. Sprawdzaj te rzeczy:

  • Stań nieruchomo, w cichym miejscu i przeczytaj listę. Liczby, które mają znaczenie, to te, które pozostają wysokie, gdy nic nie robisz.
  • Spójrz na kto jest na górze. Zasób, który idzie w górę tylko blisko jego własnego znacznika lub sklepu, jest normalne. Jeden, który jest wysoki wszędzie, nie jest.
  • Obserwuj to kilka sekund. Pojedynczy pik, gdy skrypt się uruchamia, jest nieszkodliwy; stała wartość to problem.

ms to czas na kliencie. Wydajność serwera to osobny temat: zobacz server thread hitch warning.

Przyczyna 1: pętla z Wait(0)

Najpopularniejszym powodem wysokiej wartości jest pętla uruchamiająca się na każdej klatce cały czas:

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)

To uruchamia natives 60 razy na sekundę, nawet gdy gracz jest po drugiej stronie mapy. Większość czasu odpowiedź to „nic do zrobienia" i ten koszt jest marnotrawiący.

Naprawa 1: śpij, gdy jesteś daleko

Pozwól pętli spać dłużej, gdy nic nie jest blisko, i uruchamiaj się tylko na każdej klatce, gdy gracz jest blisko:

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)

Pętla sprawdza raz na sekundę, gdy jesteś daleko, co kosztuje prawie nic, i uruchamia się na każdej klatce tylko w obszarze 10 metrów, gdzie rysuje. Użyj #(a - b) z wartościami vec3 dla odległości: jest to szybsze niż stary native GetDistanceBetweenCoords.

Naprawa 2: cache wartości, które ponownie używasz

Wezwanie native na każdej klatce, aby uzyskać wartość, która rzadko się zmienia, jest marnotrawieniem. PlayerPedId() jest klasycznym. Przechowuj ją raz i odświeżaj tylko, gdy może się zmienić:

lua
local ped = PlayerPedId()

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

Jeśli używasz ox_lib, to robi to za ciebie. cache.ped jest utrzymywany na bieżąco, a cache.vehicle i cache.serverId działają w ten sam sposób:

lua
local coords = GetEntityCoords(cache.ped)

lib.onCache pozwala ci zareagować, gdy zmienia się buforowana wartość, bez sprawdzania w pętli.

Naprawa 3: przestań wezywać natives na każdej klatce

Sprawdź treść pętli i poproś dla każdej linii: czy to naprawdę musi uruchamiać się na każdej klatce? Przesuń to co nie musi.

  • Rysowanie (tekst, znaczniki, sprite) musi działać na każdej klatce, ale tylko gdy jest widoczne.
  • Czytanie danych (praca, pieniądze, inventorz) nie musi: przeczytaj je na zdarzeniu i przechowaj w zmiennej.
  • Wyszukiwanie (GetClosestVehicle, GetGamePool, pętle po wszystkich graczach) jest drogie. Uruchom je raz na sekundę lub dwie, nie na każdej klatce.
  • Nie twórz rzeczy w pętli: tworzenie blipów, wpisów tekstowych lub tabel na każdej klatce wypełnia pamięć i sprawia, że kolektor śmieci pracuje.
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)

Naprawa 4: użyj ox_lib points i zones zamiast pętli

Większość pętli „czy jestem blisko tego miejsca" nie jest potrzebna. ox_lib może dla ciebie zrobić pracę odległości i uruchamia tylko twój kod, gdy ma to znaczenie.

Punkt wezwija funkcję, gdy wejdziesz lub opuścisz promień, i jeden na każdej klatce tylko, gdy jesteś w środku:

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

Strefy robią to samo dla kształtów takich jak kula, pudło lub wielokąt:

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

Do interakcji z encjami i miejscami, zasób docelowy (ox_target, na przykład) zastępuje pętlę „naciśnij E" w ten sam sposób. Sprawdzaj dokumentację ox_lib dla dokładnych opcji każdego.

Sprawdzaj wynik

Uruchom resmon 1 ponownie. Naprawiony skrypt powinien siedzeć blisko 0.00 ms, gdy stoisz daleko od jego miejsc i rośnie tylko, gdy jesteś blisko nich. Jeśli wciąż jest wysoki, szukaj drugiej pętli w tym samym zasobie: jeden Wait(0) często nie jest jedynym.

Ostrzeżenie: nie ustawiaj długiego snu w pętli obsługującej naciśnięcie klawisza lub rysowanie. Jeśli śpisz 500 ms i gracz naciśnie klawisz, skrypt go pominie. Śpij tylko, gdy wiesz, że nic się nie dzieje, i upuść Wait(0) gdy coś się dzieje.

Lista kontrolna

Symptom Naprawa
Wysoki ms, gdy bezczynny Znajdź pętlę while true do Wait(0) i dodaj sen oparty na odległości
PlayerPedId() na każdej klatce Buforuj to, lub używaj cache.ped z ox_lib
Sprawdzenia odległości w pętli Zastąp za pomocą lib.points.new lub lib.zones
Wyszukiwanie encji na każdej klatce Uruchom raz na sekundę i przechowaj wynik
Czytanie danych gracza w pętli Przeczytaj je na zdarzeniu frameworku i przechowaj
Pominięte naciśnięcia klawiszy po dodaniu snu Używaj Wait(0) tylko gdy gracz jest blisko

Szybkie odpowiedzi

Jaka jest dobra wartość resmon dla skryptu?

Skrypt, który jest bezczynny, powinien siedzeć wokół 0.00 do 0.01 ms. Cokolwiek, co pozostaje dobrze powyżej tego, gdy go nie używasz, ma pętlę, która działa zbyt ciężko.

Co robi Wait(0) i dlaczego jest drogi?

Wait(0) uruchamia pętlę raz na klatkę. Przy 60 klatkach na sekundę to 60 uruchomień na sekundę, i każdy native, który wezwiesz w nim, jest wezwany 60 razy na sekundę.

Czy potrzebuję ox_lib, aby naprawić wysoki ms?

Nie. Naprawy działają w zwykłym Lua. ox_lib tylko je skraca, z cache.ped, lib.points i lib.zones.

Skrypty bez tego problemu

CCTV Security CamerasKamery do rozstawienia, tablet z podglądem wielu kamer na żywo i drukowane zdjęcia jako dowody.Zobacz skrypt →Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →Arcade MachinesSiedem grywalnych gier arcade w prawdziwych automatach, z rankingami i zakładami.Zobacz skrypt →

Czytaj dalej