Değişen oyuncu verilerinin yanı sıra değişen tasarımcı verilerini yönetmenin yolları


14

Oyuncuların dünyayı bir şekilde şekillendirdiği çevrimiçi bir oyunum var - örn. Ultima Online'ın evlerinizi doğrudan dünya haritasının belirli kısımlarına inşa edebileceğiniz konutları. Bunlar, kalıcı dünyanın bir parçası olarak zaman içinde devam etmesi gereken değişikliklerdir.

Aynı zamanda, tasarım ekibi yeni içerikler ekliyor ve yeni oyuncular için oyunu geliştirmek ve genişletmek için eski içeriği değiştiriyor. Bunu test sırasında önce bir geliştirme sunucusunda yapacaklar ve daha sonra çalışmalarını canlı sunucudaki oyuncuların "çalışmaları" ile birleştirmek zorunda kalacaklar.

Oyun tasarımı sorunlarını giderdiğimizi varsayarsak - ör. oyuncular yalnızca belirlenmiş alanlarda inşa edebilirler, bu nedenle coğrafi olarak tasarımcı düzenlemeleriyle çatışmazlar - yeni tasarımcı verileri yeni oyuncu verileriyle birleştirildiğinde çakışmaları önlemek için verileri işlemenin veya veri yapılarını düzenlemenin iyi yolları nelerdir?

Örnek 1: Bir oyuncu yeni bir tür eşya üretir ve oyun buna 123456 kimliğini atar. Bu öğenin örneklerinin tümü 123456'ya işaret ediyor. Şimdi oyun tasarımcılarının benzer bir sistemi olduğunu ve bir tasarımcının 123456 numaralı yeni bir öğe oluşturduğunu hayal edin. Bu nasıl önlenebilir?

Örnek 2: Birisi tüm ejderhalarınıza Fransız aksanı veren popüler bir mod yapar. assignFrenchAccentHer ejderha nesnesine yeni ses varlıklarını atamak için kullandıkları yeni bir nesne içeren bir komut dosyası içerir . Ama aynı adı taşıyan bir nesneye sahip "Napoleon vs Smaug" DLC'nizi dağıtmak üzeresiniz - bunu müşteri hizmetleri problemleri olmadan nasıl yapabilirsiniz?

