Bir sunucu yetki modelinde, sunucu, tüm oyun durumunun tek doğru kaynağıdır ve istemcilerin yalnızca kendi girdilerini rapor etmesine güvenilir. Bu mimari, bir istemcinin kendi konumunu veya durumunu rapor etmesine asla güvenmeyerek, uçuş hileleri veya hız hileleri gibi hilelerin tüm sınıflarını önlediği için adil, rekabetçi bir oyunun temel ağ kodu temelidir.
Avantajlar
Naif bir sunucu sahipliğinde, istemciler yalnızca girdilerini sunucuya gönderir ve sunucudan geri gönderilen oyun sonuçlarını görüntüler. Teknik olarak doğru olsa da, böyle bir sistem önemli girdi gecikmesi ile karşılaşır çünkü her oyuncu eylemi sunucuya gitmeli, işlenmeli ve sonuç istemciye geri gönderilmelidir. Çoğu oyun için, özellikle hızlı tempolu olanlar için, bu gidiş-dönüş gecikmesi, oyunun gecikmeli, yanıt vermeyen ve oynanamaz hissettirmesine neden olur.
Roblox'un sunucu yetki modelinde, gecikme, istemcilerin girdilerinin etkilerini anında tahmin etmesiyle telafi edilir ve bunları sunucuya göndermeye ek olarak yapılır. Örneğin, bir oyuncu bir tuşa bastığında, istemci sunucunun yanıt vermesini beklemez; bunun yerine, son bilinen sunucu durumunun birkaç kare öncesini tahmin eder. Bu, istemcinin girdi eyleminin sonucunu anında göstermesine olanak tanır, böylece ağ gecikmesini etkili bir şekilde gizler ve oyunun yanıt vermesini sağlar.
Bazen istemci tahminini yanlış yapar (misprediction) ve ağ gecikmesi nedeniyle, istemci bir hata yaptığını birkaç kare boyunca bilemez. Örneğin:
Bir yanlış tahmin tespit edildiğinde, istemci, sunucunun yetkili durumu temelinde tahminini düzeltmelidir. Yetkili durum, istemcinin tahmin edilen durumundan farklıysa, istemci, tahmin edilen karelerini geri almalı ve yeniden simüle etmelidir. Bu istemci tarafı tahmini, geri alma ve yeniden simülasyon sistemi "gecikme telafisi" olarak bilinir ve sunucu yetkili çok oyunculu oyunların pürüzsüz ve yanıt veren hissettirmesine yardımcı olur.
Kurulum
Sunucu yetki modeli, doğru çalışması için belirli diğer motor teknolojilerine ihtiyaç duyar. Workspace nesnesindeki Explorer üzerinde aşağıdaki özellik ayarlarını onaylayın:
- Workspace.AuthorityMode Server olmalıdır (bu ayar, otomatik olarak aşağıdaki beşini ayarlar).
- Workspace.NextGenerationReplication etkin olmalıdır.
- Workspace.PlayerScriptsUseInputActionSystem etkin olmalıdır.
- Workspace.SignalBehavior Deferred olmalıdır.
- Workspace.UseFixedSimulation etkin olmalıdır.
- Workspace.StreamingEnabled etkin olmalıdır.
Kavramlar
Sunucu yetki sistemi, aşağıdaki birkaç temel kavram üzerinde çalışır.
İstemci tahmini
İstemci tahmini aracılığıyla, istemci, oyuncu girdilerinin etkilerini hemen tahmin etmek için son bilinen sunucu durumunun birkaç kare öncesini simüle eder. Bu, girdi gecikmesini gizler, ancak tahmin daha sonra yanlış çıkabilir (istemci yanlış tahmini) ve bu nedenle düzeltme gerektirebilir. İstemci, girdilerinin sunucuya hedef karede ulaşabilmesi için son bilinen yetkili sunucu durumunun önünde yeterince ileri simüle etmeye çalışır. İstemcinin bilinen sunucu durumunun önünde tahmin edeceği kare sayısı, istemci ve sunucu arasındaki gecikmeye bağlıdır.
İstemci yanlış tahmini
İstemci, sunucudan yetkili durumu aldığında, bu durumu o kare için yerel olarak tahmin ettiği tarihsel bir kayıtla karşılaştırır. İstemcinin tahmin ettiği ile sunucunun gerçekten yaptığı arasında bir fark olduğunda, bu bir yanlış tahmindir. Yanlış tahminler, ağ gecikmesindeki değişiklikler, diğer oyuncuların istemcinin öngörmediği şekillerde hareket etmesi, oyunun belirli mantıkları yalnızca sunucuda çalıştırması gibi çeşitli nedenlerden kaynaklanabilir.
Yetkili durum, istemcinin tahmin edilen durumundan farklıysa, istemci geri almalı ve yeniden simüle etmelidir.
Geri alma ve yeniden simülasyon
Bir istemci bir yanlış tahmin tespit ettiğinde, sunucunun yetkili durumuna geri dönmeli ve ardından tahmin edilen kareye geri dönmek için yeniden simüle etmelidir. Ağ gecikmesine bağlı olarak, istemci, girdilerinin sunucuya hedef karede ulaşabilmesi için son bilinen yetkili sunucu durumunun önünde yeterince ileri simüle etmeye çalışır.
Özetle, istemci:
- Sunucudan yetkili durumu alır ve bunu kendi tahmin edilen durumu ile karşılaştırır.
- İstemcinin tahmini yanlışsa:
- İstemci, sunucudan alınan son bilinen yetkili duruma geri döner.
- İstemci, yetkili durumdan tahmin edilen durumuna yeniden simüle eder, yerel girdileri yeniden uygular.
Uygulama
Ağ sahipliği ve tahmin
Sunucu yetki modelinde, temel oyun nesnelerini sunucuya ait tutabilir ve genellikle sunucu sahipliği ile ilişkili olan girdi gecikmesi maliyetini üstlenmeden tutabilirsiniz. Arabalar, oyuncu karakterleri veya diğer oyun açısından kritik nesneler, diğer oyuncularla etkileşimde bulunurken bile sunucuya ait kalabilir.
Varsayılan olarak, Roblox, yerel oyuncunun Character nesnesine yakın olan simülasyon erişimi ile özellikleri otomatik olarak tahmin eder, ancak daha ayrıntılı kontrol istiyorsanız, bir nesnenin tahminini açıkça RunService:SetPredictionMode() ile zorlayabilirsiniz.
Otomatik tahmin, tüm fizik montajlarına uygulanır, bireysel nesnelere değil. İstemci bir parçayı tahmin ettiğinde, ayrıca, kaynaklar, eklemler veya kısıtlamalar aracılığıyla ona fiziksel olarak bağlı olan her parçayı, bu parçaların ana Model'ını ve o modelin içindeki herhangi bir Humanoid'i de tahmin eder. Örneğin:
- Tahmin edilen bir karaktere kaynaklanan bir kılıç modeli, karakterin montajının bir parçası haline gelir, bu nedenle otomatik olarak tahmin edilir.
- Karaktere bağlı ancak fiziksel olarak ona bağlı olmayan bir model ayrı bir montajdır. Sadece istemcinin simülasyon yarıçapı içinde veya RunService:SetPredictionMode() ile tahmini zorlamanız durumunda tahmin edilir.
Belirli bir nesnenin şu anda tahmin edilip edilmediğini kontrol etmek için istemciden RunService:GetPredictionStatus() çağrısını yapabilirsiniz.
Simülasyon senkronizasyonu
Sunucu yetki modelinde, istemci ve sunucu, temel simülasyonu çalıştırmalıdır ve istemcinin simülasyonu, bir yanlış tahmin meydana geldiğinde geri almalı ve yeniden simüle etmelidir. Bunu sağlamak için, temel mantığınızı, istemci ve sunucuda başlatılan bir ModuleScript içinde RunService:BindToSimulation() aracılığıyla bağlanmış fonksiyonlar içinde yazın.

