Teknikler ve dönüşüm

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

Bu kılavuz, oyun içindeki örnek akışını verimli ve etkili bir şekilde kullanmanın çeşitli tekniklerini özetlemektedir. Akış oyunu tasarlamak veya akış olmadan oyunu akışa dönüştürmek için "herkese uyan bir çözüm" olmadığından, bu yüksek seviyeli adımların takip edilmesi sizi çoğu noktaya ulaştıracaktır.

Akış özellikleri

StreamingEnabled Studio'daki Workspace nesnesi için açıldığında, ilgili özelliklerini aşağıdaki önerilen değerlere ayarlayın:

ÖzellikÖneri
EnableSLIMAvatarsUygun olduğunda standart iskelet avatarlarını hafif, animasyonlu stand-in'ler olarak işlemek için Enabled kullanın. Daha fazla bilgi için SLIM avatarlarına bakın.
ModelStreamingBehaviorImproved kullanarak BasePart alt nesnelerine sahip Modeller için en verimli akışı etkinleştirin.
StreamingIntegrityModeGereksiz yere veya çok sık duraklatmadan oyun oynama bütünlüğünü dengelemek için PauseOutsideLoadedArea kullanın.
StreamingMinRadiusDüşük son cihazlar için oyunun ne kadar ölçekleneceğini artırmak için varsayılan olan 64'ü kullanın.
StreamingTargetRadiusYüksek son cihazlar için oyuncuların görünürlüğü ile makul bir bellek ayak izi arasında iyi bir denge kurmak için varsayılan olan 1024'ü kullanın.
StreamOutBehaviorİstemcinin içeriği agresif şekilde bellek temizlemesine izin vermek için Opportunistic kullanın, bu da bellek kullanımını önemli ölçüde azaltır ve bellek tahsisi hatalarını önlemeye yardımcı olur.

Model detay seviyesi

Model.LevelOfDetail akışta olmayan Model içeriğini hafif kompozit veya sahte bir ağ ile doldurmaya yardımcı olur, böylece dünya görsel olarak tamamlanmış görünür. SLIM (Ölçeklenebilir Hafif Etkileşimli Model) kompozit ağlar özellikle etkilidir, çünkü oyuncular genellikle SLIM ağını tamamen akışa alınmış asıl modelden ayırt edemezler.

En iyi sonuçlar için:

  • Mekansal ve mantıksal olarak ilişkili parçaları gruplandırın, örneğin bir arabanın tüm parçaları.
  • Statik ağlar ve parçalar içeren modeller için LevelOfDetail'yi SLIM olarak ayarlayın. Animasyon oynatan veya çalışma zamanı sırasında değiştirilen ağlar desteklenmemektedir.
  • Her modelin mekansal boyutunu ~64 kübik stud altında tutun, böylece tüm gerçek modelin birlikte akışa alınma olasılığını artırın. Bir modelin çok büyük boyutları varsa, daha küçük modüler modellere ayırın ve her biri için uygun bir LevelOfDetail uygulayın.

Model yapısı

