Способи управління зміною даних дизайнера поряд із зміною даних програвача


14

У мене є онлайн-гра, де гравці певним чином формують світ - наприклад. Корпус Ultima Online, де ви можете побудувати свої будинки безпосередньо на певних частинах світу. Це зміни, які мають тривати з часом як частина стійкого світу.

У той же час команда дизайнерів додає новий вміст та вносить зміни в старий контент, щоб покращити та розширити гру для нових гравців. Вони будуть робити це на сервері розробки спочатку під час тестування, а потім пізніше доведеться об'єднати свою роботу з "роботою" гравців на живому сервері.

Припустимо, що ми вирішуємо проблеми дизайну гри - наприклад. гравці можуть створювати лише на визначених ділянках, тому вони ніколи не стикаються географічно з дизайнерськими правками - які хороші способи обробки даних або упорядкування структур даних, щоб уникнути конфліктів, коли нові дані дизайнера об'єднуються з новими даними про програвач?

Приклад 1: Гравець створює новий тип предмета, і гра присвоює йому ідентифікатор 123456. Екземпляри цього елемента посилаються на 123456. Тепер уявіть, що у дизайнерів ігор є схожа система, і дизайнер створює новий елемент також під номером 123456. Як цього можна уникнути?

Приклад 2: хтось робить популярний мод, який надає всім вашим драконам французький акцент. Він включає в себе сценарій з новим об'єктом, assignFrenchAccentякий називається, який вони використовують для присвоєння нових голосових активів кожному об’єкту дракона. Але ви збираєтесь розгорнути свій DLC "Наполеон проти Смауга", який має однойменний об'єкт - як це можна зробити без великих проблем із обслуговуванням клієнтів?

Я продумав такі стратегії:

  • Можна використовувати 2 окремих файли / каталоги / бази даних, але тоді ваші операції з читання значно ускладнюються. "Показати всі елементи" має виконати одне прочитане на конструкторській БД і одне прочитане на БД програвача (і все одно має розрізняти два, якось.)
  • Ви можете використовувати 2 різних простору імен в одному магазині, наприклад. використовуючи рядки в якості основного ключа та префіксуючи їх "DESIGN:" або "PLAYER:", але створення цих просторів імен може бути нетривіальним, і залежності не зрозумілі. (наприклад, в RDBMS ви, можливо, не зможете ефективно використовувати рядки в якості первинних ключів. Ви можете використовувати цілі числа та виділити всі первинні ключі нижче певного числа, наприклад, 1 мільйон, щоб бути дизайнерськими даними, і все, що вище за це вказує на Дані про програвача. Але ця інформація невидима для RDBMS, і зовнішні ключові посилання перетинатимуть "розділити", тобто всі інструменти та сценарії повинні явно працювати навколо неї.)
  • Ви завжди можете працювати в одній спільній базі даних в режимі реального часу, але продуктивність може бути низькою, а ризик пошкодження даних про програвач може бути підвищений. Він також не поширюється на ігри, які працюють на більш ніж 1 сервері з різними світовими даними.
  • ... будь-які інші ідеї?

Мені здається, що хоча це в першу чергу проблема онлайн-ігор, ці концепції можуть стосуватися і модінгу, коли спільнота створює моди одночасно, коли розробники виправляють свою гру. Чи використовуються тут якісь стратегії, щоб зменшити ймовірність зламу мода, коли з’являться нові патчі?

Я також позначив це як "контроль версій", тому що на одному рівні це і є - 2 галузі розвитку даних, які потребують об'єднання. Можливо, з цього напрямку можуть з’явитися деякі розуміння.

EDIT - кілька прикладів, доданих вище, щоб допомогти з’ясувати проблему. Я починаю вважати, що проблема справді одна з просторів імен, яка може бути реалізована в магазині за допомогою складених ключів. Щонайменше, це спрощує стратегію злиття. Але можуть бути альтернативи, яких я не бачу.


1
Я думаю, що відповідь на це могла б частково залежати від того, який тип даних додають дизайнери та що додають гравці.
lathomas64

