attempt to index a nil value (local 'Player'): QBCore i QBox naprawa
Player jest nil w twoim skrypcie QBCore lub QBox? Dlaczego QBCore.Functions.GetPlayer(source) zwraca nil, wyszukiwania citizenid tylko dla graczy online i bezpieczne wzory ochrony.
W konsoli serwera:
SCRIPT ERROR: @my_script/server/main.lua:27: attempt to index a nil value (local 'Player')local Player = QBCore.Functions.GetPlayer(source)
Player.Functions.AddMoney('cash', 100) -- Player is nilGetPlayer nie znalazł załadowanego gracza dla tego id i zwrócił nil, a następna linia go indeksowała. Przyczyny odbijają przypadek ESX w ESX xPlayer is nil, z specyficznością QBCore i QBox.
1. Gracz nie jest jeszcze załadowany
Gracz może być połączony, zanim QBCore załaduje jego postać, szczególnie gdy ekran multicharacter jest otwarty. Dopóki postać nie zostanie wybrana, GetPlayer(source) zwraca nil.
Kod, który działa na playerJoining, lub ze wątku, który się natychmiast uruchamia, to trafia. Czekaj na zdarzenie QBCore, które się wypalnia, gdy gracz jest gotów. Na serwerze:
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
print(Player.PlayerData.citizenid .. ' is loaded')
end)Na kliencie, pasujące zdarzenie to QBCore:Client:OnPlayerLoaded:
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerLoaded = true
end)Jeśli twój zasób uruchamia ponownie, podczas gdy gracze są online, te zdarzenia nie wypalają się dla nich ponownie. Przy starcie, przejdź przez graczy, którzy są już załadowani:
CreateThread(function()
for _, src in pairs(QBCore.Functions.GetPlayers()) do
local Player = QBCore.Functions.GetPlayer(src)
if Player then
-- set up the player
end
end
end)2. source zmienił się po Wait
source to globalny, który FiveM ustawia dla działającego zdarzenia. Jeśli wezwiesz Wait wewnątrz handlera, inne zdarzenie może się uruchomić i zmienić go.
RegisterNetEvent('my_script:sell', function()
Wait(1000)
local Player = QBCore.Functions.GetPlayer(source) -- may be wrong, or nil
end)Zapisz to najpierw:
RegisterNetEvent('my_script:sell', function()
local src = source
Wait(1000)
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
end)3. Id jest zły
GetPlayer oczekuje server id gracza online, jako liczby.
- Ciąg z polecenia. Argumenty to tekst, więc je konwertuj:
QBCore.Functions.GetPlayer(tonumber(args[1])). - Zły id z klienta. Na kliencie,
PlayerId()jest indeksem lokalnym. Server id toGetPlayerServerId(PlayerId()). Lepiej, zignoruj id wysłane przez klienta i użyjsource, zobacz zabezpieczanie zdarzeń serwerowych. - Konsola. Polecenie wpisane w konsoli serwera ma
sourcerówny0, co nie jest graczem. - Id, które odeszło. Gracz się rozłączył, podczas gdy twój kod czekał.
QBCore.Commands.Add('givecash', 'Give cash', { { name = 'id', help = 'Player id' }, { name = 'amount', help = 'Amount' } }, true, function(source, args)
local target = QBCore.Functions.GetPlayer(tonumber(args[1]))
local amount = tonumber(args[2])
if not target or not amount then return end
target.Functions.AddMoney('cash', amount)
end, 'admin')4. Wyszukiwania citizenid znajdują tylko graczy online
Wiele skryptów przechowuje citizenid zamiast source, ponieważ source zmienia się na każdej sesji. Aby uzyskać gracza z citizenid:
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)To działa tylko, podczas gdy ten gracz jest online i załadowany. Dla gracza offline zwraca nil, co nie jest błędem w twoich danych. Przeczytaj bazę danych dla graczy offline:
local row = MySQL.single.await('SELECT charinfo, job FROM players WHERE citizenid = ?', { citizenid })
if row then
local charinfo = json.decode(row.charinfo)
endcharinfo jest przechowywana jako tekst JSON, więc dekoduj ją bezpiecznie, zobacz FiveM json.decode errors. Pisanie do gracza offline to inna praca: zmień wiersz bazy danych tylko jeśli gracz jest naprawdę offline, lub następny zapis z serwera przepiszę twoją zmianę.
5. Na QBox
Core QBox to qbx_core. Utrzymuje warstwę kompatybilności, więc QBCore.Functions.GetPlayer wciąż działa w skryptach napisanych dla QBCore. Dla nowego kodu, użyj jego eksportów, które zwracają ten sam rodzaj obiektu gracza lub nil:
local player = exports.qbx_core:GetPlayer(source)
if not player then return end
print(player.PlayerData.citizenid)Dla gracza online po citizenid:
local player = exports.qbx_core:GetPlayerByCitizenId(citizenid)Reguły z tego artykułu dotyczą w taki sam sposób: żaden gracz, dopóki postać nie będzie załadowana, magazyn source przed Wait i oczekuje nil dla gracza offline. Jeśli przenosisz skrypt między rdzeniami, zobacz konwersja skryptu QBCore do QBox.
6. playerDropped
Gdy gracz odchodzi, qb-core zapisuje i usuwa gracza samodzielnie, a kolejność handlerów dla playerDropped nie jest czymś, na czym można polegać. W twoim własnym handleru playerDropped, GetPlayer(source) może już być nil. Zachowaj to, czego potrzebujesz, we własnej tabeli, podczas gdy gracz jest online:
local sessions = {}
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
sessions[Player.PlayerData.source] = Player.PlayerData.citizenid
end)
AddEventHandler('playerDropped', function()
local citizenid = sessions[source]
sessions[source] = nil
if citizenid then
print(citizenid .. ' left')
end
end)Wzór ochrony
Zacznij każdy handler serwera, który potrzebuje gracza, w ten sam sposób:
RegisterNetEvent('my_script:action', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Player is safe to use here
end)Wskazówka: jeśli błąd dotyczy
QBCorebędącego nil, problem jest obiektem core, nie graczem. Zobacz attempt to index a nil value (global 'QBCore').
Lista kontrolna
| Symptom | Naprawa |
|---|---|
| Nil zaraz po dołączeniu gracza | Czekaj na QBCore:Server:PlayerLoaded zamiast playerJoining |
Nil po Wait |
Zapisz local src = source i użyj src |
| Nil z polecenia | Konwertuj argument za pomocą tonumber; konsola source to 0 |
GetPlayerByCitizenId zwraca nil |
Gracz jest offline; zapytaj tabelę players |
| Serwer QBox | Użyj exports.qbx_core:GetPlayer(source) i sprawdź nil |
Nil w playerDropped |
Zachowaj dane, których potrzebujesz, w swojej tabeli, podczas gdy gracz jest online |
| Dowolny nil | Dodaj if not Player then return end na górze handlera |
Szybkie odpowiedzi
Dlaczego QBCore.Functions.GetPlayer zwraca nil?
Nie ma załadowanego gracza z tym id. Gracz może wciąż ładować, id może być zły lub utracony po Wait, lub gracz już odszedł.
Czy GetPlayerByCitizenId działa dla gracza offline?
Nie. Znajduje tylko graczy online. Dla gracza offline, zamiast tego przeczytaj tabelę players w bazie danych.
Jaki jest odpowiednik QBox dla QBCore.Functions.GetPlayer?
exports.qbx_core:GetPlayer(source). Zwraca obiekt gracza, lub nil, gdy nie ma załadowanego gracza dla tego id.
Skrypty bez tego problemu
Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →
Drug Dealer AppUliczna sprzedaż jako aplikacja lb-phone: strefy, kupcy NPC, poziomy i alerty dla policji.Zobacz skrypt →
Pawn Shop AppLombard między graczami wewnątrz lb-phone.Zobacz skrypt →