Model detay seviyesi ayarlamakla birlikte, Modeller'inizin yapısı ve ayarları akışın ne kadar iyi performans gösterdiği üzerinde önemli bir etkiye sahiptir. Mevcut bir oyunu geliştirirken veya dönüştürürken:

  • Mantıksal gruplama için atomik modeller kullanın — Bir script bir modelin içindeki tüm parçalara erişmesi gerektiğinde, ModelStreamingMode'sini Atomic olarak ayarlayın. Bu, istemci tarafı scriptlerinin modelin içindeki örneklere güvenli bir şekilde erişmesini sağlar ve WaitForChild()'in aşırı kullanımını önler (ancak bu tür scriptlerin genel atomik model için WaitForChild()'in kullanılmasını gerektirdiğini unutmayın).

  • Kalıcı modelleri en aza indirinKalıcı modeller, oyuna katıldıktan sonra yüklenir ve asla akıştan çıkmaz, bellek kaplar. Bir modelin ModelStreamingMode'sini yalnızca her zaman mevcut ve erişilebilir olması gerekiyorsa Persistent olarak ayarlayın.

  • Kapsayıcı modelleri parçalara ayırın — Tek bir devasa Model birden fazla NPC, nesne veya benzeri gruplar içeriyorsa, bu genellikle akış olmadan kullanılan bir düzendir. Akış altında, kapsayıcı modeller akış verimliliğini azaltır ve sıkı bir şekilde gruplandırılmış örneklerle en iyi çalışan model detay seviyesini optimize etmezler. Kapsayıcı modelleri, fiziksel olarak yakın veya mantıksal olarak ilişkili parçalara sahip daha küçük modellere parçalara ayırın.

  • Derinlemesine yerleşik model hiyerarşilerini düzleştirin — Bir kalıcı modelin içine yerleştirilen bir atomik model, atomik modelin kalıcı gibi davranmasını zorlar. Düz hiyerarşiler, akış altında düşünülmesi daha kolaydır.

SLIM avatarlar

Akışta olmayan alanın dışındaki platform avatarları varsayılan olarak görünmez, ancak Workspace.EnableSLIMAvatars etkinleştirildiğinde standart iskelet avatarları uygun olduğunda hafif, animasyonlu stand-in'ler olarak işlenir. Temelde, motor:

  • Gerçek bir avatar modeli akıştan çıktığında bir SLIM versiyonu işler.
  • SLIM/gerçek modeli akış yarıçapı içinde mevcut kaynaklara göre değiştirir, çünkü SLIM modeller tam çözünürlük modelinden çok daha az maliyetli olarak işlenebilir.
  • SLIM animasyonlarını sahne önemi ve bant genişliği ile sınırlar.

Avatar detay seviyesi sistemi, avatarlar için özel optimizasyonlar içerir. SLIM tarafından işlenecek veya işlenmeyecek şeyleri aşağıdaki şekilde tanımlar:

Script desenleri

Aşağıdaki script desenleri en çok akıştan etkilenmektedir. Doğru strateji, kodun amacına bağlıdır, bu nedenle her desen uygun yerlerde birden fazla seçenek listeler.

Alt nesnelere doğrudan dizin

Workspace alt nesnelerine . operatörü ile dizin oluşturmak, yol üzerindeki herhangi bir örnek akışta değilse bir hata fırlatır. FindFirstChild(), FindFirstChildWhichIsA() ve FindFirstChildOfClass() için de aynı durum geçerlidir; akışa alınmamışsa nil döner.

Alt Nesne Arama

local house1 = workspace:FindFirstChild("House1") -- "House1" akışta değilse nil
local door = workspace.House1.Door -- "House1" veya "Door" akışta değilse bozulur

Benzer bir desen, Player.CharacterAdded bağlantısı içinde Humanoid veya diğer karakter alt nesnelerine doğrudan erişirken ortaya çıkar. Akış altında, karakter modeli Workspace'e alt nesnelerinin tümü çoğaltılmadan önce ebeveynlenir, bu nedenle doğrudan dizinleme başarısız olur.

Karakter Alt Nesneleri

local Players = game:GetService("Players")
local player = Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
local humanoid = character.Humanoid
end)

Eğer script bir örneksiz ilerleyemiyorsa, bunun için WaitForChild() ile bekleyin:

Alt Nesne Arama

local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")

Uzaktan gönderilen örnekler

Bir RemoteEvent/RemoteFunction sinyali ve referans aldığı örnek bağımsız olarak hareket eder, bu nedenle sinyal, istemcide örnek mevcut olmadan önce gelebilir — ya da örnek hiç mevcut olmayabilir. İki muhtemel neden şunlardır:

  • Akış altında, bir parça/modelin sunucuda oluşturulması ile istemcilere çoğaltılması arasında hafif bir gecikme olabilir. Temelde, bir RemoteEvent/RemoteFunction tarafından referans alınan bir parça, akış alanında bile olmayabilir.

  • Bir parça/model referansını sunucudan istemciye bir RemoteEvent veya RemoteFunction aracılığıyla göndermek, örneğin alıcı istemciye çoğaltılmasını gerektirir. Bir örnek yolunu bir string olarak göndermek de aynı sorunu yaşar, çünkü yol istemcide mevcut olmayan bir konuma işaret edebilir:

    İstemci Scripti

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
    remoteEvent.OnClientEvent:Connect(function(data)
    local checkpoint = data.checkpoint -- "checkpoint" akışta değilse hatalı
    local level = workspace.Levels[data.levelPath] -- Yol akışta değilse hatalı
    end)

Eğer gönderilen istemci scripti ilerlemek için örneğe ihtiyaç duyuyorsa, kullanmadan önce WaitForChild() dahil edin. Bunun, örnek akışa gelmezse sonsuz bekleyebileceğini unutmayın, bu nedenle WaitForChild()'in ikinci parametresi olarak bir zaman aşımı eklemeyi düşünün.

İstemci senkronizasyonu

İstemci tarafı senkronizasyonu bir istisna olarak değerlendirilmeli, standart bir tasarım deseni olarak değil. İstemcide yalnızca kopyalar veya örneklerin yerel olarak yeniden ebeveynlenmesi ciddi sorunlar yaratabilir. Kodunuzu istemcide bu tür değişikliklerin kalıcı olmasına dayanan yerleri kontrol edin.