Aşağıdaki stratejileri düşündüm:

  • 2 ayrı dosya / dizin / veri tabanı kullanabilirsiniz, ancak okuma işlemleriniz oldukça karmaşıktır. "Tüm Öğeleri Göster" tasarımcı DB üzerinde bir okuma ve DB oynatıcısında bir okuma gerçekleştirmelidir (ve yine de 2'yi bir şekilde ayırmak zorundadır.)
  • Bir mağazada 2 farklı ad alanı kullanabilirsiniz, örn. birincil anahtar olarak dizeleri kullanmak ve "DESIGN:" veya "PLAYER:" ile önek kullanmak, ancak bu ad alanlarını oluşturmak önemsiz olabilir ve bağımlılıklar net olmayabilir. (örn. RDBMS'de, dizeleri etkili bir şekilde birincil anahtar olarak kullanamayabilirsiniz. Tamsayıları kullanabilir ve tasarımcı gibi birincil sayıların altındaki belirli bir sayının altındaki tüm birincil anahtarları ayırabilirsiniz. Ancak bu bilgiler RDBMS tarafından görülemez ve yabancı anahtar bağlantıları 'bölünmeyi' aşacaktır, yani tüm araçların ve komut dosyalarının açıkça etrafta çalışması gerekir.)
  • Her zaman aynı paylaşılan veritabanında gerçek zamanlı olarak çalışabilirsiniz, ancak performans düşük olabilir ve oyuncu verilerine zarar verme riski artabilir. Ayrıca, farklı dünya verileri olan 1'den fazla sunucuda çalışan oyunlara da uzanmaz.
  • ... başka fikirleriniz mi var?

Bana göre bu, öncelikle çevrimiçi oyunlar için bir sorun olsa da, kavramların modding için de geçerli olabileceği, topluluğun geliştiricilerin oyunlarını yamaladığı aynı zamanda modlar oluşturduğu yerlerde. Yeni yamalar çıktığında modun kırılma olasılığını azaltmak için burada kullanılan herhangi bir strateji var mı?

Ben de bunu "sürüm kontrolü" olarak etiketledim çünkü bir düzeyde bu ne olduğunu - birleştirilmesi gereken veri geliştirme 2 dalları. Belki de bazı yönler bu yönden gelebilir.

DÜZENLEME - sorunu netleştirmeye yardımcı olmak için yukarıda bazı örnekler eklendi. Sorunun gerçekten kompozit anahtarlar aracılığıyla bir mağazada uygulanabilen ad boşluklarından biri olduğunu düşünmeye başlıyorum. Bu en azından birleştirme stratejisini basitleştirir. Ama görmediğim alternatifler olabilir.


1
Bunun cevabının en azından kısmen tasarımcıların ne tür veriler eklediğine ve oyuncuların ne eklediğine bağlı olabileceğini düşünüyorum.
lathomas64

Olabilir, ancak her ikisi de tek bir veri deposuna katkıda bulunan 2 partiye genel çözümlerle daha fazla ilgileniyorum.
Kylotan

1
Pek çok insan bu sorunun noktasını kaçırıyor - oyuncuların çelişkili değişiklikleri değil: içerik güncellemeleri vb. Mevcut düzenleri bozuyor. @Kylotan haklı mıyım?
Jonathan Dickinson

Geliştirici içerik güncellemelerinin oynatıcı içerik güncellemeleriyle çakışabileceği yer burasıdır. Oyun tasarımı geçici çözümleriyle gerçekten ilgilenmiyorum (örneğin, oyuncuların yalnızca belirli yerlerde oluşturmalarına izin verin), ancak veri yapısı geçici çözümleriyle (örneğin, yalnızca oyuncuların 1 milyondan fazla kimlikli şeyler oluşturmalarına izin verin).
Kylotan

2
Siz belirtmediniz, canlı bir dünyada gerçek zamanlı güncellemeler yapmayı mı bekliyorsunuz? Bir yan not: Tek bir veri deposuna katkıda bulunan 2 taraf bir veritabanıdır, veritabanları bunu yapar, bu gerçeği alamazsınız ve paylaşılan verilerle ilgili sorunların nasıl önleneceğine dair onlarca yıllık bilgiyi göz ardı etmek aptalca olur.
Patrick Hughes

Yanıtlar:


2

Bence DB çözümleri öneren cevaplar sorunu anlamadan belirli bir uygulamaya atlıyor. Veritabanları birleştirmeyi kolaylaştırmaz, size verilerinizi depolamanız için bir çerçeve sağlar. Çatışma, DB'de olsa bile yine de bir çakışmadır. Ve kontrol etmek, fakir bir adamın soruna çözümüdür - işe yarayacak, ancak kullanılabilirliğiniz için sakat bir maliyetle.

Burada konuştuğunuz, sorunun dağıtılmış geliştirme modeline giriyor. İlk adım, oyuncuları ve tasarımcıları ayrı içerik yaratıcıları olarak düşünmemek. Bu, probleminizi çözümü etkilemeyen yapay bir boyutu kaldırır.

Etkin bir şekilde ana hattınız var - kanonik, geliştirici onaylı sürüm. Muhtemelen başka şubeleriniz de olabilir - canlı sunucular insanların aktif olarak modlar geliştirip paylaşıyorlardı. İçerik herhangi bir şubeye eklenebilir. En önemlisi, tasarımcılarınız burada özel bir şey değil - sadece evde yaşayan içerik yaratıcıları (ve onları bulup vidalandıklarında vurabilirsiniz).

Ardından, kullanıcı tarafından oluşturulan içeriği kabul etmek standart bir birleştirme sorunudur. Değişikliklerini ana hatta geri çekmeli, birleştirmeli, sonra tekrar dışarı itmeli veya ana hat değişikliklerini şubelerine çekmeli ve birleştirmelisiniz (kullanıcı tarafından oluşturulan şeylerin ana hattını 'temiz' bırakarak). Her zamanki gibi, şubenize çekmek ve düzeltmek, diğer insanlardan değişikliklerinizi çekmelerini istemekten ve daha sonra onları sonunda düzeltmeye çalışmaktan daha dostudur.

Bu tür bir modelle çalıştıktan sonra, birleştirme çatışmalarından kaçınmayla ilgili tüm normal işlemler uygulanır. Bazıları daha açık:

  • Belirli bir yazarın / modun / ekibin içeriklerini halka çit haline getirmek için ad alanlarının liberal kullanımını teşvik etmek
  • İçeriğin etkileşim kurması gerektiğinde, geri dönüşü kolaylaştıracak şekilde geliştirmeyi yönlendiren net arama / kullanım kuralları, adlandırma kuralları ve diğer gevşek 'kurallar' oluşturun. İçerik oluşturucuların, ideal olarak içerik oluşturmanın kendisine entegre edilmiş olan bu kurallara uyup uymadıklarını bilmelerini sağlayan araçlar sağlayın.
  • Muhtemel birleştirme hatalarını ortaya çıkmadan önce tespit etmek için raporlama / analiz araçları sağlayın. Birleştirme sonrası düzeltmek muhtemelen çok acı vericidir. Belirli bir miktar içeriğin kontrol edilmesine ve hepsine birleştirmeye hazır olarak net bir şekilde verilmesini sağlayın, böylece birleştirme ağrısız olur
  • Birleştirme / entegrasyonunuzu sağlamlaştırın. Kolay geri almalara izin verin. Birleştirilmiş içeriğin titizlikle testini yapın: eğer test başarısız olursa, birleştirmeyin! Birleştirme temiz bir şekilde devam edene kadar içeriklerini veya sizinkini yineleyin.
  • Hiçbir şey için artımlı tamsayı kimliklerini kullanmaktan kaçının (bunları içerik oluşturuculara göndermenin güvenilir bir yolu yoktur). Bu sadece bir DB'de çalışır, çünkü DB'nin kendisi kanonik bir kimlik sağlayıcısıdır, böylece hiçbir zaman kopya almazsınız; ancak sisteminize tek bir hata / yük noktası da ekler.
  • Bunun yerine GUID'leri kullanın - depolamanın maliyeti daha fazladır, ancak makineye özeldir ve bu nedenle çarpışmalara neden olmaz. Alternatif olarak dize tanımlayıcıları kullanın, bu hata ayıklamak / çözmek çok daha kolaydır, ancak depolama ve karşılaştırma için daha pahalıdır.

Ne yazık ki bunların bir kısmı sorunum için yararlı değil (örneğin, oyuncuların otomatik olarak sunucu tarafında yapılması gerektiğinden belirli kurallara uyması) ve birleştirme yönetimi ve işlem derecesini desteklemenin pratik olacağını düşünmüyorum Söylediğiniz anlambilim, ancak garantili benzersiz kimlikler, belki GUID'ler tahsis etme genel yaklaşımı, muhtemelen gideceğim şeylere en yakın olanıdır.
Kylotan

Ah, anlıyorum. Yapı araçlarını kontrol ettiğiniz için, en azından bu birleştirme dostu yaklaşımları (ad alanları vb.) Uygulamak, oyuncular kabul etmek zorunda kalmadan yapabileceğiniz bir şeydir.
MrCranky

İki oyuncu yinelenen içerik oluşturuyorsa ne yaparsınız? Yoksa gameworld'ünüzün ayrı örnekleri benzersiz olarak değerlendiriliyor mu? Bu durumda, çekirdek / ana hat şubenize karşı bildiğiniz her benzersiz örneği, örneklerde bu değişiklikleri uyguladığınızda oluşabilecek çatışmalar için otomatik olarak kontrol etmek yararlı olabilir. Oyuncuları kontrol edemezseniz, en azından iç ekibinizi, yaptıkları işin, dünyanın ilk örneği X ile, geliştirmenin başlangıcında çatıştığı konusunda uyarabilirsiniz.
MrCranky

İsim alanları kavramı pek sorun değil - tüm olası isim alanlarının isim alanlarından yeterli isim alanları seçmek! :) Ve yinelenen içerik benim için sorun değil - eşdeğer bir şeyin sadece 2 örneğidir. Önemli olan, hiçbir zarar birleştirme veya üzerine yazma olmamasıdır. Otomatik çarpışma kontrollerine gelince, bu yazma sırasında verilen hasarı durdurur, ancak orijinal adlandırma sorununu çözmez. (Bir çarpışmadan kaçınmak için işleri yeniden adlandırmak, çapraz referanslama nedeniyle önemsiz olabilir.)
Kylotan

Ah evet, şimdi görüyorum, isim seçimi kadar isim alanlarının kendisi değil. Bu durumda, GUID'ler muhtemelen tekrar cevaptır - içeriğin kendi küçük alanında etkili bir şekilde tutulması. Dekoratif bir ad verilebilir, ancak oyun GUID'yi kullanır.
MrCranky

1

Her şeyi bağlama noktaları ile bir özellik (veya dekoratör) olarak saklayın. Oyuncunun örnek olarak tasarladığı bir evi ele alalım:

o House: { Type = 105 } // Simple square cottage.
 o Mount point: South Wall:
  o Doodad: Chair { Displacement = 10cm }
   o Mount point: Seat:
    o Doodad: Pot Plant { Displacement = 0cm, Flower = Posies } // Work with me here :)
 o Mount point: North Wall:
  o Doodad: Table { Displacement = 1m }
    o Mount point: Left Edge:
     o Doodad: Food Bowl { Displacement = 20cm, Food = Meatballs}

Böylece her varlık bir veya daha fazla bağlama noktasına sahip olabilir - her bir bağlama noktası sıfır veya daha fazla başka bileşeni kabul edebilir. Bu veriler , kaydedildiği sürümle ve ilgili özelliklerle (örneğimdeki Yer Değiştirme vb.) Birlikte depolanır - NoSQL muhtemelen buraya gerçekten iyi uyum sağlar (Key = Entity ID, Value = Serialized Binary) Veri).

