FiveM resmon высокие мс: как найти и исправить медленные скрипты
Ресурс показывает высокие мс в resmon? Как читать resmon 1, почему циклы Wait(0) стоят так дорого и как спать далеко, кешировать ped и использовать ox_lib points и zones.
Вы открываете монитор ресурсов и один скрипт показывает это:
my_script 0.35 msНеработающий скрипт должен быть близко к нулю. Скрипт, который съедает треть миллисекунды или намного больше на каждом кадре, делает вашу игру рывковой, и игроки с более слабыми компьютерами чувствуют это в первую очередь. Это руководство показывает, как увидеть, какой ресурс является проблемой и какие изменения приносят его вниз.
Откройте монитор ресурсов
В консоли F8 игры введите:
resmon 1Оверлей показывает каждый ресурс клиента со своим временем CPU (мс) на кадр и его памятью. Введите resmon 0 чтобы закрыть его. Проверьте эти вещи:
- Стойте неподвижно в спокойном месте и читайте список. Числа, которые имеют значение, — это те, которые остаются высокими, когда вы ничего не делаете.
- Посмотрите кто находится в верхней части. Ресурс, который увеличивается только рядом с его маркером или магазином, нормален. Один, который высокий везде, нет.
- Смотрите его несколько секунд. Единственный пик, когда скрипт запускается, безвреден; постоянное значение — это проблема.
мс — это время на клиенте. Производительность сервера — это отдельная тема: смотрите серверное предупреждение о задержке потока.
Причина 1: цикл с Wait(0)
Наиболее распространенная причина высокого значения — это цикл, который работает на каждом кадре, все время:
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)Это запускает встроенные функции 60 раз в секунду, даже когда игрок находится на другой стороне карты. Большую часть времени ответ — это «ничего не делать» и эта стоимость потеряна впустую.
Исправление 1: спите далеко
Позвольте циклу спать дольше, когда ничего не близко, и работайте только на каждом кадре, когда игрок рядом:
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)Цикл проверяет один раз в секунду, когда вы далеко, что стоит почти ничего, и работает на каждом кадре только в 10 метровой области, где он рисует. Используйте #(a - b) со значениями vec3 для расстояния: это быстрее, чем старший встроенный GetDistanceBetweenCoords.
Исправление 2: кешируйте значения, которые вы повторно используете
Вызов встроенной функции на каждом кадре для получения значения, которое редко изменяется — это потеря. PlayerPedId() — это классический. Сохраните его один раз и обновляйте его только когда это может измениться:
local ped = PlayerPedId()
CreateThread(function()
while true do
Wait(500)
ped = PlayerPedId()
end
end)Если вы используете ox_lib, это делает это за вас. cache.ped поддерживается в актуальном состоянии, и cache.vehicle и cache.serverId работают одинаково:
local coords = GetEntityCoords(cache.ped)lib.onCache позволяет вам реагировать, когда кэшированное значение изменяется, без проверки в цикле.
Исправление 3: остановите вызовы встроенных функций на каждом кадре
Проверьте тело цикла и спросите для каждой строки: должно ли это действительно работать на каждом кадре? Выведите то, что не должно.
- Рисование (текст, маркеры, спрайты) должно работать на каждом кадре, но только пока оно видимо.
- Чтение данных (работа, деньги, инвентарь) нет: прочитайте это на события и держите его в переменной.
- Поиск (
GetClosestVehicle,GetGamePool, циклы над всеми игроками) дорого. Запустите это один раз в одну или две секунды, не на каждом кадре. - Не создавайте вещи в цикле: создание blips, текстовых записей или таблиц на каждом кадре заполняет память и заставляет сборщик мусора работать.
-- 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)Исправление 4: используйте ox_lib points и zones вместо циклов
Большинство циклов «я рядом с этой точкой» не нужны. ox_lib может выполнить работу расстояния за вас и только запускает ваш код, когда это имеет значение.
Точка вызывает функцию, когда вы входите или выходите из радиуса, и одну на каждом кадре только пока вы находитесь внутри:
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Зоны делают то же самое для фигур, таких как сфера, коробка или полигон:
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,
})Для взаимодействия с сущностями и пятнами, целевой ресурс (ox_target, например) заменяет цикл «нажми E» таким же образом. Проверьте документацию ox_lib для точного параметры каждой.
Проверьте результат
Запустите resmon 1 снова. Исправленный скрипт должен сидеть около 0.00 мс, когда вы стоите далеко от его пятен, и подняться только когда вы рядом с ними. Если это все еще высоко, посмотрите для второго цикла в том же ресурсе: один Wait(0) часто не единственный.
Внимание: не устанавливайте долгий сон в цикл, который обрабатывает нажатие клавиши или рисование. Если вы спите 500 мс и игрок нажимает клавишу, скрипт его пропустит. Спите только когда вы знаете, что ничего не происходит, и упадите до
Wait(0)когда что-то происходит.
Контрольный список
| Симптом | Исправление |
|---|---|
| Высокие мс в режиме ожидания | Найдите цикл while true do Wait(0) и добавьте сон на основе расстояния |
PlayerPedId() на каждом кадре |
Кешируйте его или используйте cache.ped из ox_lib |
| Проверки расстояния в цикле | Замените на lib.points.new или lib.zones |
| Поиск сущностей на каждом кадре | Запустите его один раз в секунду и сохраните результат |
| Чтение данных игрока в цикле | Прочитайте это на события фреймворка и сохраните его |
| Пропущенные нажатия клавиш после добавления сна | Используйте Wait(0) только пока игрок рядом |
Короткие ответы
Какое хорошее значение resmon для скрипта?
Неработающий скрипт должен сидеть около 0.00 до 0.01 мс. Все, что остается значительно выше этого, когда вы не используете его, имеет цикл, который работает слишком сильно.
Что делает Wait(0) и почему это дорого?
Wait(0) запускает цикл один раз на кадр. При 60 кадрах в секунду это 60 запусков в секунду, и любой встроенный вызов в нем вызывается 60 раз в секунду.
Нужна ли мне ox_lib для исправления высоких мс?
Нет. Исправления работают в обычном Lua. ox_lib только делает их короче, с cache.ped, lib.points и lib.zones.
Скрипты без этой проблемы
CCTV Security CamerasУстанавливаемые камеры, планшет с мультиэкраном в реальном времени и распечатанные фото-улики.Смотреть скрипт →
Advanced BoostingУгон машин на заказ через планшет: контракты от класса D до S+, команды и живая очередь.Смотреть скрипт →
Arcade MachinesСемь аркадных игр в настоящих автоматах, с таблицами рекордов и ставками.Смотреть скрипт →