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ı:

text
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 (veya attempt to compare nil with number): karşılaştırmanın bir tarafı nil.
  • attempt to perform arithmetic on a nil value: bir hesaplama nil değ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:

lua
print('price', price, type(price))
print('count', count, type(count))
if price > count then
    -- ...
end

1. 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.

lua
-- 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:

lua
-- ESX client
local PlayerData = {}

RegisterNetEvent('esx:playerLoaded', function(xPlayer)
    PlayerData = xPlayer
end)
lua
-- 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:

lua
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return end
lua
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return end

QBox'ta, eşdeğer exports.qbx_core:GetPlayer(source) ile, aynı nil kontrol.

İpucu: script server'da iken yeniden başlatılırsa, playerLoaded zaten 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.

lua
-- config.lua of the old version has no Config.Price
if playerMoney >= Config.Price then
    -- ...
end

Config'inizi yeni sürümle gemiş olanla karşılaştırın ve eksik anahtarları ekleyin. Kendi kodunuzda, her ayara varsayılan verin:

lua
local price = Config.Price or 100

3. 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:

lua
local amount = tonumber(data.amount)
if not amount then
    return -- not a number: stop here
end

4. 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:

lua
local count = tonumber(data.count) or 0
local total = (item.price or 0) * count

Eksik 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:

lua
local price = Config.Items[name] and Config.Items[name].price
if not price then
    print(('no price set for %s'):format(name))
    return
end

5. Veritabanı veya callback sonucu boş

Hiçbir satır bulamayan bir sorgu nil veya boş tablo verir. Sütun okuma başarısız:

lua
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:

lua
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
local balance = row and row.balance or 0

Aynı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.

Bu sorunu yaşatmayan scriptler

Shop CreatorBir dakikadan kısa sürede dükkân kurun — sahipler, çalışanlar, kasalar ve soygunlar dahil.Scripti gör →Pawn Shop Applb-phone içinde oyuncudan oyuncuya rehin pazarı.Scripti gör →Quest CreatorGörevler ve NPC diyalogları için oyun içinde düğüm düğüm kurulan görsel editör.Scripti gör →

Okumaya devam edin