Daha sonra her bileşenin eski verileri önceki bir sürümden 'yükseltmesi' gerekir (alanları asla serileştirilmiş verilerden kaldırmaz - yalnızca 'boş' olur) - bu yükseltme, yüklendiği anda gerçekleşir (daha sonra hemen geri depolanır kullanılabilir son sürüm). Diyelim ki evimizde boyutları değişti. Yükseltme kodu, kuzey ve güney duvarları arasındaki mesafeyi göreceli olarak çözecek ve içerdiği tüm varlıkların yer değiştirmelerini orantılı olarak değiştirecektir. Başka bir örnek olarak et kabımız 'Yiyecek' alanını kaldırmış olabilir ve bunun yerine 'Çeşitlilik' (Et) ve 'Tarif' (Toplar) alabilir. Yükseltme betiği 'Meat Balls'u' Meat ',' Balls 'haline getirecektir. Her bileşen ayrıca montaj noktalarındaki değişikliklerle nasıl başa çıkacağını da bilmelidir - ör.

Bu tamamen bir sorunu açık bırakır: iki nesne birbiriyle çatışırsa ne olur (konteyner montaj noktaları sizi bundan korur)? Bir yükseltmeden sonra çarpışmaları kontrol etmeli ve bunları çözmeye çalışmalısınız (bir şeyleri biraz SAT gibi hareket ettirerek). Çarpışmayı nasıl çözeceğinizi anlayamıyorsanız, nesnelerden birini kaldırın ve bir zemine yerleştirin - kaldırılan bu ürünleri (ücretsiz) satın alabilecekleri veya satabilecekleri (tam fiyata); ve oyuncuya yükseltme işleminin düzeninin bir kısmını bozduğunu, muhtemelen sorunu görebilmeleri için 'yakınlaştır' özelliğiyle bildirin.