Це могло б, але мене більше цікавлять узагальнені рішення для двох сторін, які обидва роблять внесок у єдиний сховище даних.
Килотан

1
Дуже багато людей пропускають суть цього питання - це не суперечливі зміни гравців: скоріше оновлення вмісту тощо, що порушує існуючі макети. @Kylotan я правий?
Джонатан Дікінсон

Тут оновлення вмісту розробника потенційно стикаються з оновленнями вмісту програвача. Мене не дуже цікавлять способи вирішення ігрового дизайну (наприклад, дозволяють грати лише гравцям у певних місцях), але в структурі обходу даних (наприклад, лише дозволяти гравцям створювати речі з ідентифікаторами більше 1 мільйона).
Kylotan

2
Ви не вказали, чи очікуєте ви робити оновлення в реальному часі в реальному часі? Побічна примітка: дві сторони, що працюють в одному сховищі даних, є БД, ось що роблять бази даних, ви не можете обійти цей факт, і було б глупо ігнорувати десятиліття знань про те, як уникнути проблем із спільними даними.
Патрік Х'юз

Відповіді:


2

Я думаю, що відповіді, що пропонують рішення БД, переходять до конкретної реалізації, не розуміючи проблеми. Бази даних не спрощують злиття, вони просто дають вам основу для зберігання ваших даних. Конфлікт все ще є конфліктом, навіть якщо він знаходиться в БД. І перевірка - це проблема бідного чоловіка - це спрацює, але при цьому забиває ваші зручності.

Те, про що ви тут говорите, потрапляє в модель розподілених проблем розвитку. Перший крок, який я вважаю, - це не вважати гравців та дизайнерів окремими типами творців контенту. Це видаляє штучну міру вашої проблеми, яка не впливає на її вирішення.

Ефективно у вас є основна лінія - канонічна, затверджена розробником версія. Ви можете (напевно) також мати інші відділення - живі сервери, коли люди активно розробляють та обмінюються модами. Вміст може бути доданий у будь-якій галузі. Важливо, що ваші дизайнери тут нічого особливого - вони просто творці контенту, які, як правило, живуть у себе вдома (і ви можете знайти їх і вдарити їх, коли вони накрутяться).

Тоді прийняття створеного користувачем вмісту є стандартною проблемою злиття. Вам потрібно або перетягнути їх зміни назад на основну лінію, об'єднати, потім знову виштовхнути або витягнути зміни основної лінії на їх гілку та об'єднати (залишаючи основну лінію «чистою» від створених користувачем матеріалів). Як завжди, підтягнути до своєї гілки та виправити там є більш привітно, ніж просити інших людей здійснити зміни, а потім намагатися виправити це віддалено на їх кінці.

Коли ви працюєте з такою моделлю, застосовуються всі нормальні процеси щодо уникнення конфліктів злиття. Деякі з більш очевидних:

  • Заохочуйте до ліберального використання пробілів імен для обмеження вмісту певного автора / мода / команди.
  • Там, де вміст потребує взаємодії, встановіть чіткі конвенції про виклики / користування, конвенції про іменування та інші вільні "правила", які керують розробкою, щоб легко було об'єднатися назад. Надайте інструменти, які дозволять творцям вмісту знати, чи вони дотримуються цих правил, ідеально інтегрованих у саме створення вмісту.
  • Надайте інструменти звітності / аналізу, щоб виявити ймовірні збої об'єднання до їх виникнення. Виправити його після злиття, мабуть, дуже боляче. Зробіть так, щоб певний біт вмісту можна було перевірити і дати все зрозуміле як готове до злиття, щоб злиття було безболісним
  • Зробіть надійне об'єднання / інтеграція. Дозволити легкі відкати. Робіть ретельне тестування об'єднаного вмісту: якщо він не проходить тестування, не зливайте його! Ітератуйте або їхній вміст, або ваш, поки злиття не буде продовжуватися чисто.
  • Уникайте використання додаткових цілих ідентифікаторів ні для чого (у вас немає надійного способу передавати їх творцям). Це працює лише в БД, оскільки сама БД є канонічним постачальником ідентифікаторів, тому ви ніколи не отримуєте дублікатів; однак це також вводить єдину точку відмови / завантаження у вашій системі.
  • Натомість використовуйте GUID - вони коштують дорожче для зберігання, але є специфічними для машини і тому не спричинять зіткнень. Альтернативно використовувати рядкові ідентифікатори, це набагато простіше налагодження / вирішення, але дорожче для зберігання та порівняння.

