Arka Plan
Roblox, veri depolarına aracılığıyla DataStoreService ile API'leri sunar. En yaygın kullanım durumu bu API'leri kaydetmek, yüklemek ve kopyalamak içindir. Yani, oyuncunun ilerleme, satın alma ve diğer oturum özellikleriyle ilgili verileri kaydetmek için ilgili veriyle etiketlenmiştir.
Roblox'daki çoğu deneyim, bir oyuncu veri sisteminin bir formunu uygulamak için bu API'leri kullanır. Bu uygulamalar yaklaşımları farklıdır, ancak genellikle aynı seti sorunları çözmeyi heder.
Sıradan Sorunlar
Aşağıda, en çok çözmeye çalıştığımız oyun verileri sistemlerinin bazılarının çözmeye çalıştığı problemlerin bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazılarının bazıları
Hafıza Erişiminde:: DataStoreService istekleri web isteklerini oluşturur ve hızlı olarak işlemez. Bu, oturum sunucugirişsel bir yükleme için uygun bir başlangıçtır, ancak oynanışnormal yükleme ve yazma iş
- Bir oturumun başlangıcında ilk okuma
- Oturumun sonunda nihai oturum
- Düzenli aralıklarla senaryoda son yazın başarısız olduğu senaryoyu mitigasyon etmek için yazıyor
- Bir satın alma işlemi sırasında verilerin kaydedilmesini sağlar
Verimli Depolama: Tüm bir oyuncunun seans verilerini tek bir tabloda depolamak, birçok değeri atomik olarak güncellemenizi ve daha az isteklerde aynı miktarda veri işlemesini sağlar. Ayrıca, değerlerinizin çarpışma riskini ortadan kaldırır ve işlemleri daha kolay hale getirir.
Bazı geliştiriciler ayrıca kullanıcıların oluşturduğu büyük veri yapılarını sıkıştırmak için özel serileştirmeyi de uygulayabilir (genellikle oyun içi kullanıcı oluşturulmuş içerikleri kaydetmek için).
Replikasyon: Klientin bir oyuncunun verilerine düzenli erişimi gerekir (örneğin, UI'yi güncelleme). Klientin verilerini replikasyon etmek için genel bir yaklaşım, bu bilgileri her veri bileşeni için özelleştirilmiş replikasyon sistemleri oluşturmak zorunda kalmadan iletmenizi sağlar. Geliştiriciler genell
Hata Yönetimi: DataStores erişilemezse, çoğu çözüm bir tekrar denemesi mekanizması ve 'varsayılan' verilere dönüştürülmesi için bir çözüm mekanizması uygulayacaktır. Özel dikkat gerektirir, böylece geri verilen veriler 'gerçek' verilere üstesinden gelmez ve bu, oyuncuya açık şekilde iletilir.
Yeniden denemeler: Veri depoları erişilemezse, çoğu çözüm bir deneme mekanizması veya varsayılan verilere bir geçiş için bir çözüm için yeniden denemeyi destekler. Ayrıca, geçiş verilerinin "gerçek" verilere yazılmasını önlemek için özel dikkat etmeyi gerektirir.
Oturum kilidi: Tek bir oyuncunun verileri birden fazla sunucuda hafızanın içindeyse, bir sunucudaki bir oyuncu çıkışı gecikmiş olabilir. Bu, veri kaybı ve yaygın öğe tekrar yazma açığına yol açabilir.
Atomik Satın Alma İşlemleri:: Satın alma işlemlerini atomik olarak doğrula, ödüllendir ve alımların birden fazla kez kaybolmasını önlemek için kayıt altında tut.
Örnek Kod
Roblox, oyuncu veri sistemlerini tasarlamak ve oluşturmak için size yardımcı olmak için bir referans kodu sahiptir. Bu sayfanın geri kalanı, arka planı, uygulama ayrıntılarını ve genel notlarını inceleyecektir.
Studio'a modeli ithal ettikten sonra şu dizin yapısını görmelisiniz:
Arşitektür
Bu yüksek seviyeli grafik, örnekteki anahtar sistemlerini ve diğer deneyim bölümündeki kodla nasıl etkileşim kurduğunu gösterir.
Yeniden denemeler
Sınıf: DataStoreWrapper
Arka Plan
Tüm çıkartmalarınızı DataStoreService altında bir web isteği yaparak web isteğinizin başarılı olacağına dair garanti vermez. Bu durumda, DataStore yöntemleri hata verir ve bunları ele alabilirsiniz.
Veri depolama arızaları gibi bunları ele almaya çalışırsanız yaygın bir "oturttum" olabilir:
local function retrySetAsync(dataStore, key, value)
for _ = 1, MAX_ATTEMPTS do
local success, result = pcall(dataStore.SetAsync, dataStore, key, value)
if success then
break
end
task.wait(TIME_BETWEEN_ATTEMPTS)
end
end
Bu genel bir işlev için mükemmel bir tekrar deneme mekanizması olmasına rağmen, DataStoreService istekleri için uygun değildir, çünkü isteklerin sırasını garanti etmez. İsteklerin sırasını korumak önemlidir, çünkü DataStoreService istekleri devletle etkileşime girer. Aşağıdaki sen
- A isteği yapılır ve anahtarın değerini 1'e ayarlar.
- İstek başarısız olduğundan, 2 saniye içinde yeniden deneme planlanıyor.
- Yeniden deneme gerçekleşmeden önce, B'nin K değerini 2'ye ayarlar, ancak A'nın yeniden denemesi derhal bu değeri yazıyor ve K değerini 1'e ayarlar.
anahtardeğerinin en son sürümünde çalışmasına rağmen, UpdateAsync İsteklerinin işlenmesi hala geçersiz geçici devletleri önlemek için işlenmesi gerekir. UpdateAsync İsteklerinin işlenmesi hala geçersiz geçici devletleri
Oyuncu verilerimiz sistemi, DataStoreWrapper kullanır, bu da anahtar başına işlenmesi garanti edilen yeniden deneme sağlar.
Yaklaşım
DataStoreWrapper``Class.GlobalDataStore|DataStore yöntemlerine eşdeğer yöntemler sağlar: DataStore:GetAsync() , 0> Class.GlobalDataStore:SetAsync()
Bu yöntemler, çağrıldığında:
İstek bir sıraya eklenir. Her anahtarın kendi sırası vardır, gdzie istekler seri olarak işlenir. İstek eden subprocess yanıtlanana kadar yayınlanır.
Bu özellik ThreadQueue sınıfına dayanır, bu da bir coroutine'e dayanan görev planlayıcısı ve hız sınırıdır. Bir vaat döndürmek yerine, ThreadQueue şu andaki thread'i işlem tamamlandığına kadar yayınlandırır ve bir hata oluşursa hata ayılar. Bu, idmantik asenkron Lua modelleriyle daha
Bir istek başarısız olursa, yapılandırılabilir bir üstel geri alma ile tekrar deneyin. Bu geri alma, sıraya gönderilen çağrının ardından için kuyrukta güvence edilmiştir, bu yüzden sıraya girecek bir sonraki isteğe kadar garanti edilmiştir.
Bir istek tamamlandığında, istek metodu success, result şeklinde geri döndüğünde
DataStoreWrapper ayrıca, bir belirli anahtar için sırayı almak için yöntemleri gösterir ve stale istekleri temizler. Son seçenek özellikle sunucu kapatıldığında ve işleme sadece en son istekler olmadan herhangi bir istek olmadığında kullanışlıdır.
Kısıtlama
DataStoreWrapper Extreme senaryolardaki her veri depolama isteğinin (başarıyla veya başarısız) tamamlanmasına izin verilmesi gerektiğini takip eder, bununla birlikte, daha yeni bir istek bunu gereksiz kılarsa, stale istekler oyunun başlangıcı
Bir isteğin sırayı terk etmeye güvenli olduğu için intuitif bir kurallar setine karar vermek zor. Aşağıdaki sırayı göz önünde bulundurun:
Value=0, SetAsync(1), GetAsync(), SetAsync(2)
Beklenen davranış şu ki GetAsync()``1 ı döndürür, ancak en son yapılandırma nedeniyle SetAsync() isteğini sıraya kaldırdığı için, 1> 01> döndürür.
Mantıksal ilerleme, yeni bir yazma isteği eklenildiğinde, sadece en son okuma talepitibaren sadece kısa solgun istekleri günceller. UpdateAsync() , bu sistemin kullanılan tek işlem (ve bu sistemin hiç kullanılmayan tek işlem) olarak, her ikisi de okuma ve yazma için zorluklı olabilir
DataStoreWrapper bir UpdateAsync() isteğinin okunup/yazılmasına izin verileceğini ve/veya yazılacağını belirtmenizi gerektirebilir, ancak bu, zaman öncesi olarak oyuncu veri sistemimizde okunabilir/yazılabilir olmaz (siege kilit mekanizmasının içinde ayrıntılı ol
Sıraya çıktığından bu yana, bunun nasıl nasıl bu işlem işleneceğine karar vermek zor. Bir DataStoreWrapper isteği yapıldığında mevcut thread yanlış olarak kapatılır, tüm işlem tamamlandı
Sonuçta, basit yaklaşım (her talepişleyen) burada tercih edilir ve daha karmaşık sorunlar yaklaşıldığında daha açık bir ortam yaratır. Bu durumda, DataModel:BindToClose() ı
Oturum kilidi
Sınıf: SessionLockedDataStoreWrapperSessionLockedDataStoreWrapper
Arka Plan
Oyuncu verileri, sunucudaki hafızada saklanır ve sadece gerekli olduğunda yazılıp okunur. Web istekleri gerekli olduğunda anında okunur ve DataStoreService sınırlarını aşmayan yazılır.
Bu model aslında işlemesi için, bir servisin bir oyuncunun verilerini DataStore ile aynı anda yükleyebileceğinden çok önemlidir.
Örneğin, eğer sunucu A bir oyuncunun verilerini yüklerse, sunucu B sunucu A'nın kilidini açana kadar o verileri veri depolarından yükleyemez. Eğer kilit mekanizması yoksa, sunucu B, sunucu A'nın en son sürümünü memnuniyetle kaydederse, sunucu B'nin mem
Roblox sadece bir istemci'nin bir sunucuya sadece bir kere bağlanmasına izin verdiğini göz önünde bulundurarak, bir oturumun verilerinin bir sonraki oturum başladığında hep kaydedilmiş olacağını düşünemezsiniz. Aşağıdaki senaryolardan bazılarını dikkate alın, bir oyuncu sunucudan ayrılırsa:
- Server A, verilerini kaydetmek için bir DataStore isteği yapar, ancak istek başarısız olur ve birkaç tekrar denemesi gerekir. İtirme süresinde, oyuncu sunucuya katılır.
- Sunucu A çok fazla UpdateAsync() çağrısı yapar ve sınırlı bir şekilde işlem görür. Son kayıt isteği kuyruğa yerleştirilir. Sunucu isteği kuyruğa yerleştirilirken oyuncu sunucu B'ye katılır.
- A'daki bazı kodlar PlayerRemoving etkinliğine bağlı kalarak oyuncu verileri kaydedilmeden önce görüntülenir. Bu işlem tamamlandıktan önce oyuncu B'ye sunucuya katılır.
- Sunucunun A'nın performansı, oyuncu sunucuya B'ye katılana kadar son kaydın gecikmesine neden olur.
Bu senaryolar nadir olmalıdır, ancak meydana gel, özellikle bir oyuncu bir sunucudan başka birine hızlı bir şekilde bağlanır (örneğin, ışınlanırken). Bazı kötü niyetli kullanıcılar bu davranışı kötüye kullanmaya çalışabilirler (örneğin, ışınlanırken). Bu, öğe duplikasyonu e
oyuncuDataStore anahtarının ilk okunmasını sağlayarak bu zayıflığı giderir. Sunucu, sunucu atomu olarak anahtarın metnini aynı UpdateAsync() çağrısında ilk kez okur. Eğer bu kilit değeri me
Yaklaşım
SessionLockedDataStoreWrapper``DataStoreWrapper sınıfının etrafında bir meta-Wraper'dir. DataStoreWrapper Queue ve tekrar deneyin işlevlerini sağlar, bu da 0> SessionLockedDataStore0>'ın oturum kilitlenmesiyle desteklenir.
SessionLockedDataStoreWrapper her
Dönüşüm işlevi her istek için UpdateAsync için şu işlemleri yerine getirir:
Anahtarın erişime güvenli olduğunu doğrular, eğer değilse işlemi terk eder. "Güvenli erişim" ifadesi:
anahtarmetadatosu, kilit süresi dolduğundan daha az bir süre önce güncellenmiş olmayan bir LockId değeri içermez. Bu, kilit yerleştiren başka bir sunucunun saygısını gösterir ve kilit süresi dolduğunda görmezden gelir.
Eğer bu sunucu daha önce anahtarın metadatına kendi değerini LockId yerleştirmişse, bu değer hala anahtarın metadatında bulunur. Bu, bir başka sunucunun kilidini (genellikle süresi dolduğu için veya zorla) aldı
Class.GlobalDataStore:UpdateAsync()|UpdateAsync``Class.GlobalDataStore|DataStore işlemini yerine getirir. Örneğin, SessionLockedDataStoreWrapper 0> function(value) return value bitir0> ile çevirir.
İstekte geçen talepbağlı olarak, UpdateAsync şunu kilitler veya açar:
Anahtar kilitli olacaksa, UpdateAsync , anahtarın metadılarındaki LockId'yı bir GUID olarak kaydeder. Bu GUID, sunucunun hafızasında depolanır, böylece kilidi sonraki kez er
Anahtar kilidi açılacaksa, UpdateAsync anahtariçindeki LockId kaldırır.
Aşağıdaki DataStoreWrapper içine özel bir tekrar deneme eşenekleri geçilir, böylece işlem 1 adımda kilitlenen oturum nedeniyle iptal edilirse tekrar denemesi yeniden deneme işlemi yapılır.
Oyuncu veri sisteminin oturum kilidi için ses kilidi rapor etmesi durumunda alternatif bir hata rapor etmesine izin veren özel bir hata mesajı da tüketiciye döndürülür.
Kısıtlama
Oturum kilit mekanizması, bir anahtarın kilidini her zaman bir anahtarın kilidini açtığında, bir oturum kilit için her zaman bir anahtar serbest bırakarak güvenilir. Bu, bir anahtarın PlayerRemoving veya Class.DataModel:BindToClose()|BindToClose() içindeki bir bileşen olarak</
Ancak, kilidi bazı durumlarda başarısız olabilir. Örneğin:
- Sunucu çöktü veya DataStoreService tüm anahtariçin işlevsiz hale geldi.
- Aynı mantıksal bir hata veya benzer bir hata nedeniyle, anahtarın kilidini açma talimatı yapılmadı.
Bir anahtarın kilidini korumak için, onu belleğe yükleninceye kadar düzenli olarak erişmelisiniz. Bu, normalde oyunun arka planındaki otomatik kaydetme çevirimi içinde çalışan bir otomatik kaydetme çevirimi olarak yapılır, ancak bu sistem ayrıca manuel olarak yapmanız gereken durumda bir refreshLockAsync metodu da gösterir.
Kilit süresi dolmasına rağmen güncellenmediğinde, herhangi bir sunucu kilidi ele geçirebilir. Eğer farklı bir sunucu kilidi alırsa, mevcut sunucunun okuması veya yazması gereken anahtarı okuması veya yazması gerekir.
Geliştirici Ürün İşlemesi
Singleton: ReceiptHandler ”
Arka Plan
ProcessReceipt çağrısı, satın alma işleminin nihayetlenmesi için kritik bir işi yerine getirir. ProcessReceipt , sehr belirli senaryolarda çağrılır. Satın alma garantilerinin seti için, MarketplaceService.ProcessReceipt görün.
Bir satın alma işleminin tanımı deneyimler arasında farklı olabilir, ancak aşağıdaki kriterleri kullanırız
Satın alma daha önce işlenmedi.
Satın alma işlemi mevcut oturumda yansıtılır.
Bu, PurchaseGranted işlemini geri döndürmeden önce aşağıdaki işlemleri yapmanız gerekir:
- PurchaseId ile ilgili olmayan bir kaydın olup olmadığını doğrula.
- oyuncuiç bellekli verilerinde satın alma işlemini ödüllendir.
- oyuncuPurchaseId kaydedilen PurchaseId adlı kaydı işleyin.
- Oyuncunun DataStoreClass.GlobalDataStore|DataStore 'a yazın.
Oturum kilidi, bu akışı basitleştirir, çünkü artık şu senaryolardan endişelenmenize gerek yok:
- Mevcut sunucudaki hafıza oyuncu verileri potansiyel olarak güncelli olabilir, bu nedenle DataStore tarihini doğrulmadan önce PurchaseId dan en son değer alınması gerekir
- Aynı sunucuda gerçekleştirilen aynı satın alma için çağrı, tüm PurchaseId geçmişini okumak ve yazmak ve güncellenen oyuncu verilerini satın alma işlemini atomik olarak kaydetmek gerekir, böylece yarış koşullarını önlemek için
Oyuncunun DataStore 'ine yazma denemesi başarılı olursa, diğer sunucularda oyuncunun DataStore 'ine hiç yazılmaz veya yazılır. Bu, verilerin bu sunucuda yüklenip kaydedilmesi sırasınd
Yaklaşım
ReceiptProcessor iletişim kutusunun içindeki yorumlar yaklaşımı vurguluyor:
oyuncuverilerinin bu sunucuda yüklendiğinden ve herhangi bir hata olmadan yüklendiğinden emin olun.
Bu sistem oturum kilidi kullanıyor, bu nedenle bu kontrol ayrıca hafıza içindeki verilerin en son sürüm olduğunu doğruluyor.
Oyuncu'nun verileri henüz yüklenmedi (bu, bir oyuncu bir oyuna katıldığında beklenen şeydir), oyuncu'nun verilerini bekleyin. Ayrıca, oyuncu'nun verilerini ayrıldığından beri bu satın alma işleminin bu sunucuda yeniden çağrılmasının önlenmesi için sistem dinlenir (bu, süresiz olarak yeniden çağrılmasını
PurchaseId ile ilgili olarak oyuncu verilerinde işlenmediğinden emin olun.
Oturum kilidi nedeniyle, sistemin belleğindeki PurchaseIds matrisi en yeni versiyonu kaydediyor ve PurchaseId içine k
Satın almayı "ödüllendirmek" için bu sunucudaki Oyuncu Verilerini yerel olarak güncelle.
ReceiptProcessor genel bir çağrı yaklaşımı kullanır ve her DeveloperProductId için farklı bir çağrı atar.
PurchaseId ı depolamak için bu sunucudaki oyuncu verilerini yerel olarak güncelle
İçerikteki verileri DataStore 'a kaydetmek için bir istek gönderin, PurchaseGranted ise NotProcessedYet eğer istek başarılı ise 2>İşlenmedi2> döndürür.
Bu kaydetme isteği başarısız olursa, oyuncunun iç bellek oturum verilerini kaydetme isteği daha sonra başarılı olabilir. Sonraki ProcessReceipt çağrısında, adım 2 bu durumu ele alır ve PurchaseGranted döndürür.
Oyuncu Verileri
Kısayolluklar: PlayerData.Server > , PlayerData.Client >
Arka Plan
Oyun kodu için bir arayüz sağlayan modüller Roblox deneyimlerinde yaygındır. Bu bölüm PlayerData.Server ve PlayerData.Client ile ilgilidir.
Yaklaşım
PlayerData.Server ve PlayerData.Client takip edilenkonuları işleyin:
- oyuncuverilerini hafıza içine yükleniyor, yüklemeyi başarısız yapan durumlarda dahil olmak üzere
- Oyuncu verilerini sorgulamak ve değiştirmek için bir arayüz sağlamak
- oyuncuverilerinde değişiklikleri kaydederek, kullanıcı koduna erişebilmesi için
- Hataları gösterebilmesi için kliye yükleme veya kaydetme hatalarını yeniden oluşturuyor
- Oyuncunun verilerini periyodik olarak kaydetme, oyuncu ayrıldığında ve sunucu kapandığında
Oyuncu Verileri Yükleniyor
SessionLockedDataStoreWrapper data mağaza'a bir getAsync isteği yapar.
Eğer bu istek başarısızsa, varsayılan veriler kullanılır ve profil "hata" olarak işaretlenir, böylece veriler daha sonra veri depolarına yazılmaz.
Alternatif bir seçenek oyuncuyu atlamak, ancak oyuncunun varsayılan verilerle oynamasını sağlamak ve oyunu çıkarmak yerine girişimden ayrılmasını temizlemek öneririz.
Bir başlangıç uyanıklığı, PlayerDataClient ile yüklenen verileri ve hata durumunu içeren bir özgürlükçü yük içerir.
Oyuncu için waitForDataLoadAsync kullanılarak herhangi bir bağlantı askıya alınır.
Sunucu Kodu için Bir Arayüz Sağlamak
- PlayerDataServer bir teknik olup aynı çevreçalışan herhangi bir sunucu kodu tarafından gerekli ve erişilebilir.
- Oyuncu verileri bir anahtar ve değer sözlüğüne düzenlenmiştir. Bu değerleri sunucudaki setValue , getValue , updateValue ve 2>Player2> yöntemleri aracılığıyla manipüle edebilirsiniz. Bu yöntemlerin hepsi, verileri yüklemeyi gerektirmeyen bir şekilde çalışır.
- hasLoaded ve waitForDataLoadAsync yöntemleri, verilerin yüklendiğinden emin olmak için kullanılabilir. Bu, diğer sistemlerin başlatılmasından önce yükleme ekranında bir kez yapılmasını öneririz.
- Bir hasErrored yöntemi, oyuncunun başlangıç yüklemesi başarısız olduğunda sorabilir, böylece varsayılan verileri kullanır. Bu yöntemi hasErrored olmadan oyuncu satın alma işlemlerine izin vermeden önce kontrol edin, çünkü satın alma işlemleri başarısız olabilir.
- Bir playerDataUpdated sinyali, player , key ve 1> value1> ile herhangi bir anda değiştirilmiş oyuncunun verilerini değiştirir. Bir kişisel sistem buna abone olabilir.
Değişiklikleri Klient'e Replikasyon
- Oyuncu verilerinde herhangi bir değişiklik PlayerDataServer içindeki herhangi bir değişiklik PlayerDataClient içine kopyalanır, aksi takdirde setValueAsPrivate kullanılarak özel olarak etiketlenmiş değilse
- setValueAsPrivate kullanıcıya gönderilmeyecek anahtarları ifade eder
- PlayerDataClient , bir anahtarın değerini alma (alın) ve güncellendiğinde ateşlenen sinyali içerir. A hasLoaded metodu ve bir loaded sinyali de dahil edilmiştir, böylece kliğın sistemlerini başlatmadan önce verileri yükleme ve kopyalama için bekleyebilir
- PlayerDataClient bir teknik özellik oluşturucudur ve aynı çevreçalışan herhangi bir kod tarafından gerekebilir ve erişilebilir
Client'a Hataları Replikasyon
- Oyuncu verilerinin kopyalanması veya yüklenmesi sırasında PlayerDataClient ile karşılaşılan hata durumları.
- Bu bilgiyere getLoadError ve getSaveError yöntemleri ile, loaded ve 1>Saved1> sinyalleri ile erişin.
- İki tür hata vardır: DataStoreError (DataStoreService isteği başarısız) ve SessionLocked (1> Oturum kilidi1> görünüyor).
- Bu etkinlikleri kullanarak müşteri satın alma ekranlarını devre dışı bırakın ve uyarı diyaloglarını uygulayın. Bu görsel bir öğretici diyalog gösterir:
Oyuncu Verileri Kaydediliyor
Oyuncu oyundan ayrıldığında, sistem aşağıdaki adımları izler:
- Oyuncunun verilerini veri mağazayazmak güvenli olup olmadığını kontrol edin. Güvenli olmayan senaryolarda oyuncunun verileri yüklemeyi başaramaz veya hala yükleniyor.
- Mevcut veri değerini hafıza ve oturum kilidini kaldırmak için şu şekilde bir istek gönderin: SessionLockedDataStoreWrapper
- oyuncuverilerini (ve diğer değişkenleri, örneğin metadatlar ve hata durumları) sunucudaki hafızadan temizler.
Düzenli bir döngüde, sunucu her oyuncunun verilerini veri depolarına yazıyor (kaydedilmesi güvenli olduğu takdirde). Bu hoşgeldiniz geçersizliği, bir sunucu kaybı durumunda kayıp olma riskini azaltır ve ayrıca oturum kilidini korumak için gereklidir.
Sunucunun kapatılması istenildiğinde, şunu BindToClose çağrısında görür:
- Bir istek, bir oyuncunun sunucuda herhangi bir verisini kaydetmesini sağlar, bir oyuncu sunucudan ayrıldığında normalde işlenen süreci izleyerek. Bu istekler paralel olarak yapılır, çünkü BindToClose çağrılarının sadece 30 saniye süresi vardır.
- Kayıtları hızlandırmak için, her bir anahtarın sırasındaki tüm diğer istekler DataStoreWrapper (görüntülenen Yeniden deneyin) ile temizlenir.
- Çağrı, tüm isteklerin tamamlanana kadar iade edilmez.