attempt to call a nil value (field, global, method): jak to naprawić

Otrzymujesz 'attempt to call a nil value' w FiveM? Co oznaczają warianty field, global i method oraz jak naprawić literówkę, brakujący eksport lub błąd dwukropek-kontra-kropka.

W konsoli:

text
SCRIPT ERROR: @my_script/server/main.lua:42: attempt to call a nil value (field 'GetPlayerFromId')
SCRIPT ERROR: @my_script/client/main.lua:17: attempt to call a nil value (global 'DrawText3D')
SCRIPT ERROR: @my_script/client/main.lua:63: attempt to call a nil value (method 'Notify')

Lua mówi ci, że linia próbowała uruchomić funkcję, która nie istnieje. Ten artykuł wyjaśnia trzy warianty, zwyczajne przyczyny i jak naprawić każdą z nich.

Co błąd oznacza

W Lua brakująca nazwa sama w sobie nie jest błędem: przeczytanie jej daje nil. Błąd pojawia się tylko wtedy, gdy umieścisz nawiasy po niej, ponieważ nie możesz uruchomić nil. Tekst w nawiasach mówi, jak skrypt osiągnął brakującą funkcję:

  • attempt to call a nil value (global 'X'): nagie wezwanie, takie jak X(). Funkcja nie jest nigdzie zdefiniowana, gdzie skrypt może widzieć.
  • attempt to call a nil value (field 'X'): wezwanie przez tabelę, takie jak ESX.X() lub QBCore.Functions.X(). Tabela istnieje, ale nie ma wpisu o nazwie X.
  • attempt to call a nil value (method 'X'): wezwanie z dwukropkiem, takie jak obj:X(). Obiekt istnieje, ale nie ma metody X.

Plik i linia na przedzie wiadomości (@my_script/server/main.lua:42) to linia, która robi wezwanie. Jeśli nie jesteś pewien, jak przeczytać resztę wyjścia, przeczytaj jak przeczytać błąd skryptu FiveM.

1. Literówka w nazwie

Lua jest czuła na wielkość liter. GetPlayerFromId i getPlayerFromId to dwie różne nazwy, i podobnie TriggerClientEvent i TriggerclientEvent. Porównaj nazwę w błędzie z dokumentacją frameworku, litera po literze.

2. Funkcja nie istnieje w twojej wersji

Frameworki zmieniają nazwę i usuwają funkcje. To jest najczęstsza przyczyna na skryptach, które były napisane dla innej wersji twojego frameworku.

lua
-- an old call that may be gone on your version
local xPlayer = ESX.GetPlayerFromId(source)
xPlayer.getInventoryItem('bread')

Sprawdź, co twój framework naprawdę oferuje. Wydrukuj tabelę, aby zobaczyć jej wpisy:

lua
for name, value in pairs(ESX) do
    print(name, type(value))
end

Jeśli funkcja, której potrzebujesz, nie jest na liście, skrypt i framework się nie pasują. Zaktualizuj framework, zaktualizuj skrypt, lub zastąp wezwanie tym, który ma twoja wersja.

3. Eksport brakuje

Eksporty to funkcje, które inny zasób dostarcza. Gdy zasób jest zatrzymany, nie powiódł się uruchomić, lub nie eksportuje tej nazwy, wezwanie zawala się.

lua
local core = exports['qb-core']:GetCoreObject()
core.Functions.GetPlayer(source)

Jeśli zasób nie działa, FiveM drukuje No such export. Jeśli działa, ale nazwa eksportu jest zła, możesz skończyć z nil polem. Uruchom zasób pierwszy w server.cfg i sprawdź dokładne nazwy eksportów w jego dokumentacji lub fxmanifest.lua. Dwie powiązane poprawki: ESX jest nil i Brak takiego eksportu getSharedObject.

4. Dwukropek versus kropka

Dwukropek przechodzi obiekt jako ukryty pierwszy argument. Kropka nie. Mieszanie ich daje либо ten błąd, либо złe argumenty.

lua
-- calls the method with the object as first argument
player:Notify('hello')

-- calls a plain function stored in a table
Utils.Notify('hello')