На жаль, щось із цього не допомагає моїй проблемі (наприклад, те, що гравці дотримуються певних правил, оскільки все це повинно робитися автоматично на стороні сервера), і я не думаю, що це буде практично підтримувати ступінь управління злиттями та транзакцій. семантику, яку ви згадуєте, але загальний підхід розподілу гарантованих унікальних ідентифікаторів, можливо, GUID, є, мабуть, найближчим до того, з чим я піду.
Килотан

А, бачу. Отже, оскільки ви керуєте їх інструментами побудови, принаймні застосовуйте ці зручні для злиття підходи (простори імен тощо) - це те, що ви можете зробити, без того, щоб гравці мали згоди.
MrCranky

Що робити, якщо два гравці створюють повторюваний вміст? Або окремі екземпляри вашого ігрового світу трактуються як унікальні? У цьому випадку, можливо, це корисний підхід до автоматичної перевірки кожного унікального екземпляра, який ви знаєте, щодо вашої основної / основної гілки, на конфлікти, які відбудуться, коли ви висунете ці зміни до екземплярів. Якщо ви не можете контролювати гравців, ви можете принаймні попередити свою внутрішню команду про те, що робота, яку вони виконують, конфліктує з інстанцією X світу на початку розвитку.
MrCranky

Концепція просторів імен не стільки проблема - вибір адекватних просторів імен з простору імен усіх можливих просторів імен! :) І дублювати вміст для мене не є проблемою - це лише два екземпляри рівнозначних. Важливим є те, що не відбувається пошкодження злиття або перезапису. Що стосується автоматичної перевірки зіткнення, це зупиняє шкоду, заподіяну в записі, але не вирішує оригінальну проблему іменування. (Перейменування речей, щоб уникнути зіткнення, може бути нетривіальним через перехресне посилання.)
Kylotan

Ага так, я бачу зараз, це не самі простори імен, скільки вибір імені. У цьому випадку GUID, ймовірно, знову відповідь - чи вміст ефективно зберігається у власній невеликій області. Можна назвати декоративну назву, але гра використовуватиме GUID.
MrCranky

1

Зберігайте все як атрибут (або декоратор) - з точками кріплення. Візьмемо, наприклад, будинок, який програвач створив:

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}

Таким чином, кожна сутність може мати одну або більше точок монтажу - кожна точка монтажу може приймати нуль або більше інших компонентів. Ці дані зберігатимуться у версії якій він був збережений, а також з будь-якими відповідними властивостями (такими як Displacement і т. Д. У моєму прикладі) - NoSQL, швидше за все, справді добре впишеться тут (Key = Entity ID, Value = Serialized Binary Дані).

Кожен компонент тоді повинен мати можливість "оновити" старі дані з попередньої версії (ніколи не видаляйте поля з серіалізованих даних - просто "обнуляйте їх") - це оновлення відбувається в хвилину завантаження (воно буде негайно зберігатися назад у найновіша версія доступна). Скажімо, у нас в будинку змінилися розміри. Код оновлення відносно розробив би відстань між північною та південною стінами і пропорційно змінив би переміщення всіх міститься сутностей. В якості іншого прикладу з нашої чаші з м'ясом може бути видалено поле «Їжа», а натомість вийде «Різноманітність» (М’ясо) та «Рецепт» (Кульки). Сценарій оновлення перетворив би "М'ясні кульки" на "М'ясо", "Кульки". Кожен компонент також повинен знати, як поводитися зі змінами точок кріплення - наприклад

