Eseguire il debug di FiveM NUI: nui_devtools, errori della console e callback non riusciti

Esegui il debug di una FiveM NUI: apri i devtools di Chromium con nui_devtools, leggi gli errori Uncaught TypeError, correggi un fetch non riuscito a https://resource/cb e testa l'UI in un browser.

La tua NUI si apre come un pannello vuoto, un pulsante non fa nulla, o il cursore appare e nessuna schermata segue. Di solito non c'è un errore Lua, perché il difetto è nella pagina web. Hai bisogno della console del browser, e FiveM ne ha una. Questa guida copre come aprirla, come leggere i suoi errori e come testare la tua UI senza il gioco.

Apri i devtools: nui_devtools

NUI è una pagina Chromium all'interno del gioco. Premi F8 per aprire la console FiveM ed esegui:

text
nui_devtools

Una finestra di devtools si apre per il layer NUI, come quella che conosci da un browser. Usa queste schede:

  • Console: errori di JavaScript e le tue righe console.log.
  • Network: ogni richiesta che la pagina fa, inclusi i callback a Lua.
  • Elements: l'HTML e il CSS live. Usalo per vedere se il tuo elemento esiste, quanto è grande e se è nascosto.
  • Sources: imposta breakpoint nello script.

Attenzione: se nui_devtools è disponibile dipende dalle impostazioni e dalla build del client che esegui. Se il comando non fa nulla, controlla che il tuo game client sia aggiornato, e testa l'UI in un browser normale come mostrato sotto.

Se la tua UI è visibile solo dopo un SendNUIMessage, apri i devtools prima e attiva l'azione dopo, in modo da vedere i messaggi che arrivano.

Leggi gli errori della console

Gli errori nella scheda Console mostrano il file e la riga dello script. Quelli che vedrai più spesso:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'items')

Il tuo codice ha letto .items su qualcosa che è undefined. In NUI questo quasi sempre viene dal messaggio:

js
window.addEventListener('message', (event) => {
  const { action, data } = event.data
  if (action === 'open') {
    render(data.items)   // data is undefined
  }
})

Controlla cosa Lua ha veramente inviato. Stampa l'intero messaggio prima:

js
window.addEventListener('message', (event) => {
  console.log('NUI message', JSON.stringify(event.data))
})

Poi confrontalo con la chiamata Lua:

lua
SendNUIMessage({ action = 'open', data = { items = items } })

Le chiavi devono corrispondere esattamente, inclusa la capitalizzazione. Un campo impostato su nil in Lua manca dal messaggio, quindi è undefined in JavaScript.

Altri errori comuni:

Messaggio della console Causa usuale
Uncaught ReferenceError: x is not defined Un file di script non ha caricato, o un errore di digitazione in un nome
Uncaught SyntaxError Un file di script rotto, o un output del bundler con il percorso sbagliato
Failed to load resource: 404 Un file non è elencato in files nel fxmanifest, o il percorso è sbagliato
Uncaught (in promise) TypeError: Failed to fetch Una richiesta di callback ha fallito, vedi sotto

Se la scheda Network mostra un 404 per il tuo JS, CSS o immagini, aggiungi ogni file che la pagina carica a files nel manifesto, e punta ui_page all'HTML corretto:

lua
ui_page 'web/index.html'

files {
  'web/index.html',
  'web/**/*',
}

Per una build Vite o React, usa la cartella di output, vedi FiveM NUI con React e Vite.

Fetch non riuscito a https://resource/cb

NUI invia messaggi a Lua con una richiesta a https://<resource name>/<callback name>:

js
fetch(`https://${GetParentResourceName()}/close`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({}),
})

Nella scheda Network una richiesta non riuscita è mostrata in rosso:

text
POST https://my_script/close net::ERR_FAILED

Controlla questi in ordine:

  1. Il callback non è registrato. Il nome dopo la barra deve corrispondere a un RegisterNUICallback sul client, esattamente:
lua
RegisterNUICallback('close', function(data, cb)
    SetNuiFocus(false, false)
    cb('ok')
end)
  1. Il nome della risorsa è sbagliato. L'host nell'URL è il nome della cartella della risorsa. Se hai rinominato la cartella, un https://old_name/close hardcoded fallisce. Usa GetParentResourceName() nella pagina, come sopra, così il nome segue la cartella.
  2. Il callback non risponde mai. Chiama sempre cb(...), anche con cb('ok'). Un handler che ritorna senza chiamarlo lascia la richiesta in sospeso, e la pagina può aspettare per sempre.
  3. L'handler Lua errori prima di cb. Controlla la console F8 per un errore di script allo stesso momento. Un errore prima di cb significa che la risposta non è mai inviata.
  4. La risorsa non è in esecuzione. I callback vivono finché lo script client che li ha registrati.

Focus e cursore

Se l'UI mostra ma non può essere cliccata, o il mouse rimane bloccato dopo la chiusura, il problema è SetNuiFocus, non la pagina. Vedi Cursore bloccato di NUI focus.

Testa l'UI in un browser normale

Il debug in gioco è lento. La maggior parte di un NUI può essere testata in un browser, con il live reload del tuo editor.

Apri index.html attraverso un server locale, o esegui npm run dev per un progetto Vite. Poi crea un mock delle due cose che il gioco normalmente fornisce.

Primo, un falso GetParentResourceName, e callback che non falliscono:

js
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 () => ({}) }
  }
}

Secondo, invia i messaggi che Lua invierebbe. Dalla console del browser, o un pulsante solo per sviluppo:

js
window.postMessage({ action: 'open', data: { items: [{ name: 'water', count: 3 }] } }, '*')

Questo chiama il tuo listener message esattamente come SendNUIMessage farebbe. Puoi progettare, correggere il layout e controllare la gestione dei dati nel browser, e mantenere il gioco per il controllo finale di focus, dati reali e callback reali.

Consiglio: rimuovi i mock dalla build di produzione, o avvolgili in modo che vengano eseguiti solo quando la pagina è aperta al di fuori del gioco, come sopra con l'if su GetParentResourceName.

Checklist

Sintomo Soluzione
NUI vuota Apri nui_devtools, leggi le schede Console e Network
nui_devtools non fa nulla Aggiorna il client e controlla le impostazioni; testa in un browser normale
Uncaught TypeError ... of undefined Registra event.data e corrisponde alle chiavi inviate da SendNUIMessage
404 per un file Elencalo in files e controlla ui_page
POST https://resource/name fallisce Registra il callback con RegisterNUICallback e usa il nome esatto
Nome della risorsa sbagliato nell'URL Usa GetParentResourceName()
Il pulsante funziona, nulla accade in Lua Assicurati che il callback chiami cb('ok')
Cursore bloccato dopo la chiusura Chiama SetNuiFocus(false, false)

Risposte rapide

Come apro i devtools per una FiveM NUI?

Apri la console F8 in gioco ed esegui nui_devtools. Una finestra di devtools di Chromium si apre per il layer NUI. La disponibilità può dipendere dalle impostazioni e dalla build del client.

Perché il mio callback NUI fallisce?

La richiesta a https://resource_name/callback non ha raggiunto Lua. Il callback non è registrato con RegisterNUICallback, il nome della risorsa nell'URL è sbagliato, o il callback non risponde mai con cb.

Posso testare la mia NUI senza avviare il gioco?

Sì. Apri la pagina in un browser normale o esegui il server di sviluppo Vite, invia messaggi falsi con window.postMessage, e mock i callback. Solo il gioco vero ti dà il focus, i dati veri e i callback veri.

Script senza questo problema

Mic PhoneUn telefono pieghevole che si apre in un tablet e arriva sul telefono vero del giocatore.Vedi script →Arcade MachinesSette giochi arcade giocabili in cabinati veri, con classifiche e scommesse.Vedi script →CCTV Security CamerasTelecamere posizionabili, un tablet multi-vista in diretta e foto stampate come prove.Vedi script →

Continua a leggere