Jeśli błąd mówi (method 'Notify'), obiekt nie ma wpisu Notify: użyj formy z kropką, jeśli funkcja żyje w tabeli biblioteki, lub sprawdź, czy obiekt naprawdę jest tym, co myślisz. Z ox_lib, na przykład, lib.notify({...}) to wezwanie z kropką w tabeli lib.

5. Funkcja jest zdefiniowana później lub w innym pliku

Lokalna funkcja musi być zdefiniowana przed linią, która ją wołuje, w tym samym pliku. Funkcja zdefiniowana w innym pliku jest tylko widoczna, jeśli jest globalna, i tylko jeśli ten plik jest ładowany przez tę samą stronę (klient lub serwer) tego samego zasobu.

lua
-- fails: DoThing is defined below the call
DoThing()

local function DoThing()
    print('hi')
end

Przenieś definicję powyżej wezwania, lub zadeklaruj to najpierw za pomocą local DoThing i przypisz później. Sprawdź też fxmanifest.lua: plik, który nie jest wymieniony w client_scripts, server_scripts lub shared_scripts, nigdy się nie ładuje, więc jego funkcje nigdy nie istnieją.

lua
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }
shared_scripts { '@ox_lib/init.lua', 'config.lua' }

6. Funkcja klienta używana na serwerze, lub odwrotnie

Wiele natives i funkcji frameworku istnieje tylko po jednej stronie. PlayerPedId jest tylko klientem, a GetPlayerIdentifiers jest tylko serwerem. Tabele frameworku również się różnią: ESX.GetPlayerFromId to funkcja serwera, podczas gdy klient używa ESX.GetPlayerData. Skrypt, który działa w shared_scripts, działa po obu stronach, więc wezwanie, które działa po jednej stronie, spada na drugiej.

Porada: najszybszym testem jest print zaraz przed linią niepowodzenia: print(type(ESX.GetPlayerFromId)). Jeśli wypisuje nil, funkcja brakuje. Jeśli wypisuje function, prawdziwy problem jest gdzieś indziej.

Osłoń to, gdy debugujesz

Sprawdzaj, zanim wołasz, abyś otrzymał jasną wiadomość zamiast awarii:

lua
local fn = ESX.GetPlayerFromId
if type(fn) ~= 'function' then
    print('GetPlayerFromId is missing: check the ESX version')
    return
end

Nie pozostawiaj straży, takie jak to, na miejscu jako naprawa. Ukrywają prawdziwy problem, którym jest skrypt i framework, które się nie pasują.

Lista kontrolna

Objaw Naprawa
(global 'X') Funkcja nie jest zdefiniowana w pliku lub nigdy się nie załadowała: sprawdź manifest i kolejność definicji
(field 'X') Tabela nie ma takiego wpisu: sprawdź pisownię i wersję frameworku
(method 'X') Zły obiekt lub dwukropek użyty zamiast kropki: sprawdź, co zawiera zmienna
Działa tylko po jednej stronie Funkcja istnieje tylko na kliencie lub tylko na serwerze
Błąd po aktualizacji frameworku Zastąp usuniętą funkcję nową, lub zaktualizuj skrypt
Wezwanie eksportu zwraca nil Uruchom dostarczający zasób pierwszy i sprawdź nazwę eksportu

Szybkie odpowiedzi

Co oznacza 'attempt to call a nil value'?

Skrypt próbował uruchomić coś jako funkcję, ale nazwa zawiera nil, więc nie ma niczego do uruchomienia. Nazwa wewnątrz nawiasów mówi ci, której funkcji brakuje.

Jaka jest różnica między field, global i method w tym błędzie?

Global to sama nazwa, taka jak Foo(), field to wpis tabeli, taki jak Config.Foo() lub ESX.Foo(), a method to wezwanie z dwukropkiem, takie jak obj:Foo(). To tylko mówi ci, jak brakująca funkcja została osiągnięta.

Czy zła wersja frameworku może to spowodować?

Tak. Skrypt napisany dla starszej lub nowszej ESX, QBCore lub QBox może wywoływać funkcję, którą twoja wersja zmieniła nazwę lub usunęła, co pozostawia nil za sobą.

Skrypty bez tego problemu

Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →Quest CreatorWizualny edytor questów i dialogów z NPC, budowanych węzeł po węźle w grze.Zobacz skrypt →Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →

Czytaj dalej