Örneğin, bir örneği ReplicatedStorage'dan Workspace'e yerel olarak yeniden ebeveynlemek, o örneği akıştan çıkma yeterliliği sağlar. Benzer şekilde, bir örneği Instance:Clone() ile ReplicatedStorage'dan Workspace'e yerel olarak çoğaltmak, artık sunucu yeniden çoğaltma boru hattının bir parçası olmayan istemciye özel bir kopya oluşturur ve orijinal sunucuya ait örnekten güncellemeler almaz.

Sunucuya ait bir nesne için istemcide Instance:Destroy() çağrısı yapıldığında aynı kavram geçerlidir. Bu, örneği yerel olarak kaldırır ancak sunucunun hala onu bulundurması nedeniyle, uygun olduğunda kendi orijinal durumu ile birlikte tekrar akışa alınacaktır.

Proaktif akış

Bir oyuncunun bir sonraki hedefinin tahmin edilebilir olduğu durumlarda, sunucu tarafında Player:RequestStreamAroundAsync()'a çağrılar yaparak geçici yükleme için geçici alanları akışa alın veya açıkça serbest bırakılıncaya kadar yüklenmesi gereken alanlar için Player:AddReplicationFocus()'u sınırlı bir ölçekte kullanın.

Örneğin, bir oyuncu karakteri başka bir oyuncunun evine uzak bir konuma CFrame değişimi ile ışınlanmak üzereyken, kaynağı önceden almak için hedef alanı akışa alabilirsiniz, böylece pop-in'i en aza indirir ve daha düzgün bir geçiş sağlarsınız. Aşağıdaki script, bir oyuncu karakterini önceden almak için bir istemci ile sunucu uzaktan olay tetiklemeyi göstermektedir. Önceden alma isteği başarılı olursa, hedef konum çevresindeki minimum yarıçap istemcide mevcut olmalıdır.

Sunucu Scripti - Oyuncu Karakterini Işınla

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- Hedef konum çevresinde akış talep et
player:RequestStreamAroundAsync(teleportTarget)
-- Karakteri ışınla
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- İstemci uzaktan olayı tetiklediğinde ışınlama fonksiyonunu çağır
teleportEvent.OnServerEvent:Connect(teleportPlayer)

Örnek özellik okuma

Bir örnek akıştan çıktıktan sonra, özellik güncellemeleri artık o istemciye çoğaltılmaz. BasePart.Position gibi özellikleri okumak devam eder ancak son çoğaltılan değeri döner, bu da istediğinizden oldukça eski olabilir.


local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- "target" akıştan çıktığında konum eski olabilir
local dist = (target.Position - player.Character.HumanoidRootPart.Position).Magnitude

Mantığı sunucuya taşıyın, çünkü sunucu tarafı scriptleri her zaman tüm örneklere erişebilir. Bu, mesafe kontrolleri ve diğer konuma duyarlı mantık için genellikle en güvenilir seçenektir.

Kritik yol üzerinde bekleme

Bazı akışsız oyunlar haritalarını ReplicatedStorage'dan Workspace'e klonlayarak yükler, ardından bir yükleme ekranını kapatmadan ve hazır olduğunu bildirmeden istemcide bekler. Akış altında bu işlemi sürekli bekletebilir — istemcinin karakteri henüz doğmadığı için burada bir çoğaltma odak noktası olmadığı için mekansal harita örneği asla akışa alınamaz.

Yükleme ekranı mantığını, özel mekansal bir örneğin mevcut olmasına bağlı kalmayacak şekilde taşıyın; örneğin, karakterin doğduğunda ve çevresinin akışa alındığında hazır olduğunu bildirin.

Sinyal değişikliği yönetimi

Instance.ChildAdded/Instance.ChildRemoved ve CollectionService sinyalleri gibi GetInstanceAddedSignal() veya GetInstanceRemovedSignal() gibi sinyaller de akış olan durumlarda tetiklenir, gerçek doğma veya kaldırma olayından ayırt edilemez. Alıcı scriptler, sinyalin kendisinden tek başına farkı anlamaz, bu nedenle bir sinyalin bir "gerçek" olayla ilişkilendirildiğini varsayan mantık güncellenmelidir.

Akış üzerinde tetiklendiğinde bozulan veya önemli ölçüde değişen herhangi bir sinyal dinleyicisi için scriptleri denetleyin. Örneğin, bir düşman NPC dünyaya ilk kez doğduğunda ses veya görsel efektler oynatıyorsanız, her düşmana ilk doğumda Spawned gibi bir özellik atayın ve düşmanın gelecekteki akışlarında aynı ses/efektleri yeniden oynatmayı atlayın.