Все це залишає відкритим рівно одне питання: що станеться, якщо два об'єкти зіткнуться один з одним (а не їх контейнер - точки монтажу захищають вас від цього)? Після оновлення слід перевірити наявність зіткнень і спробувати вирішити їх (перемістивши речі, трохи схожі на SAT). Якщо ви не можете зрозуміти, як вирішити зіткнення, видаліть один із предметів і помістіть його в сховище - там вони можуть придбати ці вилучені речі (безкоштовно) або продати їх (за ціною); і, очевидно, повідомте програвача, що оновлення порушило частину їх макета - можливо, за допомогою функції «збільшення масштабу», щоб вони могли бачити проблему.

Зрештою, ви повинні залишити складні зміни в руках гравців (не швидко вийти з ладу), оскільки жоден алгоритм не може пояснити естетичність - ви повинні просто вміти давати гравцеві контекст щодо того, де знаходився предмет (щоб вони могли запам'ятати, а не просто висадити всі ці предмети в їх сховище і не знати, де вони були).


Це зосереджено трохи вузько на позиціонуванні об'єктів, що насправді не є ключовою проблемою, яку я намагаюся вирішити. Йдеться більше про те, щоб мати унікальні ідентифікатори в паралельних наборах даних та потребувати можливості об'єднати ці дані без можливого ризику конфлікту. Днями я додав у свій допис 2 приклади, щоб спробувати і пояснити трохи далі.
Килотан

1

Я намагаюся пов’язати це з чимось, що я розумію, тому зараз я думаю про поняття Minecraft. Я зображую живий сервер з гравцями, які вносять зміни в режимі реального часу, поки розробники працюють на тестовому сервері, що фіксує / створює новий вміст.

Ваше запитання майже схоже на 2 унікальних питання:

  1. Як застрахувати, що ідентифікатори об’єктів унікальні
  2. Як переконатися, що простори імен скриптів не стикаються

Я б спробував вирішити номер 1 через систему тимчасових посилань. Наприклад, коли хтось створює новий об’єкт, він може бути позначений як мінливий або тимчасовий. Я б міг уявити, що весь новий вміст, створений на тестовому сервері, буде позначений мінливим (хоча він також може посилатися на енергонезалежний вміст).

Коли ви будете готові донести новий вміст до живого сервера, ваш процес імпорту знайде мінливі об'єкти та призначить їм ідентифікатори об’єктів живого сервера, встановлені в камені. Це відрізняється від прямого імпорту / злиття, оскільки вам потрібно мати можливість посилатися на існуючі енергонезалежні об'єкти, якщо вам потрібно їх виправити чи оновити.

Для №2, здається, вам дійсно потрібно мати певний рівень проміжної трансмутації скрипту, який може хешувати ім'я функції до унікального простору імен. тобто

assignFrenchAccent

Стає

_Z11assignFrenchAccent

0

Якщо файли даних є текстовими, а не двійковими, а дизайнери та програвачі змінюють різні області, ви можете спробувати SVN злиття.


0

Я думаю, що найкраща база даних / файлова система, реплікувана в різних середовищах з процедурою «виїзду».

Отже, коли дизайнер хоче внести якісь модифікації в світ, він перевіряє / заблокує всі активи, які він хоче створити / змінити на всіх копіях бази даних (розробка та виробництво), тому жоден інший програвач чи дизайнер не може її змінити . Потім він буде працювати над базою даних розробок до тих пір, поки нова конструкція не буде закінчена, і в цей час зміни будуть об'єднані з виробничою базою даних, і ці активи будуть зареєстровані / розблоковані у всіх середовищах.

Правки програвача працюватимуть приблизно так само, за винятком того, що ролі бази даних / файлової системи будуть змінені - вони працюють на виробничій базі даних, а всі оновлення завантажуються в розробник після завершення.

Блокування активів може бути обмежено властивостями, в яких ви хочете гарантувати відсутність конфліктів: у прикладі 1 ви заблокуєте, ID 123456як тільки гравець почне його розробляти, тож розробникам не буде призначено цей ідентифікатор. У Прикладі 2 ваші розробники заблокували ім'я сценарію assignFrenchAccentпід час розробки, тому гравцеві довелося вибрати інше ім'я при розробці його модифікації (цю невелику неприємність можна зменшити шляхом простору імен, але це само по собі не уникне конфліктів, якщо ви не дасте кожному користувач / розробник певного простору імен, і тоді у вас виникне та сама проблема з керуванням просторами імен). Це означає, що всі розробки повинні читатись з однієї он-лайн бази даних, але все, що вам потрібно від цієї бази даних у цих прикладах, є назви об'єктів, тому продуктивність не повинна бути проблемою.

З точки зору реалізації, достатньо мати єдину таблицю з усіма ключами та станом активів (доступними, заблокованими від розробника, заблокованими від prod), синхронізованими / доступними в режимі реального часу в різних середовищах. Більш складне рішення дозволило б реалізувати повну систему управління версіями - ви можете використовувати існуючу систему, наприклад CVS або SVN, якщо всі ваші активи перебувають у файловій системі.


Зазвичай неможливо заблокувати будь-які дані в усьому світі - гравці можуть редагувати світ просто завдяки звичайній грі, і ви не хочете, щоб ця гра перешкоджала дизайнерам працювати. Якщо ви дозволяєте глобальні блокування, то операція злиття - це в основному операція перезапису, що легко - але якщо у вас немає глобальних блокувань, що тоді?
Кілотан

Як зазначалося lathomas64, відповідь залежатиме від того, про які дані ви говорите. Без глобальних блокувань я думаю, що вам доведеться мати систему версій та набір правил для вирішення будь-яких конфліктів - ці правила залежатимуть від вимог до даних та геймплея. Після їх отримання, я думаю, що кожен злиття зводиться до простої операції перезапису.
SkimFlux

0

Я думаю, що тут важливо чітко прийняти свою відповідальність. 1) Сервер повідомляє, що є прийнятним на даний момент, та API для доступу до нього. База даних змінюється згідно певних правил. 2) Творцям дозволяється створювати контент, але він повинен відтворюватися після оновлень. Це виключно ваша відповідальність: будь-яке оновлення повинне бути здатним проаналізувати старі структури даних, бажано максимально чисто та легко.