Nihayetinde, hiçbir algoritma estetiği açıklayamadığı için oyuncuların ellerinde karmaşık değişiklikler bırakmalı (hızlı başarısız olmalısınız) - sadece oyuncuya öğenin nerede olduğu ile ilgili bağlam verebilmelisiniz (böylece sadece hatırlamak için değil, tüm bu eşyalarını saklamak ve nerede olduklarını bilmemek).


Bu, nesnenin konumlandırmasına biraz fazla odaklanmıştır, ki bu çözmeye çalıştığım temel sorun değildir. Daha çok, eşzamanlı veri kümelerinde benzersiz tanımlayıcılara sahip olmak ve herhangi bir olası çatışma riski olmadan bunları birleştirmek zorunda kalmakla ilgilidir. Geçen gün yazıma 2 örnek ekledim ve biraz daha anlatmaya çalıştım.
Kylotan

1

Bunu anladığım bir şeyle ilişkilendirmeye çalışıyorum, bu yüzden şu anda Minecraft açısından düşünüyorum. Geliştiriciler yeni içerik düzeltme / oluşturma testi yapan bir test sunucusunda çalışırken oyuncuların gerçek zamanlı olarak değişiklik yapmasıyla canlı bir sunucu hayal ediyorum.

Sorunuz neredeyse 2 benzersiz soru gibi görünüyor:

  1. Nesne kimliklerinin benzersiz olmasını sağlama
  2. Komut dosyası ad alanlarının çakışmamasını sağlama

