Paralel Luau

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Paralel Luau programlama modeli ile kodu aynı anda birden fazla iş parçacığında çalıştırabilirsiniz; bu, deneyiminizin performansını artırabilir. Deneyiminizi daha fazla içerikle genişletirken, bu modeli benimseyerek Luau scriptlerinizin performans ve güvenliğini sağlamaya yardımcı olabilirsiniz.

Paralel programlama modeli

Varsayılan olarak, scriptler sırayla çalışır. Eğer deneyiminiz, oyuncu olmayan karakterler (NPC'ler), ışın izleme doğrulaması ve prosedürel üretim gibi karmaşık mantık veya içerik barındırıyorsa, o zaman sıralı yürütme kullanıcılarınız için gecikmelere neden olabilir. Paralel programlama modeli ile görevleri birden fazla script'e bölebilir ve bunları paralel olarak çalıştırabilirsiniz. Bu, deneyiminiz kodunun daha hızlı çalışmasını sağlar ve kullanıcı deneyimini geliştirir.

Paralel programlama modeli, kodunuza güvenlik faydaları da ekler. Kodunuzu birden fazla iş parçacığına ayırarak, bir iş parçacığındaki kodu değiştirdiğinizde, paralel olarak çalışan diğer kodları etkilemez. Bu, kodunuzda bir hatanın tüm deneyimi bozma riskini azaltır ve bir güncelleme gönderdiğinizde canlı sunuculardaki kullanıcılar için gecikmeyi en aza indirir.

Paralel programlama modelini benimsemek, her şeyi birden fazla iş parçacığına koymak anlamına gelmez. Örneğin, sunucu tarafındaki ışın izleme doğrulaması her bir kullanıcıya paralel olarak bir uzaktan etkinlik atar; ancak yine de küresel özellikleri değiştirmek için başlangıç kodunun sıralı olarak çalışmasını gerektirir, bu da paralel yürütme için yaygın bir örüntüdür.

Çoğu zaman, istediğiniz çıktıyı elde etmek için sıralı ve paralel aşamaları birleştirmeniz gerekir; çünkü şu anda paralel aşamalarda desteklenmeyen bazı işlemler vardır ve bu işlemler scriptlerin çalışmasını engelleyebilir, örneğin paralel aşamalarda örnekleri değiştirmek gibi. Paralel kullanım için API'lerin kullanım seviyeleri hakkında daha fazla bilgi için iş parçacığı güvenliği bilgisine bakın.

Kodu birden fazla iş parçacığına bölme

Deneyiminizin scriptlerini birden fazla iş parçacığında eşzamanlı olarak çalıştırmak için, bunları veri modeli altında farklı aktörler ile mantıksal parçalara ayırmanız gerekir. Aktörler, Actor örnekleri olarak DataModel sınıfından miras alır. Bu aktörler, eşzamanlı olarak çalışan birden fazla çekirdeğe yük dağıtan yürütme izolasyonu birimleri olarak çalışır.

Aktör örneklerini yerleştirin

Aktörleri uygun kaplarda koyabilir veya onları NPC'ler ve ışın izleyiciler gibi 3D varlıklarınızın üst düzey örnek türlerini değiştirmek için kullanabilir ve ardından ilgili scriptleri ekleyebilirsiniz.

Bir Aktör altındaki Script örneği

Çoğu durumda, bir aktörü veri modelinde başka bir aktörün çocuğu olarak koymamalısınız. Ancak, belirli bir kullanım durumunuz için bir scripti birden fazla aktör içinde yerleştirmeye karar verirseniz, script en yakın ata aktörüne aittir.

Bir scriptin en yakın aktör tarafından sahiplenildiğini gösteren aktörler ve scriptlerin ağacı

İş parçacıklarını senkroize etme

Scriptler, aktörlerin altında yer aldığında paralel yürütme yeteneğine sahip olmasına rağmen, varsayılan olarak kod hala tek bir iş parçacığında sıralı çalışır; bu, çalışma zamanını artırmaz. task.desynchronize() fonksiyonunu çağırmanız gerekir; bu, mevcut coroutine'in yürütmesini askıya alan ve kodun paralel çalıştırılması için bir sonraki paralel yürütme fırsatında geri yükleyen bir yieldable işlevdir. Bir scripti tekrar sıralı yürütmeye geçirebilmek için task.synchronize() çağrısını yapmalısınız.

Alternatif olarak, RBXScriptSignal:ConnectParallel() yöntemini, bir sinyal geri çağrısını tetiklediğinde kodunuzu hemen paralel olarak çalıştırmak için planlamak istediğinizde kullanabilirsiniz. Sinyal geri çağrısının içinde task.desynchronize() çağırmanıza gerek yoktur.

Bir İş Parçacığını Senkroize Et

local RunService = game:GetService("RunService")
RunService.Heartbeat:ConnectParallel(function()
... -- Durum güncellemesi hesaplayan bazı paralel kod
task.synchronize()
... -- Örneklerin durumunu değiştiren bazı sıralı kod
end)

Aynı aktörün parçası olan scriptler birbirlerine göre her zaman sıralı olarak yürütülür, bu yüzden birden fazla aktöre ihtiyacınız vardır. Örneğin, NPC'niz için tüm paralel etkinleştirilmiş davranış scriptlerini tek bir aktöre koyarsanız, yine de tek bir iş parçacığında sıralı olarak çalışır; ancak farklı NPC mantıkları için birden fazla aktörünüz varsa, her biri kendi iş parçacığında paralel olarak çalışır. Daha fazla bilgi için En iyi uygulamalar bölümüne bakın.

Aynı anda çalışan paralel kodların tek bir iş parçacığında sıralı olarak çalıştığı durum
Aynı anda çalışan paralel kodların birden fazla iş parçacığında çalıştığı durum

İş parçacığı güvenliği

Paralel yürütme sırasında, DataModel hiyerarşisinin çoğu örneğine normalde olduğu gibi erişebilirsiniz; ancak, bazı API özellikleri ve işlevleri okunması veya yazılması güvenli değildir. Eğer bunları paralel kodunuzda kullanırsanız, Roblox motoru bu tür erişimleri otomatik olarak tespit edip engelleyebilir.

API üyeleri, paralel kodunuzda nasıl kullanabileceğinizi gösteren bir iş parçacığı güvenlik seviyesi taşır. Aşağıdaki tabloda bu seviyeler gösterilmektedir:

Güvenlik seviyesiÖzellikler içinİşlevler için
GüvensizParalel olarak okunamaz veya yazılamaz.Paralel olarak çağrılamaz.
Paralel OkumaParalel olarak okunabilir ancak yazılamaz.N/A
Yerel GüvenliAynı Aktör içinde kullanılabilir; paralel olarak diğer Actors tarafından okunabilir ama yazılamaz.Aynı Aktör içinde çağrılabilir; paralel olarak diğer Actors tarafından çağrılamaz.
GüvenliOkunabilir ve yazılabilir.Çağrılabilir.

API üyeleri için iş parçacığı güvenlik etiketlerini API referansı sayfasında bulabilirsiniz. Bunları kullanırken, API çağrılarının veya özellik değişikliklerinin paralel iş parçacıkları arasında nasıl etkileşimde bulunabileceğini de düşünmelisiniz. Genellikle, birden fazla aktörün diğer aktörlerle aynı verileri okumak için güvenli olmasıdır, ancak diğer aktörlerin durumunu değiştirmesi güvenli değildir.

İş parçacıkları arası iletişim

Çoklu iş parçacığı bağlamında, farklı aktörlerdeki scriptlerin birbirleriyle veri paylaşımı, görevleri koordine etme ve etkinlikleri senkronize etme gibi iletişim yollarını sağlayabilirsiniz. Motor, iş parçacıkları arası iletişim için aşağıdaki mekanizmaları destekler:

İş parçacıkları arası iletişim ihtiyaçlarınızı karşılamak için birden fazla mekanizmayı destekleyebilirsiniz. Örneğin, bir ortak tabloyu Aktör Mesajlaşma API'si aracılığıyla gönderebilirsiniz.

Aktör mesajlaşma

Aktör mesajlaşma API'si, bir scriptin, sıradan veya paralel bir bağlamda, aynı veri modelindeki bir aktöre veri göndermesine izin verir. Bu API aracılığıyla iletişim asenkron olup, gönderici, alıcı mesajı aldığında bloke olmaz.

Bu API kullanılarak mesaj gönderirken, mesajı kategorize etmek için bir konu tanımlamanız gerekir. Her mesaj yalnızca bir aktöre gönderilebilir, ancak o aktör, bir mesajla bağlı birden fazla geri çağrıya sahip olabilir. Yalnızca bir aktörün soyundan gelen scriptler mesaj alabilir.

API aşağıdaki yöntemlere sahiptir:

Aşağıdaki örnek, Actor:SendMessage() yöntemini kullanarak bir konu tanımlayıp gönderen mesaj gönderme tarafını göstermektedir:

Örnek Mesaj Gönderici

local Workspace = game:GetService("Workspace")
-- "Selam" konusuyla işçi aktöre iki mesaj gönder
local workerActor = Workspace.WorkerActor
workerActor:SendMessage("Greeting", "Merhaba Dünya!")
workerActor:SendMessage("Greeting", "Hoş geldiniz")
print("Mesajlar gönderildi.")

Aşağıdaki örnek, alıcı tarafında belirli bir konu için paralel bir bağlamda bir geri çağrı bağlamak için Actor:BindToMessageParallel() yöntemini kullanmaktadır:

Örnek Mesaj Alıcı

-- Bu scriptin ait olduğu aktörü al
local actor = script:GetActor()
-- "Selam" mesaj konusuna bağlı bir geri çağrı bağla
actor:BindToMessageParallel("Greeting", function(greetingString)
print(actor.Name, "-", greetingString)
end)
print("Mesajlara bağlı")

Paylaşılan tablo

SharedTable, birden fazla aktör altında çalışan scriptlere erişilebilen tablo benzeri bir veri yapısıdır. Çok miktarda veri içeren ve birden fazla iş parçacığı arasında ortak bir durum talep eden durumlar için yararlıdır. Örneğin, birden fazla aktörün veri modelinde saklanmayan ortak bir dünya durumunda çalışması durumunda faydalıdır.

Bir paylaşılan tabloyu başka bir aktöre göndermek veri kopyası oluşturmaz. Bunun yerine, paylaşılan tablolar, birden fazla scriptin aynı anda güvenli ve atomik güncellemeleri yapmasına izin verir. Bir aktör tarafından paylaşılan bir tablodaki her güncelleme hemen tüm aktörlere görünür. Paylaşılan tablolar, altındaki veriyi kopyalamak yerine yapısal paylaşım kullanarak kaynak verimli bir şekilde klonlanabilir.

Doğrudan veri modeli iletişimi

Ayrıca, farklı aktörlerin özellikleri veya nitelikleri yazmasına ve daha sonra okumalarına olanak tanıyarak, birden fazla iş parçacığı arasında doğrudan veri modeli aracılığıyla iletişim sağlanabilir. Ancak, iş parçacığı güvenliğini korumak için genellikle paralel çalışan scriptler veri modeline yazamaz. Bu nedenle, iletişim için veri modelini doğrudan kullanmak kısıtlamalarla gelir ve scriptlerin sıklıkla senkronize olmasını zorunlu kılabilir; bu da scriptlerinizin performansını olumsuz etkileyebilir.

Örnekler

Sunucu tarafında ışın izleme doğrulaması

Bir dövüş ve savaş deneyimi için, kullanıcıların silahları için ışın izlemeyi etkinleştirmeniz gerekir. İyi bir gecikme sağlamak için istemcinin silahları simüle etmesi gerektiği gibi, sunucunun bu vuruşu doğrulaması gerekir; bu, ışın izlemeleri gerçekleştirmeyi ve beklenen karakter hızını hesaplayan bir miktar sezgisel hesaplama yapmayı ve geçmiş davranışlara bakmayı içerir.

İstemcilerin vuruş bilgilerini ilettiği uzak bir etkinliğe bağlanan tek bir merkezi script yerine, sunucu tarafında her bir vuruş doğrulama işlemini paralel olarak çalıştırabilirsiniz; her kullanıcı karakterinin ayrı bir uzak olaya sahip olacaktır.

O karakterin Actor altında çalışan sunucu tarafındaki script, bu uzak olaya bağlanarak vuruşu doğrulamak için ilgili mantığı yürütür. Mantık bir vuruş onayı bulursa, hasar düşürülür; bu, özelliklerin değiştirilmesini içerdiği için ilk olarak sıralı çalışır.


local Workspace = game:GetService("Workspace")
local tool = script.Parent.Parent
local remoteEvent = Instance.new("RemoteEvent") -- Yeni uzak bir olay oluştur ve araca ekle
remoteEvent.Name = "RemoteMouseEvent" -- Yerel scriptin arayabileceği şekilde yeniden adlandır
remoteEvent.Parent = tool
local remoteEventConnection -- Uzak olay bağlantısı için bir referans oluştur
-- Uzak bir olayı dinleyen fonksiyon
local function onRemoteMouseEvent(player: Player, clickLocation: CFrame)
-- SIRALI: Sıralı kurulum kodunu çalıştır
local character = player.Character
-- Işın izleme sırasında kullanıcının karakterini göz ardı et
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = { character }
-- PARALEL: Paralel olarak ışın izlemeyi gerçekleştirin
task.desynchronize()
local origin = tool.Handle.CFrame.Position
local epsilon = 0.01 -- Tıklama konumu nesneden biraz kaymış olabileceği için ışını biraz uzatmak için kullanılır
local lookDirection = (1 + epsilon) * (clickLocation.Position - origin)
local raycastResult = Workspace:Raycast(origin, lookDirection, params)
if raycastResult then
local hitPart = raycastResult.Instance
if hitPart and hitPart.Name == "block" then
local explosion = Instance.new("Explosion")
-- SIRALI: Aşağıdaki kod aktörün dışındaki durumu değiştirir
task.synchronize()
explosion.DestroyJointRadiusPercent = 0 -- Patlamayı ölümcül hale getirme
explosion.Position = clickLocation.Position
-- Birden fazla aktör raycast ile aynı parçayı alabilir ve yok etmeyi karar verebilir
-- Bu tamamen güvenlidir ancak aynı anda iki patlama gerçekleşmesine neden olur
-- Aşağıdaki kontrol, yürütmenin önce bu kısma ulaşmasını kontrol eder
if hitPart.Parent then
explosion.Parent = Workspace
hitPart:Destroy() -- Yok et
end
end
end
end
-- Öncelikle bazı kurulum kodları paralel olarak çalıştırılamadığı için sıralı olarak sinyali bağla
remoteEventConnection = remoteEvent.OnServerEvent:Connect(onRemoteMouseEvent)

Sunucu tarafında prosedürel arazi oluşturma

Deneyiminiz için büyük bir dünya oluşturmak için, dünyayı dinamik olarak doldurabilirsiniz. Prosedürel üretim tipik olarak bağımsız arazi parçaları yaratır; üretici nesne yerleştirme, malzeme kullanımı ve voxel doldurma için nispeten karmaşık hesaplamalar yapar. Üretim kodunu paralel olarak çalıştırmak, sürecin verimliliğini artırabilir. Aşağıdaki kod örneği bir örnek olarak hizmet etmektedir.


-- Paralel yürütme aktörlerin kullanılmasını gerektirir
-- Bu script kendini klonlayacak; orijinali süreci başlatır, klonlar ise işçi olarak hareket eder
local Workspace = game:GetService("Workspace")
local actor = script:GetActor()
if actor == nil then
local workers = {}
for i = 1, 32 do
local actor = Instance.new("Actor")
script:Clone().Parent = actor
table.insert(workers, actor)
end
-- Tüm aktörleri kendisine yerleştir
for _, actor in workers do
actor.Parent = script
end
-- Aktörlere mesajlar göndererek arazi oluşturması talimatı ver
-- Bu örnekte aktörler rastgele seçildi
task.defer(function()
local rand = Random.new()
local seed = rand:NextNumber()
local sz = 10
for x = -sz, sz do
for y = -sz, sz do
for z = -sz, sz do
workers[rand:NextInteger(1, #workers)]:SendMessage("GenerateChunk", x, y, z, seed)
end
end
end
end)
-- Orijinal scriptten çık, geri kalan kod her aktörde yürütülecek
return
end
function makeNdArray(numDim, size, elemValue)
if numDim == 0 then
return elemValue
end
local result = {}
for i = 1, size do
result[i] = makeNdArray(numDim - 1, size, elemValue)
end
return result
end
function generateVoxelsWithSeed(xd, yd, zd, seed)
local matEnums = {Enum.Material.CrackedLava, Enum.Material.Basalt, Enum.Material.Asphalt}
local materials = makeNdArray(3, 4, Enum.Material.CrackedLava)
local occupancy = makeNdArray(3, 4, 1)
local rand = Random.new()
for x = 0, 3 do
for y = 0, 3 do
for z = 0, 3 do
occupancy[x + 1][y + 1][z + 1] = math.noise(xd + 0.25 * x, yd + 0.25 * y, zd + 0.25 * z)
materials[x + 1][y + 1][z + 1] = matEnums[rand:NextInteger(1, #matEnums)]
end
end
end
return {materials = materials, occupancy = occupancy}
end
-- Paralel yürütme bağlamında çağrılacak geri çağrıyı bağla
actor:BindToMessageParallel("GenerateChunk", function(x, y, z, seed)
local voxels = generateVoxelsWithSeed(x, y, z, seed)
local corner = Vector3.new(x * 16, y * 16, z * 16)
-- Şu anda, WriteVoxels() sıralı aşamada çağrılmalıdır
task.synchronize()
Workspace.Terrain:WriteVoxels(
Region3.new(corner, corner + Vector3.new(16, 16, 16)),
4,
voxels.materials,
voxels.occupancy
)
end)

En iyi uygulamalar

Paralel programlamanın maksimum faydalarını elde etmek için, Luau kodunuzu eklerken aşağıdaki en iyi uygulamalara başvurun:

  • Uzun Hesaplamalardan Kaçının — Paralel olsa bile uzun hesaplamalar diğer scriptlerin yürütmesini engelleyebilir ve gecikmelere neden olabilir. Çok sayıda uzun, yield etmeyen hesaplamalarla başa çıkmak için paralel programlamayı kullanmaktan kaçının.

    Paralel yürütme aşamasını aşırı yüklemenin hala gecikmelere neden olabileceğini gösteren diyagram
  • Doğru Sayıda Aktör Kullanın — En iyi performans için daha fazla Actors kullanın. Cihaz daha az çekirdek olsa bile, granülarite daha verimli yük dengelemesi sağlar.

    Daha fazla aktör kullanmanın yükü çekirdekler arasında nasıl dengelediğini gösteren örnek

    Bu, mümkün olan kadar çok Actors kullanmalısınız anlamına gelmez. Logic birimlerine göre Actors içinde kodunuzu bölmelisiniz; connected logic ile birbirine bağlı olan kodu farklı Actors bölmektense. Örneğin, ışın izleme doğrulamasını paralel olarak etkinleştirmek istiyorsanız, sistemin ölçeklenebilirliği açısından 4 çekirdekli sistemlere yönelik planladığınızda 4 yerine 64 Class.Actor|Actors kullanmak mantıklıdır. Bu sistemi ölçeklenebilir hale getirir ve altındaki donanımın yeteneklerine dayalı olarak işi dağıtmasına izin verir. Ancak, çok fazla Actors kullanmamalısınız; çünkü bu, yönetilmesi zor olabilir.

©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.