Ідея Mount Mount має переваги, якщо вам цікаво відстежувати унікальні предмети та позиції всередині ковкої конструкції, особливо якщо ми погоджуємось, що вся «домашня» структура гравця зазнає кардинальних змін, і ви хочете це зберегти маленькі речі деко у відповідних шафках.

Це масово складне питання, удачі! Напевно, немає жодної відповіді.


0

Я не думаю, що це має великі проблеми, коли ти це робиш.

Я б просто перезаписав створені користувачем моди, з попередженням, що "Mod X може не працювати належним чином з цією версією", залиште це творцям мод, щоб змінити свою роботу. Я не думаю, що це нереально сподівання, що оновлення можуть вимкнути певні моди.

Те саме, що створений користувачем вміст, просто зробіть резервну копію та перезапишіть.

Я не маю фактичного досвіду в цьому, просто роблю пропозиції.


Я думаю, якби це було виключно для модників, що надаються користувачем, то ви б мали рацію. Але деякі ігри явно стосуються створеного користувачем вмісту, і тому ви не можете просто його знищити.
Килотан

Тоді просто залиште місце в системі для вмісту, який ви можете додати пізніше. Якщо ви використовуєте ідентифікаційні номери, резервуйте 1-1000. Або якщо користувачі можуть назвати свої активи, не дозволяйте користувачам починати ім’я з "FINAL-" або щось подібне (зарезервуйте це для власних активів). EDIT: або ще краще, зробіть це в зворотному порядку, примушуючи вміст користувачів до діапазону чи префіксу
Woody Zantzinger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.