attempt to compare number with nil / arithmetic on a nil value: düzelt
FiveM'de 'attempt to compare number with nil' ve 'arithmetic on a nil value' düzelt: yüklenmemiş oyuncu verileri, eksik config değerleri, tonumber ve güvenli varsayılanlar with `or`.
Konsol çıktısı:
SCRIPT ERROR: @my_script/server/main.lua:58: attempt to compare number with nil
SCRIPT ERROR: @my_script/client/main.lua:91: attempt to perform arithmetic on a nil value (field 'money')Script'in bir satırı, bir karşılaştırmada veya hesaplamada henüz mevcut olmayan bir değeri kullanır. Burada değeri genellikle boş bırakanlar ve script'i güvenli yapma yöntemi vardır.
Hata ne demek
Lua size hiçbir değeri olmayan herhangi bir değişken veya tablo girişi için nil verir. nil ile karşılaştırma (<, >, <=) veya hesaplama (+, -, *, /) script'i bu mesajlardan biri ile durdurur:
attempt to compare number with nil(veyaattempt to compare nil with number): karşılaştırmanın bir tarafınil.attempt to perform arithmetic on a nil value: bir hesaplamanildeğişkenini kullanır. Lua adı bildiğinde, bunu ekler,(field 'money')veya(local 'price')gibi.
Mesajdaki satır numarası, karşılaştırma veya toplamanın satırıdır. nil, bu satırdaki değerlerden biridir. Hangisini görmek için yazdırın:
print('price', price, type(price))
print('count', count, type(count))
if price > count then
-- ...
end1. Oyuncu verileri henüz yüklenmedi
En yaygın neden: script, çerçeve onları yüklemeyi bitirmeden oyuncuyu okur, örneğin dosyanın ilk satırlarında veya hemen başlayan bir thread'te.
-- runs too early on the client: money is nil
local money = ESX.GetPlayerData().money
if money > 100 then
-- ...
endÇerçevenin yüklü olayını bekleyin ve oradan verileri okuyun:
-- ESX client
local PlayerData = {}
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
end)-- QBCore client
local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = {}
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
end)Server'da, id yanlış olduğunda veya oyuncu ayrıldığında oyuncu nesnesi nil olabilir. Kullanmadan önce kontrol edin:
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return endlocal Player = QBCore.Functions.GetPlayer(source)
if not Player then return endQBox'ta, eşdeğer exports.qbx_core:GetPlayer(source) ile, aynı nil kontrol.
İpucu: script server'da iken yeniden başlatılırsa,
playerLoadedzaten ateşlenmiş ve tekrar ateşlenmez. Resource başladığında bir kez verileri okuyun.
2. Bir config değeri eksik
Script'in sahip olmadığı config.lua öğesine bir satır eklediniz veya script, eski config'iniz içermeyenayarlamayan bir anahtarı okur. Güncellemeden sonra, eski config.lua çok yaygın bir nedendir.
-- config.lua of the old version has no Config.Price
if playerMoney >= Config.Price then
-- ...
endConfig'inizi yeni sürümle gemiş olanla karşılaştırın ve eksik anahtarları ekleyin. Kendi kodunuzda, her ayara varsayılan verin:
local price = Config.Price or 1003. Değer sayı değil, string
Veritabanından değerler, menüdeki input kutusu veya JSON mesajı genellikle metin olarak gelir. String'i sayı ile karşılaştırmak farklı bir hata verir (attempt to compare number with string), ancak başarısız dönüşüm nil verir, bu da bu hatayı geri getirir. tonumber dönüştürür ve başaramadığında nil döndürür:
local amount = tonumber(data.amount)
if not amount then
return -- not a number: stop here
end4. Varsayılan için or kullanın
or sol taraf nil (veya false) olduğunda sağ tarafı döndürür. Hesaplamayı güvenli hale getirmenin en kısa yoludur:
local count = tonumber(data.count) or 0
local total = (item.price or 0) * countEksik bir değer gerçekten sıfır anlamına geldiği yerde kullanın, örneğin isteğe bağlı bonus gibi. Eksik değer bir hata olduğunda, örneğin var olması gereken bir fiyat, gizlemek yerine açık bir mesaj ile durdurun:
local price = Config.Items[name] and Config.Items[name].price
if not price then
print(('no price set for %s'):format(name))
return
end5. Veritabanı veya callback sonucu boş
Hiçbir satır bulamayan bir sorgu nil veya boş tablo verir. Sütun okuma başarısız:
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
if row.balance > 0 then -- row is nil when the player has no row
-- ...
endÖnce satırı kontrol edin:
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
local balance = row and row.balance or 0Aynısı server callbacks'leri için: callback bulunamadı veya hiçbir şey döndürmedi se cevap nil olabilir. Script'iniz bir callback'te beklerseniz, bu durumu işleyin. İlgili: attempt to call a nil value kardeş hatadır, değer değil fonksiyon eksik olduğunda.
6. Alan adında yazım hatası
xPlayer.money ve xPlayer.Money farklıdır. price ve Price de. Hata mesajı genellikle alanı adlandırır: çerçeve belgelerine veya print(json.encode(data)) ile yazdırdığınız tabloyla eş anlamlılığını kontrol edin.
Kontrol listesi
| Belirti | Fix |
|---|---|
| Katıldıktan hemen sonra hata | Oyuncu verileri okumadan önce oyuncu yüklü olayını bekleyin |
xPlayer veya Player server'da nil |
if not xPlayer then return end kontrol edin ve kaynak id'yi |
| Script güncellemesinden sonra hata | Gönderilen config.lua yeni anahtarlarını sizinkine ekleyin |
| Değer menüden veya JSON'dan gelir | tonumber(value) ile dönüştürün ve nil olmadığını kontrol edin |
| Bir değer amacıyla eksik olabilir | Varsayılan olarak value or 0 kullanın |
| Veritabanı sorgusu hiçbir şey döndürmez | Sütunlarını okumadan önce satırın nil olmadığını kontrol edin |
| Alan nil bile olmalı olsa da | Yazım ve büyük harfleri kontrol edin |
Kısa yanıtlar
'attempt to compare number with nil' ne anlama geliyor?
Bir satır bir sayıyı, price nil olduğunda price > 100 gibi hiçbir değeri olmayan bir şey ile karşılaştırır. Hangi değişkenin nil olduğunu ve neden asla ayarlanmadığını bulun.
Lua'da bir değişkene varsayılan bir değer nasıl veririm?
or kullanın: local count = tonumber(value) or 0. Değer nil veya sayı değilse, count 0 olur.
Neden sadece sunucuya katılır katılmaz olur?
Script, çerçeve yükledikten sonra oyuncu verileri okur. Oyuncu yüklü olayını bekleyin veya oyuncu nesnesinin nil olmadığını okumadan önce kontrol edin.