Özellik Takibi

local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "Enemy"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- Düşmanın ilk doğumunda "Spawned" özelliğini ayarlayın
enemy:SetAttribute("Spawned", true)
-- Bu ilk doğum için ses/görsel efektleri oynatın
playSpawnEffects(enemy)
end
end)

Koleksiyonlar üzerinde yineleme

İstemci tarafında Instance:GetChildren() ve Instance:GetDescendants() gibi koleksiyonlara olan yinelemeler yalnızca akışta olan alt nesnelerin alt kümesini döndürür. Bu, ebeveynin kendisi her zaman yeniden çoğaltıldığında bile, örneğin mekanik alt nesnelerin içe dışa akış yapabileceği Folder gibi durumlarda geçerlidir.


local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- "Homes" klasörü her zaman çoğaltılır ama çocukları akışta olabilir
-- Bu döngü, şu anda akışta olmayan evleri atlayabilir
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
end

Tam bir tarama gerektiğinde, sunucuda taramayı gerçekleştirin ve gerekirse sonucu bir RemoteEvent aracılığıyla oyuncuya iletin.

Mekansal sorgular

İstemci tarafında WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox() ve Model:GetBoundingBox() gibi mekansal sorgular yalnızca akışta olan içerikleri yansıtır. Bunun bir problem olup olmadığı, sorgunun ne için kullanıldığına bağlıdır.

Sonuçların tam dünyayı yansıtması gereken sorgular için sunucuyu kullanın; örneğin, bir oyuncunun uzak bir hedefe görüş çizgisinde olup olmadığını kontrol eden bir ışın takip.

Diğer desenler

Aşağıdaki desenler de geçerli olabilir ve dikkatlice düşünülmelidir:

  • Bir Sound veya AudioPlayer, bir 3D nesneye ebeveynlendirilirse, o nesne akıştan çıktığında durur. Akıştan bağımsız olarak devam etmesi gereken ortam sesleri için, vericiyi kalıcı bir modele veya akışa girmeyen bir kapsayıcıya ebeveynlendirin.

  • Oyun içi UI nesneleri gibi BillboardGui veya SurfaceGui, ayrıca akıştan çıkan bir adornee veya bağlantı gibi görsel efektler (örneğin Beams veya Highlights) yalnızca akıştan çıktığında durur. Bu, istenen bir davranış olabilir, ancak doğrulayın.

  • BasePart.Touched olayları, ProximityPrompts, DragDetectors, ve ClickDetectors akışta bulunan parçaların/portların istemcisine sahip olmayan oyuncular için çalışmaz. Eğer etkileşimin herhangi bir mesafeden mümkün olması gerekiyorsa, modelin kalıcı olması gerekecek veya etkileşim farklı bir mekanizmaya ihtiyaç duyacaktır.

  • PathfindingService ve istemci tarafı yol bulma için, yol bulucu yalnızca istemcide akışta olan geometrileri görür ve sunucuda var olan engellerin içinden geçebilir. Burada stratejilerine bakın.

Gerçekçi test koşulları

Scripter güncellenince oyunu kapsamlı bir şekilde test edin. Akış hataları genellikle akış alanının kenarlarında veya geçişler sırasında ortaya çıkar, bu nedenle yalnızca doğma veya hedef yarıçapında test yapmak yeterli olmayabilir.

  • Workspace.StreamingTargetRadius'ı minimum değerine (64) ayarlayın. Bazı akış hataları yalnızca akış alanı küçük olduğunda görünür.

  • Oyunun tam geçiş desenlerinde oynayın, uzak alanlar arasında ışınlanın ve onları terk ettikten sonra bu alanları tekrar ziyaret edin. Bunlar, akışa alma ve akıştan çıkma işlemlerini en çok harekete geçiren durumlarıdır.

  • Aktif akış ayarlarını, şu anda yüklenmiş bölgeleri ve çalışma zamanı akış durumunu izlemek için akış hata ayıklama örtüsünü kullanın.

  • Hatalar için Output penceresini ve Geliştirici Konsolu izleyin, çünkü birçok script deseni hataları sessiz şekilde yanlış davranış yerine üretir. Sıklıkla attempt to index nil with ... biçimindeki hatalara dikkat edin, bu genelde eksik bir WaitForChild() çağrısını belirtir.

  • Tools ekipmanı giyin ve aktive edin, silahlar ateşleyin ve farklı oyun etkileşimlerini tetikleyin.

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