Yeniden simülasyon sırasında, Roblox, BindToSimulation() aracılığıyla simülasyona bağlanan fonksiyonları yeniden çalıştırır. Oyuncu girdilerini işlemek, senkronize fizik nesneleriyle etkileşimde bulunmak ve temel oyun durumunu güncellemek, bu bağlı fonksiyonlar içinde yer almalıdır.
Zaman tabanlı mantık için, örneğin bir animasyon hızını sürdürmek veya bir değeri zamanla dalgalandırmak için, bağlı bir simülasyon fonksiyonu içinde time() kullanın. Workspace.AuthorityMode Enum.AuthorityMode.Server olduğunda, time() istemci ve sunucu arasında senkronize edilir ve sabit adım simülasyon zamanını kullanır. Yeniden simülasyon sırasında, yetkili kareye geri sarar ve istemci kareleri yeniden oynatırken ilerler, bu nedenle her simüle edilen karede tutarlı bir değer döndürür.
ModuleScript adı Simulation olan ReplicatedStorage içinde:
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Simulation = {}
Simulation.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- Oyuncu girdilerini oku
-- Oyun durumunu güncelle
end)
end
return SimulationDurum senkronizasyonu ile özellikler
Roblox, tahmin edilen nesnelerde simülasyon erişimi olan tüm özellikleri otomatik olarak senkronize eder. Özel veriler için, özellikler tahmin edilen nesneleri senkronize etmenin birincil yoludur; bu tür nesnelerde, sunucunun doğru kaynağı ile istemcinin tahmini arasındaki özellik değerlerindeki herhangi bir uyumsuzluk, tam bir geri alma ve yeniden simülasyon tetikler.
Özellik sınırlamaları
Bir özelliğin çoğaltılabilmesi için, aşağıdaki tüm kriterleri karşılaması gerekir:
- Instance üzerindeki ilk 64 özellikten biri olmalıdır.
- Adı en fazla 50 karakter içermelidir.
- Eğer bir dize türü özelliği ise, değeri en fazla 50 karakter içermelidir.
Simülasyon erişimi
Motor API referansındaki birçok özellik ve yöntem, Simülasyon Erişimi etiketini içerir, örneğin BasePart.CFrame. Bu etiketle işaretlenmiş özellikler, sunucu yetki sistemi tarafından tahmin edilecektir. Ayrıca, yalnızca bu etiketle işaretlenmiş özellikler ve yöntemler, RunService:BindToSimulation() ile bağlı fonksiyonlar içinde erişilebilir.
Nesneleri oluşturma ve kaldırma
BindToSimulation() aracılığıyla bağlı fonksiyonlar içinde, Instance.new(), Instance:Clone() veya Instance.fromExisting() ile nesneler oluşturabilirsiniz. İstemci, nesneyi hemen oluşturur ve Roblox, sunucunun yetkili kopyası geldiğinde bunu sunucunun yetkili kopyasıyla birleştirir. Ayrıntılar için, tahmin edici nesne oluşturma bölümüne bakın.
Nesneleri kaldırma işlemi farklı çalışır. Instance:Destroy() simülasyon erişimi yoktur ve DataModel içinde zaten bulunan bir nesnenin Parent'ını değiştiremezsiniz, bu nedenle bağlı bir fonksiyon içinde herhangi birini çağırmak bir hata oluşturur. Bunun yerine, simülasyon içinde bir özellik aracılığıyla bir nesneyi kaldırma niyetini kaydedin, ardından nesneyi simülasyon dışında, örneğin sunucudaki bir PostSimulation bağlantısında kaldırın.
local RunService = game:GetService("RunService")
local character = script.Parent
RunService.PostSimulation:Connect(function()
-- "SwordEquipped" oyuncu kılıcı çıkardığında simülasyon tarafından yazılır
local sword = character:FindFirstChild("Sword")
if sword and not character:GetAttribute("SwordEquipped") then
sword:Destroy()
end
end)Girdi eylemleri
Sunucu yetkili bir oyunda, bir istemcinin oyunun durumunu etkilemenin birincil yolu Girdi Eylem Sistemi aracılığıyladır. Bu girdiler sunucuya gönderilir ve yeniden simülasyon sırasında istemcide yeniden oynatılır. Sonuç olarak, InputActions temel simülasyonu etkileyen tüm girdiler için kullanılmalı ve işlenmeden önce geçerlilikleri kontrol edilmelidir.
InputContexts'in bir Player'ın alt öğesi olması gerektiğini unutmayın, böylece motor InputContext üzerindeki sahipliği bilebilir. Bir yaklaşım, InputContexts'inizi ReplicatedStorage altında bir klasöre eklemek ve her oyuncu için ServerScriptService altında bir Script kullanarak InputContexts'i kopyalamaktır:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")
local function onPlayerAdded(player)
local clone = InputsFolder:Clone()
clone.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
endBu deseni kullanarak, her iki istemci ve sunucuda RunService:BindToSimulation() içinde tüm oyuncular için InputActions'ı okuyabilir ve belirli bir kare için aynı verileri alabilir ve önceki kare girdisini bir özellik içinde kaydedebilirsiniz, örneğin bir RunAction girdi eylemi tetiklendiğinde bir karakterin koşmasını sağlamak için.
Uzaktan olaylar
Uzaktan olaylar, sunucu yetki modelinde istemci ve sunucu arasında belirli iletişimi kolaylaştırmak için hala kullanılabilir. Örneğin, sunucular, oyuncuların puan kazanması veya nesneleri toplaması hakkında veri yaymak için uzaktan olayları kullanabilir ve istemciler, sunucuya girdi göndermek için alternatif bir API olarak uzaktan olayları kullanabilir, örneğin düğmelere basma veya 3D dünyadaki nesnelere dokunma gibi.
Animasyonlar
Oyun oynanışını etkileyen animasyonlar, karakter hareketi veya saldırı animasyonları gibi, BindToSimulation() aracılığıyla bağlı fonksiyonlar içinde kontrol edilmelidir ve bu, hem istemci hem de sunucuda çalışan aynı ModuleScript içinde olmalıdır. Temel Animator ve AnimationTrack üyeleri, LoadAnimation(), Play(), Stop(), AdjustSpeed() ve TimePosition simülasyon erişimi vardır.
Animasyon durumu, tahmin edilen simülasyonun bir parçasıdır. Bir animasyon sırasında bir geri alma meydana geldiğinde, istemci animasyonu yetkili duruma geri sarar ve simülasyonun geri kalanıyla birlikte yeniden oynatır, böylece istemci ve sunucu animasyonları senkronize kalır. İstemci, bir geri alma sırasında animasyon izlerini değiştirebileceğinden, kareler arasında AnimationTrack referanslarını önbelleğe almayın. Bunun yerine, her karede canlı izleme Animator:GetTrackByAnimationId() ile bakın. Tam bir örnek için, animasyon kodu yazma bölümüne bakın.
Sesler ve efektler
İstemci tarafı efektleri, sesler ve parçacıklar gibi, istemci simülasyonunun yalnızca yetkili sunucu durumunun bir tahmini olduğunu bilerek yazılmalıdır. BindToSimulation() bağlı fonksiyonlar içinde çağrılabilecek özellikler ve yöntemler üzerinde kısıtlamalar getirir, böylece yalnızca senkronize simülasyon durumuna yazmanız konusunda sizi yönlendirir. Bu simülasyonun sonuçlarını görüntülemek, efektleri ve sesleri tetiklemek vb. işlemler, simülasyonun sonuçlarını okuyan ve istenen efektleri tetikleyen RenderStepped ile bağlantılı ayrı bir fonksiyonda yapılmalıdır.
İstemci, sunucuda asla gerçekleşmeyen bir olayı tahmin edebileceğinden, render kodunuz yanlış tahmin edilen efektleri geri alabilmeli veya gizleyebilmelidir. Tahmin edilen bir simülasyonu görüntüleme ile ilgili daha fazla rehberlik, sesleri ve görsel efektleri oynatma bölümünde ele alınmaktadır.
Örnek projeler
Bu belgelerin yanı sıra, aşağıdaki şablonlar size başlamanızda yardımcı olabilir:


