Depurar NUI en FiveM: nui_devtools, errores de consola y callbacks fallidos
Depura una NUI en FiveM: abre herramientas de desarrollador de Chromium con nui_devtools, lee errores de Uncaught TypeError, corrige una búsqueda fallida a https://resource/cb y prueba la UI en un navegador.
Tu NUI se abre como un panel en blanco, un botón no hace nada, o el cursor aparece y no hay pantalla. Generalmente no hay error de Lua, porque la falla está en la página web. Necesitas la consola del navegador, y FiveM tiene una. Esta guía cubre cómo abrirla, cómo leer sus errores y cómo probar tu UI sin el juego.
Abre las herramientas: nui_devtools
NUI es una página de Chromium dentro del juego. Presiona F8 para abrir la consola de FiveM y ejecuta:
nui_devtoolsSe abre una ventana de herramientas de desarrollador para la capa NUI, como la que conoces de un navegador. Usa estas pestañas:
- Console: Errores de JavaScript y tus propias líneas de
console.log. - Network: cada solicitud que hace la página, incluyendo los callbacks a Lua.
- Elements: el HTML y CSS en vivo. Úsalo para ver si tu elemento existe, cuán grande es y si está oculto.
- Sources: establece puntos de quiebre en tu script.
Cuidado: si
nui_devtoolsestá disponible depende de tus configuraciones y de la compilación del cliente que ejecutes. Si el comando no hace nada, verifica que tu cliente de juego esté actualizado, y prueba la UI en un navegador normal como se muestra a continuación.
Si tu UI es visible solo después de un SendNUIMessage, abre las herramientas de desarrollador primero y dispara la acción después, para que veas los mensajes que llegan.
Lee los errores de la consola
Los errores en la pestaña Console muestran el archivo y la línea de tu script. Los que verás con más frecuencia:
Uncaught TypeError: Cannot read properties of undefined (reading 'items')Tu código leyó .items en algo que es undefined. En NUI esto casi siempre viene del mensaje:
window.addEventListener('message', (event) => {
const { action, data } = event.data
if (action === 'open') {
render(data.items) // data is undefined
}
})Verifica qué realmente envió Lua. Imprime todo el mensaje primero:
window.addEventListener('message', (event) => {
console.log('NUI message', JSON.stringify(event.data))
})Luego compáralo con la llamada de Lua:
SendNUIMessage({ action = 'open', data = { items = items } })Las claves deben coincidir exactamente, incluyendo mayúsculas. Un campo establecido a nil en Lua falta del mensaje, por lo que es undefined en JavaScript.
Otros errores comunes:
| Mensaje de consola | Causa usual |
|---|---|
Uncaught ReferenceError: x is not defined |
Un archivo de script no se cargó, o un typo en un nombre |
Uncaught SyntaxError |
Un archivo de script roto, o una salida de bundler con la ruta incorrecta |
Failed to load resource: 404 |
Un archivo no está listado en files en el fxmanifest, o la ruta es incorrecta |
Uncaught (in promise) TypeError: Failed to fetch |
Una solicitud de callback falló, véase a continuación |
Si la pestaña Network muestra un 404 para tu JS, CSS o imágenes, añade cada archivo que carga la página a files en el manifest, y apunta ui_page al HTML correcto:
ui_page 'web/index.html'
files {
'web/index.html',
'web/**/*',
}Para una compilación de Vite o React, usa la carpeta de salida, véase FiveM NUI with React and Vite.
Búsqueda fallida a https://resource/cb
NUI envía mensajes a Lua con una solicitud a https://<nombre de recurso>/<nombre de callback>:
fetch(`https://${GetParentResourceName()}/close`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({}),
})En la pestaña Network una solicitud fallida se muestra en rojo:
POST https://my_script/close net::ERR_FAILEDVerifica estos en orden:
- El callback no está registrado. El nombre después de la barra debe coincidir con un
RegisterNUICallbacken el cliente, exactamente:
RegisterNUICallback('close', function(data, cb)
SetNuiFocus(false, false)
cb('ok')
end)- El nombre del recurso es incorrecto. El host en la URL es el nombre de la carpeta del recurso. Si renombraste la carpeta, un
https://old_name/closecodificado falla. UsaGetParentResourceName()en la página, como arriba, para que el nombre siga la carpeta. - El callback nunca responde. Siempre llama a
cb(...), incluso concb('ok'). Un controlador que retorna sin llamarla deja la solicitud pendiente, y la página puede esperar para siempre. - El controlador de Lua genera un error antes de
cb. Verifica la consola F8 por un error de script en el mismo momento. Un error antes decbsignifica que la respuesta nunca se envía. - El recurso no se está ejecutando. Los callbacks viven mientras el script del cliente que los registró se está ejecutando.
Enfoque y el cursor
Si la UI se muestra pero no se puede hacer clic, o el mouse permanece atrapado después de cerrar, el problema es SetNuiFocus, no la página. Véase NUI focus stuck cursor.
Prueba la UI en un navegador normal
Depurar en el juego es lento. La mayoría de una NUI se puede probar en un navegador, con la recarga en vivo de tu editor.
Abre index.html a través de un servidor local, o ejecuta npm run dev para un proyecto de Vite. Luego simula las dos cosas que el juego normalmente proporciona.
Primero, un GetParentResourceName falso, y callbacks que no fallan:
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 () => ({}) }
}
}Segundo, envía los mensajes que Lua enviaría. Desde la consola del navegador, o un botón solo de desarrollo:
window.postMessage({ action: 'open', data: { items: [{ name: 'water', count: 3 }] } }, '*')Esto llama tu listener de message exactamente como lo hace SendNUIMessage. Puedes diseñar, corregir la disposición y verificar el manejo de datos en el navegador, y mantener el juego para la verificación final del enfoque, datos reales y callbacks reales.
Consejo: elimina los stubs de la compilación de producción, o envuélvelos para que solo se ejecuten cuando la página se abre fuera del juego, como arriba con el
ifenGetParentResourceName.
Lista de verificación
| Síntoma | Solución |
|---|---|
| NUI en blanco | Abre nui_devtools, lee las pestañas Console y Network |
nui_devtools no hace nada |
Actualiza el cliente y verifica tus configuraciones; prueba en un navegador normal |
Uncaught TypeError ... of undefined |
Registra event.data y coincide con las claves enviadas por SendNUIMessage |
| 404 para un archivo | Listalo en files y verifica ui_page |
POST https://resource/name falla |
Registra el callback con RegisterNUICallback y usa exactamente el mismo nombre |
| Nombre de recurso incorrecto en la URL | Usa GetParentResourceName() |
| El botón funciona, nada sucede en Lua | Asegúrate de que el callback llame a cb('ok') |
| Cursor atrapado después de cerrar | Llama a SetNuiFocus(false, false) |
Respuestas rápidas
¿Cómo abro las herramientas de desarrollador para una NUI en FiveM?
Abre la consola F8 en el juego y ejecuta nui_devtools. Se abre una ventana de herramientas de desarrollador de Chromium para la capa NUI. La disponibilidad puede depender de tus configuraciones y compilación del cliente.
¿Por qué falla mi callback de NUI?
La solicitud a https://resource_name/callback no llegó a Lua. El callback no está registrado con RegisterNUICallback, el nombre del recurso en la URL es incorrecto, o el callback nunca responde con cb.
¿Puedo probar mi NUI sin iniciar el juego?
Sí. Abre la página en un navegador normal o ejecuta el servidor dev de Vite, envía mensajes falsos con window.postMessage, y simula los callbacks. Solo el juego real te da enfoque, datos reales y callbacks reales.
Scripts que evitan este problema
Mic PhoneUn móvil plegable que se abre en tablet y llega al móvil real del jugador.Ver script →
Arcade MachinesSiete juegos arcade jugables en máquinas reales, con clasificaciones y apuestas.Ver script →
CCTV Security CamerasCámaras colocables, una tablet con vista múltiple en vivo y fotos como prueba.Ver script →