Отладка FiveM NUI: nui_devtools, ошибки консоли и неудачные обратные вызовы
Отладьте FiveM NUI: откройте Chromium devtools с nui_devtools, прочитайте ошибки Uncaught TypeError, исправьте неудачную выборку в https://resource/cb и протестируйте пользовательский интерфейс в браузере.
Ваш NUI открывается как пустая панель, кнопка ничего не делает, или появляется курсор, но экран не следует. Обычно нет ошибки Lua, потому что проблема на веб-странице. Вам нужна консоль браузера, и у FiveM она есть. Это руководство объясняет, как её открыть, как читать её ошибки и как протестировать ваш пользовательский интерфейс без игры.
Откройте devtools: nui_devtools
NUI — это страница Chromium внутри игры. Нажмите F8, чтобы открыть консоль FiveM и запустите:
nui_devtoolsОкно devtools откроется для слоя NUI, как то, что вы знаете из браузера. Используйте эти вкладки:
- Console: ошибки JavaScript и ваши собственные строки
console.log. - Network: каждый запрос, который делает страница, включая обратные вызовы к Lua.
- Elements: живой HTML и CSS. Используйте его, чтобы увидеть, существует ли ваш элемент, насколько он большой и скрыт ли он.
- Sources: устанавливайте точки разрыва в вашем скрипте.
Внимание: доступность
nui_devtoolsзависит от ваших настроек и версии клиента, которую вы запускаете. Если команда ничего не делает, убедитесь, что ваш игровой клиент обновлён, и протестируйте пользовательский интерфейс в обычном браузере, как показано ниже.
Если ваш пользовательский интерфейс видимый только после SendNUIMessage, откройте devtools сначала и запустите действие потом, чтобы вы видели прибывающие сообщения.
Прочитайте ошибки консоли
Ошибки на вкладке Console показывают файл и строку вашего скрипта. Те, которые вы будете видеть чаще всего:
Uncaught TypeError: Cannot read properties of undefined (reading 'items')Ваш код прочитал .items на чём-то, что undefined. В NUI это почти всегда исходит от сообщения:
window.addEventListener('message', (event) => {
const { action, data } = event.data
if (action === 'open') {
render(data.items) // data is undefined
}
})Проверьте, что действительно отправила Lua. Сначала распечатайте всё сообщение:
window.addEventListener('message', (event) => {
console.log('NUI message', JSON.stringify(event.data))
})Затем сравните это с вызовом Lua:
SendNUIMessage({ action = 'open', data = { items = items } })Ключи должны совпадать ровно, включая регистр. Поле, установленное в nil в Lua, отсутствует в сообщении, поэтому оно undefined в JavaScript.
Другие частые ошибки:
| Сообщение консоли | Обычная причина |
|---|---|
Uncaught ReferenceError: x is not defined |
Файл скрипта не загрузился, или опечатка в имени |
Uncaught SyntaxError |
Сломанный файл скрипта, или выходные данные бандлера с неправильным путём |
Failed to load resource: 404 |
Файл не указан в files в fxmanifest, или путь неправильный |
Uncaught (in promise) TypeError: Failed to fetch |
Запрос обратного вызова не удался, смотрите ниже |
Если на вкладке Network показано 404 для вашего JS, CSS или изображений, добавьте каждый файл, загружаемый страницей, в files в манифесте и укажите ui_page на правильный HTML:
ui_page 'web/index.html'
files {
'web/index.html',
'web/**/*',
}Для сборки Vite или React используйте папку вывода, смотрите FiveM NUI с React и Vite.
Неудачная выборка в https://resource/cb
NUI отправляет сообщения Lua с запросом в https://<resource name>/<callback name>:
fetch(`https://${GetParentResourceName()}/close`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({}),
})На вкладке Network неудачный запрос показан красным:
POST https://my_script/close net::ERR_FAILEDПроверьте эти пункты по порядку:
- Обратный вызов не зарегистрирован. Имя после слеша должно совпадать с
RegisterNUICallbackна клиенте, ровно:
RegisterNUICallback('close', function(data, cb)
SetNuiFocus(false, false)
cb('ok')
end)- Имя ресурса неправильное. Хост в URL — это имя папки ресурса. Если вы переименовали папку, жёстко закодированный
https://old_name/closeне работает. ИспользуйтеGetParentResourceName()на странице, как выше, чтобы имя следовало за папкой. - Обратный вызов никогда не ответит. Всегда вызывайте
cb(...), даже сcb('ok'). Обработчик, который возвращается без вызова, оставляет запрос в ожидании, и страница может ждать вечно. - Обработчик Lua ошибается до
cb. Проверьте консоль F8 на ошибку скрипта в тот же момент. Ошибка доcbозначает, что ответ никогда не отправляется. - Ресурс не запущен. Обратные вызовы существуют так долго, как клиентский скрипт, который их зарегистрировал.
Фокус и курсор
Если пользовательский интерфейс показан, но его не удаётся щёлкнуть, или мышь зависает после закрытия, проблема в SetNuiFocus, а не на странице. Смотрите NUI focus stuck cursor.
Протестируйте пользовательский интерфейс в обычном браузере
Отладка в игре медленная. Большую часть NUI можно протестировать в браузере с живой перезагрузкой вашего редактора.
Откройте index.html через локальный сервер или запустите npm run dev для проекта Vite. Затем заглушите две вещи, которые игра обычно предоставляет.
Сначала, поддельный GetParentResourceName и обратные вызовы, которые не могут не пройти:
if (!window.GetParentResourceName) {
window.GetParentResourceName = () => 'my_script'
window.fetch = async (url, options) => {
console.log('NUI callback', url, options && options.body)
return { ok: true, json: async () => ({}) }
}
}Во-вторых, отправляйте сообщения, которые отправила бы Lua. Из консоли браузера или кнопки только для разработки:
window.postMessage({ action: 'open', data: { items: [{ name: 'water', count: 3 }] } }, '*')Это вызывает ваш слушатель message ровно так же, как SendNUIMessage. Вы можете проектировать, исправлять макет и проверять обработку данных в браузере, и держать игру для финальной проверки фокуса, реальных данных и реальных обратных вызовов.
Совет: удалите заглушки из выпускной сборки или оберните их так, чтобы они запускались только при открытии страницы вне игры, как выше с
ifнаGetParentResourceName.
Контрольный список
| Симптом | Решение |
|---|---|
| Пустой NUI | Откройте nui_devtools, прочитайте вкладки Console и Network |
nui_devtools ничего не делает |
Обновите клиент и проверьте ваши настройки; протестируйте в обычном браузере |
Uncaught TypeError ... of undefined |
Зарегистрируйте event.data и совпадите ключи, отправленные SendNUIMessage |
| 404 для файла | Указайте его в files и проверьте ui_page |
POST https://resource/name не работает |
Зарегистрируйте обратный вызов с RegisterNUICallback и используйте точное имя |
| Неправильное имя ресурса в URL | Используйте GetParentResourceName() |
| Кнопка работает, ничего не происходит в Lua | Убедитесь, что обратный вызов вызывает cb('ok') |
| Курсор зависает после закрытия | Вызовите SetNuiFocus(false, false) |
Короткие ответы
Как открыть devtools для FiveM NUI?
Откройте консоль F8 в игре и запустите nui_devtools. Окно Chromium devtools откроется для слоя NUI. Доступность может зависеть от ваших настроек и версии клиента.
Почему мой обратный вызов NUI не работает?
Запрос к https://resource_name/callback не достиг Lua. Обратный вызов не зарегистрирован с помощью RegisterNUICallback, имя ресурса в URL неправильное, или обратный вызов никогда не ответит с cb.
Могу ли я протестировать мой NUI без запуска игры?
Да. Откройте страницу в обычном браузере или запустите dev сервер Vite, отправляйте фальшивые сообщения с window.postMessage и заглушите обратные вызовы. Только реальная игра даёт вам фокус, реальные данные и реальные обратные вызовы.
Скрипты без этой проблемы
Mic PhoneСкладной телефон, который раскладывается в планшет и работает и на настоящем телефоне игрока.Смотреть скрипт →
Arcade MachinesСемь аркадных игр в настоящих автоматах, с таблицами рекордов и ставками.Смотреть скрипт →
CCTV Security CamerasУстанавливаемые камеры, планшет с мультиэкраном в реальном времени и распечатанные фото-улики.Смотреть скрипт →