Geçici bir referans sistemi ile # 1'i çözmeyi denerdim. Örneğin, birisi tarafından yeni bir nesne oluşturulduğunda, geçici veya geçici olarak işaretlenebilir. Test sunucusunda oluşturulan tüm yeni içeriğin uçucu olarak işaretleneceğini hayal ediyorum (her ne kadar uçucu olmayan içeriğe de başvurabilir).

Canlı sunucuya yeni içerik getirmeye hazır olduğunuzda, içe aktarma işleminiz geçici nesneleri bulur ve bunlara taş olarak ayarlanmış canlı sunucu nesne kimliklerini atar. Bu düz bir içe aktarma / birleştirme işleminden farklıdır, çünkü bunları düzeltmeniz veya güncellemeniz gerektiğinde mevcut kalıcı nesnelere başvurabilmeniz gerekir.

# 2 için, işlev adını benzersiz bir ad alanına ayırabilen bir miktar orta düzey komut dosyası dönüşümüne sahip olmanız gerekir. yani

assignFrenchAccent

Oluyor

_Z11assignFrenchAccent

0

Veriler için dosyalar ikilinin aksine metinse ve tasarımcılar ve oyuncular farklı alanları değiştiriyorsa bir SVN birleştirmeyi deneyebilirsiniz.


0

Ben bir 'check-out' prosedürü ile ortamlar arasında çoğaltılan bir veritabanı / dosya sistemi en iyi olacağını düşünüyorum.

Bu nedenle, bir tasarımcı dünya üzerinde bir değişiklik yapmak istediğinde, veritabanının tüm kopyalarında (geliştirme ve üretim) oluşturmak / değiştirmek istediği tüm varlıkları kontrol eder / kilitler, böylece başka hiçbir oyuncu veya tasarımcı bunu değiştiremez . Daha sonra yeni tasarım bitene kadar geliştirme veritabanı üzerinde çalışacak ve o zaman değişiklikler üretim veritabanı ile birleştirilecek ve bu varlıklar tüm ortamlarda iade edilecek / kilidi açılacaktı.

Oyuncu düzenlemeleri, veritabanı / dosya sistemi rollerinin tersine çevrilmesi dışında, aynı şekilde çalışır - üretim veritabanında çalışır ve tüm güncellemeler tamamlandığında geliştiriciye yüklenir.

Varlık kilitleme, çakışma olmadığını garanti etmek istediğiniz özelliklerle sınırlandırılabilir: Örnek 1'de, ID 123456oynatıcı bunu oluşturmaya başlar başlamaz kilitlersiniz , böylece geliştiricilere bu kimlik atanmaz. Örnek 2'de geliştiricileriniz komut dosyası adını kilitlerdiassignFrenchAccent sırasında , bu nedenle oyuncu değişikliğini geliştirirken farklı bir ad seçmeliydi (bu küçük rahatsızlık ad boşluklarıyla azaltılabilir, ancak her birini vermedikçe kendi başına çatışmalardan kaçınmayacaktır. kullanıcı / geliştirici belirli bir ad alanını kullandığınızda, ad alanlarını yönetme konusunda da aynı sorunla karşılaşırsınız). Bu, tüm geliştirmelerin tek bir çevrimiçi veritabanından okunması gerektiği anlamına gelir, ancak bu örneklerde bu veritabanından ihtiyacınız olan her şey nesne adlarıdır, bu nedenle performans bir sorun olmamalıdır.

Uygulama açısından, tüm anahtarların ve varlık durumunun (kullanılabilir, geliştiriciden kilitli, eşyadan kilitli) tek bir tabloya sahip olması, ortamlar arasında gerçek zamanlı olarak senkronize / erişilebilir olmalıdır. Daha karmaşık bir çözüm, eksiksiz bir Sürüm Kontrol sistemi uygulayacaktır - varlıklarınız bir dosya sisteminde ise CVS veya SVN gibi mevcut bir sistemi kullanabilirsiniz.


Genellikle küresel olarak herhangi bir veriyi kilitlemek pratik değildir - oyuncular dünyayı normal oyun yoluyla düzenliyor olabilir ve bu oyunun tasarımcıların çalışmasını durdurmak istemezsiniz. Genel kilitlere izin verirseniz, birleştirme işlemi temelde üzerine yazma işlemidir, bu da kolaydır - ancak genel kilitleriniz yoksa, ne olacak?
Kylotan

Lathomas64'ün de belirttiği gibi, cevap ne tür verilerden bahsettiğinize bağlı olacaktır. Küresel kilitler olmadan, herhangi bir çatışmayı çözmek için bir sürüm sistemine ve bir dizi kurala sahip olmanız gerektiğini düşünürüm - bu kurallar veri ve oyun gereksinimlerine bağlı olacaktır. Bunlara sahip olduğunuzda, her birleştirme basit bir üzerine yazma işlemine dönüşür sanırım.
SkimFlux

0

Sanırım burada mesele, sorumluluğunuzu temiz bir şekilde kabul etmek. 1) Sunucu şu anda kabul edilebilir olanı ve erişilecek API'yı söylüyor. Veritabanı, belirli kurallara göre değiştirilmektedir. 2) İçerik oluşturucuların içerik oluşturmasına izin verilir, ancak güncellemelerden sonra oynatılabilir olmaları gerekir. Bu tamamen sizin sorumluluğunuzdadır: herhangi bir güncelleme eski veri yapılarını tercihen mümkün olduğunca temiz ve kolay bir şekilde ayrıştırabilmelidir.

Bağlama noktası fikri, benzersiz öğeleri ve pozisyonları dövülebilir bir yapı içinde takip etmekle ilgileniyorsanız, özellikle de bir oyuncunun tüm 'ev' yapısının dramatik bir değişim geçireceğini kabul edersek ve bunu korumak istiyorsanız kendi dolaplarında küçük deco şeyler.

Oldukça karmaşık bir konu, iyi şanslar! Muhtemelen bir cevap yok.


0

Bunu yaparken büyük bir sorun olduğunu düşünmüyorum.

Sadece kullanıcı tarafından oluşturulan modların üzerine yazardım, bir uyarı ile "Mod X bu sürümle doğru çalışmayabilir", çalışmalarını değiştirmek için mod yaratıcılarına bırakın. Bunun, güncellemelerin belirli modları devre dışı bırakabileceği gerçekçi olmayan bir beklenti olduğunu düşünmüyorum.

Kullanıcı tarafından oluşturulan içerik için aynıdır, sadece bir yedek oluşturun ve üzerine yazın.

Bu konuda gerçek bir deneyimim yok, sadece önerilerde bulunuyorum.


Ben sadece kullanıcı tarafından sağlanan modlar için olsaydı, o zaman haklı olurdu. Ancak bazı oyunlar açıkça kullanıcının oluşturduğu içerikle ilgilidir ve bu yüzden onu yok edemezsiniz.
Kylotan

Ardından, daha sonra ekleyebileceğiniz içerik için sistemde yer bırakın. Kimlik numaraları kullanıyorsanız, 1-1000 ayırın. Veya kullanıcılar varlıklarını adlandırabiliyorsa, kullanıcıların adı "FINAL-" veya başka bir şeyle başlatmasına izin vermeyin (kendi varlıklarınız için ayırın). DÜZENLEME: ya da daha iyisi, tersine yapın, kullanıcı içeriğini bir aralığa veya bir ön
eke zorlayın
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.