Debuguj FiveM NUI: nui_devtools, błędy konsoli i nieudane callback'i

Debuguj FiveM NUI: otwórz devtools Chromium za pomocą nui_devtools, przeczytaj błędy Uncaught TypeError, napraw nieudane pobieranie do https://resource/cb i przetestuj UI w przeglądarce.

Twój NUI otwiera się jako pusta panel, przycisk nic nie robi, lub kursor pojawia się i żaden ekran nie następuje. Zwykle nie ma błędu Lua, ponieważ wina jest w stronie internetowej. Potrzebujesz konsoli przeglądarki, a FiveM ją ma. Ten przewodnik obejmuje jak ją otworzyć, jak przeczytać jej błędy i jak przetestować UI bez gry.

Otwórz devtools: nui_devtools

NUI jest stroną Chromium wewnątrz gry. Wciśnij F8 aby otworzyć konsolę FiveM i uruchom:

text
nui_devtools

Okno devtools otwiera się dla warstwy NUI, takie jak to znasz z przeglądarki. Użyj tych zakładek:

  • Console: Błędy JavaScript i twoje własne linie console.log.
  • Network: każde żądanie które strona wysyła, włącznie z callback'ami do Lua.
  • Elements: żywy HTML i CSS. Użyj go aby zobaczyć czy twój element istnieje, jak duży jest i czy jest ukryty.
  • Sources: ustaw punkty przerwania w twoim skrypcie.

Ostrzeżenie: czy nui_devtools jest dostępny zależy od twoich ustawień i kompilacji klienta którą uruchamiasz. Jeśli polecenie nic nie robi, sprawdź że twój klient gry jest zaktualizowany, i przetestuj UI w normalnej przeglądarce jak pokazano poniżej.

Jeśli twój UI jest widoczny tylko po SendNUIMessage, otwórz devtools najpierw i wyzwól akcję potem, aby zobaczyć wiadomości które docierają.

Przeczytaj błędy konsoli

Błędy w karcie Console pokazują plik i linię twojego skryptu. Te które zobaczysz najczęściej:

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

Twój kod przeczytał .items na czymś to jest undefined. W NUI to prawie zawsze pochodzi z wiadomości:

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

Sprawdź co Lua naprawdę wysłała. Wydrukuj całą wiadomość najpierw:

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

Następnie porównaj to do wołania Lua:

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

Klucze muszą dokładnie pasować, włącznie z wielkością liter. Pole ustawione na nil w Lua brakuje z wiadomości, więc to jest undefined w JavaScript.

Inne czaste błędy:

Wiadomość konsoli Zwykła przyczyna
Uncaught ReferenceError: x is not defined Plik skryptu nie załadował się, lub błąd pisowni w nazwie
Uncaught SyntaxError Uszkodzony plik skryptu, lub wynik bundlera ze złą ścieżką
Failed to load resource: 404 Plik nie jest wymieniony w files w fxmanifest, lub ścieżka jest zła
Uncaught (in promise) TypeError: Failed to fetch Żądanie callback'u nie powiodło się, zobacz poniżej

Jeśli karta Network pokazuje 404 dla twojego JS, CSS lub obrazów, dodaj każdy plik który strona ładuje do files w manifeście, i wskaż ui_page na prawidłowy HTML:

lua
ui_page 'web/index.html'

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

Dla kompilacji Vite lub React, użyj folderu wyjściowego, patrz FiveM NUI with React and Vite.

Nieudane pobieranie do https://resource/cb

NUI wysyła wiadomości do Lua za pomocą żądania do https://<resource name>/<callback name>:

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

W karcie Network nieudane żądanie pokazuje się na czerwono:

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

Sprawdź te w kolejności:

  1. Callback nie jest zarejestrowany. Nazwa po ukośniku musi dokładnie pasować do RegisterNUICallback na kliencie:
lua
RegisterNUICallback('close', function(data, cb)
    SetNuiFocus(false, false)
    cb('ok')
end)
  1. Nazwa zasobu jest zła. Host w URL to nazwa folderu zasobu. Jeśli przemianowałeś folder, hardcoded https://old_name/close nie powiedzie się. Użyj GetParentResourceName() na stronie, jak powyżej, aby nazwa podążyła za folderem.
  2. Callback nigdy nie odpowiada. Zawsze wołaj cb(...), nawet z cb('ok'). Obsługa, która wraca bez wołania go zostawia żądanie oczekujące, a strona może czekać wiecznie.
  3. Obsługa Lua błędów przed cb. Sprawdź konsolę F8 dla błędu skryptu w tym samym momencie. Błąd przed cb oznacza że odpowiedź nigdy nie jest wysłana.
  4. Zasób nie jest uruchomiony. Callback'i żyją tak długo jak skrypt klienta, który je zarejestrował.

Fokus i kursor

Jeśli UI pokazuje ale nie może być klikięty, lub mysz zostaje zablokowana po zamknięciu, problem to SetNuiFocus, nie strona. Patrz NUI focus stuck cursor.

Przetestuj UI w normalnej przeglądarce

Debugowanie w grze jest powolne. Większość NUI może być przetestowana w przeglądarce, z live reload'em twojego edytora.

Otwórz index.html poprzez lokalny serwer, lub uruchom npm run dev dla projektu Vite. Następnie zastępuj dwie rzeczy które gra normalnie dostarcza.

Pierwsza, fałszywy GetParentResourceName, i callback'i które nie zawiodą:

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

Druga, wyślij wiadomości które Lua byłaby wysłała. Z konsoli przeglądarki, lub guzika dev-only:

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

To wołuje twojego nasłuchiwacza message dokładnie jak SendNUIMessage. Możesz projektować, naprawiać układ i sprawdzać obsługę danych w przeglądarce, i trzymać grę dla ostatecznego sprawdzenia fokus, rzeczywistych danych i rzeczywistych callback'i.

Porada: usuń zastępujące z kompilacji produkcji, lub owrap'uj je aby uruchomiły się tylko gdy strona jest otwarta poza grą, jak powyżej z if na GetParentResourceName.

Checklist

Objaw Naprawić
Pusta NUI Otwórz nui_devtools, przeczytaj karty Console i Network
nui_devtools nic nie robi Zaktualizuj klienta i sprawdź ustawienia; przetestuj w normalnej przeglądarce
Uncaught TypeError ... of undefined Zaloguj event.data i dopasuj klucze wysłane przez SendNUIMessage
404 dla pliku Wymień go w files i sprawdź ui_page
POST https://resource/name nie powiedzie się Zarejestruj callback z RegisterNUICallback i użyj dokładnej nazwy
Zła nazwa zasobu w URL Użyj GetParentResourceName()
Przycisk działa, nic się nie dzieje w Lua Upewnij się że callback wołuje cb('ok')
Kursor zablokowany po zamknięciu Wołaj SetNuiFocus(false, false)

Szybkie odpowiedzi

Jak otworzyć devtools dla FiveM NUI?

Otwórz konsolę F8 w grze i uruchom nui_devtools. Okno devtools Chromium otwiera się dla warstwy NUI. Dostępność może zależeć od twoich ustawień i kompilacji klienta.

Dlaczego mój callback NUI nie powiedzie się?

Żądanie do https://resource_name/callback nie osiągnęło Lua. Callback nie jest zarejestrowany z RegisterNUICallback, nazwa zasobu w URL jest zła, lub callback nigdy nie odpowiada z cb.

Czy mogę przetestować mój NUI bez uruchamiania gry?

Tak. Otwórz stronę w normalnej przeglądarce lub uruchom serwer Vite dev, wyślij fałszywe wiadomości za pomocą window.postMessage, i zastępuj callback'i. Tylko prawdziwa gra daje ci fokus, rzeczywiste dane i rzeczywiste callback'i.

Skrypty bez tego problemu

Mic PhoneSkładany telefon, który rozkłada się w tablet i działa też na prawdziwym telefonie gracza.Zobacz skrypt →Arcade MachinesSiedem grywalnych gier arcade w prawdziwych automatach, z rankingami i zakładami.Zobacz skrypt →CCTV Security CamerasKamery do rozstawienia, tablet z podglądem wielu kamer na żywo i drukowane zdjęcia jako dowody.Zobacz skrypt →

Czytaj dalej