FiveM CreateThread ve Wait(0) açıklanmış: neden script'iniz ms tutuyor
CreateThread, Wait ve SetTimeout FiveM Lua'da nasıl çalışır, her döngüde Wait(0) neden resmon'da görünür ve Wait'siz while döngüsü neden oyunu donduruyor.
Bir şeyi kontrol etmek için bir döngü yazarsınız ve oyun cevap vermeyi durdurur veya resmon kaynağınızı hareketsizken birkaç ms'de gösterir:
while true do
-- no Wait here: the game never gets control back
local ped = PlayerPedId()
endBu makale, FiveM Lua'da thread'ler ve Wait nasıl çalışır, Wait(0) gerçekten ne kadara mal olur ve ucuz kalan döngüler nasıl yazılır açıklar.
Thread'ler FiveM'de nasıl çalışır
FiveM'deki Lua işbirliğidir. Script'iniz oyun ile paralel olarak çalışmaz: runtime onu çağırdığında çalışır ve kontrol geri vermelidir. İki şey bunu mümkün kılar:
- Event handler'ları ve geri çağrıları bir kez çalışır, baştan sonuna kadar, sonra geri döner.
- Thread'ler
CreateThreadile oluşturulan küçük coroutine'lerdir, scheduler bunları tekrar tekrar devam ettirir. Bir thread,Waitçağırdığında kontrol geri verir.
CreateThread(function()
while true do
Wait(1000)
print('one second later')
end
end)CreateThread ve Citizen.CreateThread aynı fonksiyon, Wait ve Citizen.Wait de öyle. Hangisini isterseniz kullanın, ama bir script'te tutarlı olun.
Wait'siz while döngüsü oyunu donduruyor
Bir thread asla Wait çağırmazsa, scheduler asla kontrol geri almaz. Client'ta oyun, döngü bitene kadar frame çizmeyi durdurur ve server'da diğer her script senininkini bekler.
CreateThread(function()
while true do
-- missing Wait: this blocks the whole client
end
end)Aynı şey repeat … until veya ağır işleme yapan uzun for döngüsü ile de olur. Bir süre çalışabilen her döngünün içinde Wait gerekir. Script oyunu başlangıçta donduruyor sa, önce böyle bir döngü arayın.
Wait(0) ne kadara mal olur
Wait(0) anlamı: client'ta sonraki frame'e veya server'da sonraki tick'e kadar durakla, sonra devam et. Döngü her frame'de tekrar çalışır, bu nedenle 60 fps'de gövdesi saniyede 60 kez ödenir.
CreateThread(function()
while true do
Wait(0)
local coords = GetEntityCoords(PlayerPedId())
local dist = #(coords - vector3(215.0, -810.0, 30.7))
if dist < 3.0 then
-- draw a marker, show text...
end
end
end)Böyle bir döngü çok az mal olur. Otuz kaynak arasında on tanesi birkaç ms istemci zamanı ekler, bu tam olarak resmon yüksek ms olarak gösterir. Maliyet Wait(0) nin kendisi değil, her frame'de tekrarladığınız her şeydir.
Wait yalnızca ihtiyacınız kadar kısa
Çoğu kontrol her frame'de çalışması gerekmez. Döngü ne için sorun:
| Döngü ne yapıyor | Makul wait |
|---|---|
| Marker veya metin çiz, tuş basmasını işle | 0 (yalnızca oyuncu yakın olduğu zaman) |
| Bir şeyin yakın olup olmadığını belirlemek için mesafeyi kontrol et | 250 to 1000 |
| Nadiren değişen bir durumu yokla (iş, araç) | 1000 veya daha fazla, veya olay kullanın |
Usual trick iki hızdır: mesafeyi kontrol eden yavaş döngü ve oyuncu bölgenin içinde olurken hızlı bir tane.
local zone = vector3(215.0, -810.0, 30.7)
CreateThread(function()
while true do
local sleep = 1000
local dist = #(GetEntityCoords(PlayerPedId()) - zone)
if dist < 10.0 then
sleep = 0
DrawMarker(1, zone.x, zone.y, zone.z - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1.5, 1.5, 0.5, 255, 255, 255, 120, false, false, 2, false, nil, nil, false)
end
Wait(sleep)
end
end)Bölgeden uzakta, thread saniyede bir kez uyanır. Yakınında, her frame'de çizer. Resmon çoğu oyuncu için neredeyse hiçbir şeye düşer.
İpucu: daha hızlı bir döngüye ulaşmadan önce, bir olay veya state bag değer değiştiğinde sizi söyleyip söyleyemeyeceğini sorun. Hiçbir döngü hiçbir Wait'den daha ucuzdur.
SetTimeout: bir şeyi sonra bir kez çalıştır
Yalnızca gecikmeden sonra bir kez bir şey yapmanız gerekiyorsa, bir thread'e Wait gerekli değildir:
SetTimeout(5000, function()
print('five seconds later')
end)SetTimeout(ms, callback) geri çağrıyı gecikmeden sonra bir kez çalıştırır ve hiçbir şeyi engel olmez. Server'da da var. Tekrarlayan bir görev için, SetTimeout kendiliğinden tekrarlama olmadığından Wait ile bir thread doğru araçtır.
Event handler'lar içinde bekleme
Bir event handler da Wait çağırabilir, çünkü FiveM onu kendi coroutine'inde çalıştırır. Server'da dikkatli olun: Wait sonra, global source artık olayı tetikleyen oyuncuya işaret etmez. Önce kaydedin (client ve server olaylarına bakın):
RegisterNetEvent('my_script:server:buy', function()
local src = source
Wait(500)
print(('player %s bought something'):format(src))
end)Thread'i durdurma
Bir thread, fonksiyonu geri döndüğünde biter. Bir döngüyü dışarıdan durdurmak için, döngünün kontrol ettiği bir bayrak kullanın:
local running = true
CreateThread(function()
while running do
Wait(500)
-- work
end
end)
AddEventHandler('onResourceStop', function(resource)
if resource == GetCurrentResourceName() then
running = false
end
end)Bir kaynağın tüm thread'leri, kaynak durdurulduğunda kendi kendine durur, bu nedenle kaynak çalışmaya devam ederken bir döngüyü durdurmak için buna ihtiyacınız var.
Kontrol listesi
| Belirti | Fix |
|---|---|
| Script başladığında oyun donuyor | while true do döngüsünün Wait yok: bir tane ekleyin |
| Kaynak hareketsizken resmon'da sabit ms gösteriyor | Wait(0) yerine mesafe kontrol ve daha uzun bekleme ile değiştirin |
| Gecikmeden sonra bir şey bir kez çalıştırması gerekir | Thread yerine SetTimeout(ms, fn) |
Server'da Wait sonra source yanlış |
Wait öncesinde local src = source kaydedin |
| Nadiren değişen bir değeri yoklama | Döngü yerine olay veya state bag kullanın |
Citizen.Wait veya Wait? |
Aynı fonksiyon, bir stil seçin |
Kısa yanıtlar
FiveM'de Wait(0) ne yapar?
Mevcut thread'i client'ta sonraki frame'e veya server'da sonraki tick'e kadar duraklatır. Döngü daha sonra her frame'de tekrar çalışır, bu nedenle içindeki her şey saniyede 60 veya daha fazla kez ödenir.
Citizen.Wait, Wait'ten farklı mı?
Hayır. Wait ve Citizen.Wait aynı fonksiyon, CreateThread ve Citizen.CreateThread de öyle. Kısa adlar sadece takma adlar.
Wait tüm oyunu durdurur mu?
Hayır. Yalnızca onu çağıran thread'i duraklatır ve diğer thread'ler ve oyun çalışmaya devam eder. Asla Wait çağırmayan bir döngü, her şeyi engeller.
Bu sorunu yaşatmayan scriptler
Advanced BoostingTabletten araç boosting: D’den S+ sınıfına kontratlar, ekipler ve canlı sıra.Scripti gör →
CCTV Security CamerasYerleştirilebilir kameralar, canlı çoklu görüntü tableti ve basılı delil fotoğrafları.Scripti gör →
Mic PhoneTablete dönüşen katlanabilir bir telefon; oyuncunun gerçek telefonuna da taşınır.Scripti gör →