attempt to index a nil value (local 'Player'): QBCore und QBox Behebung
Player ist nil in deinem QBCore oder QBox Script? Warum QBCore.Functions.GetPlayer(source) nil zurückgibt, citizenid Lookups nur für online Spieler, und die sicheren Guard-Muster.
In der Server-Konsole:
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 fand keinen geladenen Spieler für diese ID und gab nil zurück, und die nächste Zeile indizierte ihn. Die Ursachen spiegeln den ESX-Fall in ESX xPlayer ist nil mit QBCore und QBox-Besonderheiten wider.
1. Der Spieler ist nicht geladen
Ein Spieler kann verbunden sein, bevor QBCore seinen Charakter geladen hat, besonders während ein multicharacter Bildschirm offen ist. Bis der Charakter gewählt wird, gibt GetPlayer(source) nil zurück.
Code, der auf playerJoining läuft, oder aus einem Thread, der sofort startet, trifft dies. Warte auf das QBCore-Event, das auslöst, wenn der Spieler bereit ist. Auf dem Server:
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
print(Player.PlayerData.citizenid .. ' is loaded')
end)Auf dem Client ist das passende Event QBCore:Client:OnPlayerLoaded:
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerLoaded = true
end)Wenn deine Ressource neu gestartet wird, während Spieler online sind, werden diese Events für sie nicht erneut ausgelöst. Beim Start gehe durch die Spieler, die bereits geladen sind:
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 ändert sich nach einem Wait
source ist ein Global, das FiveM für das laufende Event setzt. Wenn du Wait in dem Handler aufrufst, kann ein anderes Event laufen und ihn ändern.
RegisterNetEvent('my_script:sell', function()
Wait(1000)
local Player = QBCore.Functions.GetPlayer(source) -- may be wrong, or nil
end)Speichere es zuerst:
RegisterNetEvent('my_script:sell', function()
local src = source
Wait(1000)
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
end)3. Die ID ist falsch
GetPlayer erwartet die Server-ID eines Online-Spielers als Zahl.
- Eine Zeichenkette aus einem Befehl. Argumente sind Text, also konvertiere sie:
QBCore.Functions.GetPlayer(tonumber(args[1])). - Die falsche ID vom Client. Auf dem Client ist
PlayerId()ein lokaler Index. Die Server-ID istGetPlayerServerId(PlayerId()). Besser, ignoriere IDs, die vom Client gesendet werden, und verwendesource, siehe sichere Server-Events. - Die Konsole. Ein Befehl, der in der Server-Konsole eingegeben wird, hat
sourcegleich0, was kein Spieler ist. - Eine ID, die verlassen hat. Der Spieler hat die Verbindung getrennt, während dein Code wartete.
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. citizenid Lookups finden nur Online-Spieler
Viele Scripts speichern die citizenid statt der source, weil sich die source bei jeder Session ändert. Um den Spieler aus einer citizenid zu bekommen:
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)Dies funktioniert nur, während dieser Spieler online und geladen ist. Für einen Spieler, der offline ist, gibt es nil zurück, was kein Fehler in deinen Daten ist. Lese die Datenbank für Offline-Spieler:
local row = MySQL.single.await('SELECT charinfo, job FROM players WHERE citizenid = ?', { citizenid })
if row then
local charinfo = json.decode(row.charinfo)
endcharinfo wird als JSON-Text gespeichert, also dekodiere es sicher, siehe FiveM json.decode Fehler. Das Schreiben auf einen Offline-Spieler ist eine andere Aufgabe: ändere die Datenbankzeile nur, wenn der Spieler wirklich offline ist, oder die nächste Speicherung vom Server überschreibt deine Änderung.
5. In QBox
Der Core von QBox ist qbx_core. Es behält eine Kompatibilitätsebene, also funktioniert QBCore.Functions.GetPlayer immer noch in Scripts, die für QBCore geschrieben sind. Für neuen Code verwende seine Exports, die das gleiche Spieler-Objekt oder nil zurückgeben:
local player = exports.qbx_core:GetPlayer(source)
if not player then return end
print(player.PlayerData.citizenid)Für einen Online-Spieler per citizenid:
local player = exports.qbx_core:GetPlayerByCitizenId(citizenid)Die Regeln aus diesem Artikel gelten auf die gleiche Weise: kein Spieler bis der Charakter geladen ist, speichere source vor einem Wait, und erwarte nil für einen Offline-Spieler. Wenn du ein Script zwischen den Cores bewegst, siehe Konvertiere ein QBCore-Script zu QBox.
6. playerDropped
Wenn ein Spieler verlässt, speichert qb-core und entfernt den Spieler von selbst, und die Reihenfolge der Handler für playerDropped ist nichts, auf das man sich verlassen sollte. In deinem eigenen playerDropped Handler kann GetPlayer(source) bereits nil sein. Behalte, was du brauchst, in deiner eigenen Tabelle, während der Spieler online ist:
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)Das Guard-Muster
Beginne jeden Server-Handler, der einen Spieler braucht, auf die gleiche Weise:
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)Tipp: Wenn der Fehler über
QBCoreselbst nil ist, ist das Problem das Core-Objekt, nicht der Spieler. Siehe attempt to index a nil value (global 'QBCore').
Checkliste
| Symptom | Behebung |
|---|---|
| Nil direkt nach dem Spieler beitritt | Warte auf QBCore:Server:PlayerLoaded anstelle von playerJoining |
Nil nach einem Wait |
Speichere local src = source und verwende src |
| Nil aus einem Befehl | Konvertiere das Argument mit tonumber; die Konsole source ist 0 |
GetPlayerByCitizenId gibt nil zurück |
Der Spieler ist offline; frage die players Tabelle ab |
| QBox Server | Verwende exports.qbx_core:GetPlayer(source) und überprüfe auf nil |
Nil in playerDropped |
Behalte die Daten, die du brauchst, in deiner eigenen Tabelle, während der Spieler online ist |
| Jeder nil | Füge if not Player then return end am Anfang des Handlers ein |
Kurze Antworten
Warum gibt QBCore.Functions.GetPlayer nil zurück?
Es gibt keinen geladenen Spieler mit dieser ID. Der Spieler lädt möglicherweise noch, die ID könnte falsch sein oder nach einem Wait verloren gehen, oder der Spieler hat bereits verlassen.
Funktioniert GetPlayerByCitizenId für Offline-Spieler?
Nein. Es findet nur Spieler, die online sind. Für einen Offline-Spieler lese stattdessen die players Tabelle in der Datenbank.
Was ist das QBox-Äquivalent von QBCore.Functions.GetPlayer?
exports.qbx_core:GetPlayer(source). Es gibt das Spieler-Objekt zurück, oder nil wenn es keinen geladenen Spieler für diese ID gibt.
Scripts ohne dieses Problem
Advanced BoostingFahrzeug-Boosting per Tablet: Aufträge von Klasse D bis S+, Crews und eine Live-Warteschlange.Script ansehen →
Drug Dealer AppStraßenverkauf als lb-phone-App: Zonen, NPC-Käufer, Level und Polizeialarme.Script ansehen →
Pawn Shop AppEin Pfandmarkt zwischen Spielern, direkt in lb-phone.Script ansehen →