1*XNaVare9VDhXPpKH7oVdPQ

Игровой баланс. Часть 3

Краткое содержание цикла про баланс:
— Введение и подготовка к работе
— Начало работы: константы и прогрессии
— Боевой баланс или расчет эффективности
— Модели и экономика

Расчет эффективности

Таким образом я называю, наверное, самую очевидную часть работы: боевой баланс, баланс между фракциями, стратегиями, юнитами и зданиями разных уровней и тому подобное.

Напоминаю, мы делаем мобильный баттлер.
Как убедиться, что вот эта карта 23-его уровня равна по силе другой карте той же ценности того же уровня?
Как контролировать, что любая «редкая карта» на любом уровне ровно в двое сильнее любой «обычной карты»?
В других жанрах похожие задачи: вот два строения в ситибилдере с похожей ценой, но разной функцией — как сделать их равными по «полезности»?

Универсальный ответ: сводите всю параметры к одному. Можете назвать его «эффективность», «полезность», «сила», как угодно.

Ранее мы уже делали прогрессию силы. Теперь разберемся с тем, что это такое.

Боевая эффективность

Сила юнита = HP * DMG.

Вот так просто, серьезно.
Даже если в игре два десятках параметров, все они сводятся сначала к этим двум, а потом и к одному.
Иначе говоря: ОТНОСИТЕЛЬНАЯ ЭФФЕКТИВНОСТЬ ЮНИТА =
HP [ 
СУММА УРОНА, КОТОРЫЙ Я ПРИМУ ] * DMG [ МОЕГО УРОНА ЗА ЕД.ВРЕМ.

Рассмотрим другие параметры.
Например, есть процентный шанс нанести двойной урон (CRIT).
Тогда DMG = DMG * ( 1 + CRIT% ). То есть, добавить 50%-ый шанс крита на языке баланса то же самое, что увеличить базовый урон на 50%. Все просто и логично.

Или, например, есть шанс избежать атаку врага (DODGE).
Тогда HP = HP / ( 1 — DODGE%). То есть, 50%-ый шанс увернуться равен увеличению здоровья вдвое: логично, т.к. уворот от половины атак позволит юниту вдвое дольше прожить в бою. Точно так же считаются эффекты типа PARRY и ABSORB.

Но если эффектов несколько, то надо смотреть, как они складываются. Например, уворот вместе с поглощением урона — поглощение срабатывает только тогда, когда не сработал уворот. Раз они действуют по-очереди — их нельзя складывать. В таком случае формула будет выглядеть так:
HP = HP / ( 1 — ( DODGE%+ ABSORB%*(1-DODGE%) )
То есть, ABSORB надо уменьшать на вероятность уворота: больше уворот — реже поглощение.

Дальше, по аналогии, можно рассчитывать не только параметры юнитов, но так же предметов, заклинаний, зданий и прочего.

Важное примечание: если один юнит ровно вдвое сильнее другого — значит, одолев слабого врага, у сильного останется примерно половина здоровья и возможность победить второго слабого врага.
Но в сражении одновременно с двумя слабыми врагами — всегда побеждают двое, поскольку они наносят свой суммарный урон за единицу времени.
Позже я расскажу, как моделировать битвы между отрядами разной численности и распишу несколько нераскрытых нюансов. А пока считаем, что разобрались.

Параметры из эффективности

Возвращаемся к нашей прогрессии силы.
Мы уже разобрались, что такое сила и у нас уже есть прогрессия. Осталось только вывести из нее параметры юнитов.

Проще всего это делать с помощью коэффициентов к средним значениям: например, для «танка» нужно будет указать, что его здоровье в 1.5 раза выше среднего.

Теперь подробно: допустим, сила (PW) юнитов 1-ого уровня = 100.
Тогда средние значения HP и DMG = SQRT(100) = 10 (квадратный корень из эффективности).
Однако, ранее мы решили, что здоровье должно быть в 6 раз больше урона.
Пересчитываем: среднее HP = SQRT(100) * SQRT(6) = 24
Соответственно, среднее DMG = 24/6 = 4
Проверяем: 24 * 4 = 96 (не ровно 100, т.к. до этого я округлил, но в рамках баланса такие погрешности допустимы)

Теперь мы хотим сделать «танка».
Нам надо умножить средний HP на ранее выбранный множитель = 24 * 1.5 = 37
соответственно DMG = 4 * ( 1 / 1.5 ) = 4 * 0.7 = 3
Проверяем: 37 * 3 = 111 (Все получилось, хоть и с погрешностью округления).

В итоге наши расчеты будут выглядеть примерно так: t11 В этой таблице единственное вручную задаваемое число — коэффициент к HP.

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

Заполнение вручную

Параметры можно вписывать и вручную, а формулой только «проверять», чтобы вписанное не сильно отличалось от расчетного.

Как это может выглядеть: t10

Теперь все значения внесены вручную, а под каждым юнитом есть столбик с проверкой. В нем — относительная разница между полученным PW и расчетным, которая подсвечивается красным (conditional formating), если превышает 10%.

  • Плюсы вписывания: значения лучше смотрятся, их можно связать с эмоциями, например «Адская бомба с уроном 666″.
    Еще я люблю использовать четные цифры для «толстых» юнитов и нечетные для дамагеров.
    А эпические юниты хорошо смотрятся с круглыми числами.
  • Минусы вписывания: больше работы, больше мусора в таблицах и выше риск ошибки.

Aвтоматическое заполнение с коэффициентами или ручное с проверкой — выбор за вами.
Если ваши юниты и способности могут прокачиваться на десятки уровней — в эмоциональных числах нет никакого смысла, все-равно их почти не будет заметно.
Зато, если речь о каком-то уникальном контенте, который не меняется и не имеет сотню состояний — задумайтесь о ручном заполнении, с ним красивее.

Используя ручное заполнение, добавьте на главный лист результат всех проверок, чтобы не было нужды после каждого изменения проверять все листы.

На этом основы кончаются, а мы можем спокойно получить все параметры всех юнитов. Переходим к обещaнным нюансам.

Дополнительно

Как уже упоминал: автоматизация вносит погрешность.
Видя перед собой только цифры мы забываем про вещи, казалось бы, очевидные. Их лучше провоговорить заранее и учитывать при балансировке.

(Не)очевидные параметры

Да, все параметры сводятся к HP и DMG, это чистая математика.

Но в балансе всегда есть здоровая доля «магии» из-за невозможности предсказать и посчитать все возможные события и комбинации.
И не везде есть прямое математическое решение — иногда вам придется вносить изменения «на глаз» и проверять в прототипе.

Вот некоторые примеры.

Самый очевидный: лечение.
Легко догадаться, что для целителя DMG = силе исцеления. Однако, атакующий всегда найдет цель, а целитель может быть неэффективен, когда он один на поле или когда все здоровы. Плюс он не лечит выше максимального здоровья.
Поэтому, при сравнении целителя и дамагера с одинаковыми параметрами, расчетная эффективность целителя должна быть ниже.
Я обычно использую коэффициент 0.7-0.8 к DMG.

Другой пример: лучник атакует летающие цели, рыцарь — нет.
Лучник, очевидно, «эффективнее» и для правильного баланса ему надо заложить коэффициент к урону.
Но подбирать коэффициент придется «на глаз», опираясь на тестирование и некоторые соображения. Например:

  • Количество летунов в игре. Если летун, допустим, всего один — к-т должен быть минимален.
  • Эффективность самих летунов. Если все ленуты заведомо слабые и легко выносимые, а «лучников» в игре много — к-т так же не должен быть слишком высоким.

Этот пример относится ко всем параметрам, подразумевающим определенный фильтр характеристик. Например, к «пробитию брони», при условии, что броня есть не у всех персонажей. Или к повышенному «урону по зданиям». Или к «стойкости против гоблинов».
В некоторых случаях остается возможность посчитать коэффициент математически: умножив чистую эффективность свойства на вероятность его использования — ведь все юниты нам известны заранее.

Другой пример: атака на расстоянии.
В игре с перемещением или позиционированием побеждает тот, кто начал атаковать раньше, соответственно, ему нужен коэффициент к урону.
Вам может показаться, что у этой задачи есть математическое решение: мы можем посчитать среднее количество попаданий до прямого столкновения, опираясь на среднюю скорость врагов.
И в этом даже есть смысл. Но нельзя забывать:

  • Во-1-х, далеко не всегда столкновение будет начинаться с максимального радиуса атака. В играх типа Clash Royale можно скидывать юнитов с ближней атакой прямо на юнитов с дальней — тогда весь эффект дальнего боя сводится к нулю.
    В каждой игре свои ограничения — считая по максимуму мы, скорее всего, завысим эффективность.
  • Во-2-х, мы не учитываем тактику комбинирования «жирных» юнитов спереди и дальнобойных сзади. В зависимости от игры эта тактика может быть выгодна по-разному, от «вообще не имеет смысла» (к-т минимальный), до «только так и нужно играть» (к-т максимальный). Определитесь, что нужно для геймплея — и подкрепите этот вариант коэффициентом.

Этот же пример можно отнести ко всем вопросам позиционирования, включая, например, преграждение пути, замедление, другие формы crowd-controll’a.

И в каждом случае есть логичное, но не полное математическое решение: например, для мага с «заморозкий» можно посчитать среднее число поражаемых целей, умножить на среднюю атаку и на его силу замедления — получится обоснованное число «урона, который цели не смогли нанести из-за эффекта замедления», и это число смело можно плюсовать к DMG мага.
Но в зависимости от механик и тактик игры — реальная эффективность может сильно отличатся от наших расчетов.
Так что, без тестирования и правок «на глаз» не обойтись.

Эффективность группы

Этот вопрос уже упоминался: если в игре есть битвы с разным количеством юнитов или юниты типа «отряд из N персонажей» — мы должны знать, как посчитать их эффективность с учетом количества.

Просто умножить «силу» на количество недостаточно — наше число будет отражать «силу» отряда, в котором одновременно сражается только один юнит.

На количество (N) следует умножить отдельно HP, отдельно DMG:
PW(N) = ( HP*N ) * ( DMG*N )
Иначе это можно записать HP*DMG*N², что кажется даже логичнее — но мы так делать не будем, и вот почему: эта запись отражает эффективность отряда, который имеет общее здоровье и постоянный урон, не меняющийся от гибели членов отряда.

В реальности такое встречается редко, поэтому DMG надо понизить на коэффициент, отражающий смертность. А это уже зависит от конкретных механик игры, например — распространенности AoE атак, возможности отряда атаковать на расстоянии и т.д.

Возьмем, навскидку, коэффициент 0.7 и тогда формула выглядит так:
PW(N) при N>1 = ( HP * N ) * ( DMG0.7N )

Но если вы хотите использовать одну формулу и для отрядов и для одиночных героев, то ее надо переписать:
PW(N) = ( HP*N ) * ( DMG + DMG * 0.7 * (N-1) )

Рейтинги вместо процентов

Это совершенно отдельная механика, в которую можно было бы и не углубляться, если бы не ее распространенность и частая необходимость.

Начну с проблемы: допустим, мы делаем классический World of Warcraft и хотим, чтобы рыцарь-защитник в нормальной броне поглощал 40% урона.
Это правильная логика: она закрепляет за классом определенную роль на протяжении всей игры, что гораздо лучше, чем если бы в начале было 10%, а в конце — под 80%.

Но вот проблема: все параметры в MMO должны расти. Зачем нам ходить в рейды и валить боссов, если первая броня дает 40% и последняя — тоже 40%? Плюс, есть риск превысить 100%.

У проблемы есть решение: пусть броня 5-ого уровня дает 40% защиты только против врагов 5-ого уровня.
А против врагов 6-ого уровня та же броня даст, скажем, 36%. Против 7-ого всего 32% — и так далее. Таким образом мы сохраним роль классов и обеспечим потребность в постоянном росте.

Технически решение звучит так: процентный параметр делается зависимым от абсолютного значение параметра (рейтинга) и другого модификатора (например — уровня атакующего врага).
Модификатором может быть и уровень самого героя и любой другой параметр, например «пробитие брони» у атакующего.

Недостаток у такого метода ровно один: все это придется объяснять игроку. И вместо простых и удобных процентов, показывать, в довесок, непонятный «рейтинг брони».
К счастью, тот же World of WarCraft уже воспитал поколение привычных к этому игроков.

Теперь: как это делать.
Рассматриваем на том же примере: 40% защиты против врага того же уровня.

Сперва нам нужна прогрессия нормальных значений брони для этого класса. То есть: сколько «рейтинга брони» (ARMOR) должно быть у игрока на каждом уровне, чтобы его поглощение (ARMOR%) было = 40%.

Впоследствии из этой же прогрессии мы получим параметры всех шмоток, доступных этому классу, поскольку знаем, чему должна равняться сумма их брони.

Формула, которая превратит рейтинг в процент выглядит просто:
ARMOR% = ARMOR / ( ARMOR + PENETRATION )
Легко догадаться, что за счет деления числа на его сумму с другим положительным числом мы никогда не получим > 100%

Теперь разберемся с PENETRATION.
В самом простом сценарии — это значение из той же прогрессии, взятое по уровню врага.
Тогда, против равного врага мы будем иметь:
ARMOR / ( ARMOR + PENETRATION ) = 50% поглощения.
Нам, однако, требовалось 40%.
Для этого мы должны сделать еще одну прогрессию: пенетрации. И значения в ней должны быть в 1.5 раза выше, чем в предыдущей прогрессии.

Таким образом: у нас 10-ый уровень, для которого требуется, допустим, 300 брони. Нас бьет враг 10-ого же уровня, с пенетрацией 300*1.5=450.
Считаем:  300 / ( 300 + 450 ) = 40%
То, что надо.

Теперь, подбирая модификаторы мы можем расписать ожидаемые значения брони для всех классов.
Если нам не нравится, как падает или повышается % от разницы в уровнях — мы  можем добавить зависимость второго слагаемого от этой разницы.

И последнее: в нашей ММОRPG полученный урон будет расчитываться на сервере по той формуле, с которой сделаны прогрессии брони и пенетрации. Если для прогрессии вы использовали фибоначчи — вас, скорее всего, засунут в блендер и порвут на сотню маленьких геймдизайнеров.

________________

В следующем посте: модели и экономика. Он, скорее всего, выйдет с задержкой.

Share on Facebook0Tweet about this on TwitterShare on VK
  • Александр

    У меня возникла небольшая трудность с просчетом, не могли бы прояснить? HP = HP / ( 1 — DODGE%). Я рассчитал прогрессии по уровням и получил условные HP1, HP2, HP3… За каждый n-й уровень я хочу давать игроку DODGE. Получается формулы для перехода с 32-го на 33-й уровень:

    HP32=(HP32_actual)/ ( 1 — DODGE32_actual%);
    HP32_actual, DODGE32_actual — те значения, которые уже сложились у игрока к 32 уровню
    HP33 — значение из расчетной таблицы
    также HP33 = HP32 / ( 1 — DODGE33%)
    выходит, DODGE33%=HP33/(HP32_actual)/ ( 1 — DODGE32_actual%) — 1

    — это по моему пониманию, именно тот DODGE, добавив который к HP32_actual и DODGE32_actual, игрок получит искомые HP33. Все верно?

    Отдельная благодарность, если распишите как рассчитать, сколько можно добавить от уровня к уровню эффективности в обращении с оружием, если она входит в состав формулы, там тоже у меня какая-то погрешность выходит(формула вида DMG=DMG*(1+EFF%/100))

    • Смотрите, мои формулы не универсальны. Если менять метод подсчета, то и формулы придется менять соответственно. Как я понял, у вас метод немного отличается.
      В моем случае мы получаем не прогрессию HP, а прогрессию силы, все остальное рассчитывается коэффициентами. Логика, грубо говоря, такая: «насколько юнит силен здоровьем по отношению к урону» и так далее.
      Если считать сразу вместе с уворотом, то надо, соответственно, из силы получить суммарное здоровье, а уже суммарное здоровье коэффициентами разложить на реальное здоровье и уворот, которые в сумме, по формуле, дают эту суммарное здоровье.

      Вот для понимания расширил пример из статьи: http://take.ms/xMlDQ
      У рыцаря 1ур то же суммарное здоровье 37, как по тексту.
      Теперь мы хотим добавить ему шанс уворота (DODGE%). Суммарное здоровье раскладываем на HP и DODGE%, которые в сумме должны дать 37.
      Допустим, хотим дать уворот 40%. Значит его HP должно быть 100%-40%=60%, т.е. 22
      Проверяем по формуле: 22 / ( 1 — 40%) = 37
      Все, готово.

      Если DODGE% должен расти с уровнем, то привязываете его к отдельной прогрессии или заполняете вручную. Но надо учесть, что базовая прогрессия должно быть сильно экспоненциальной, иначе при lvlup-е будет уменьшаться реальный HP.
      Как-то так.

      На счет эффективности владения: а что это такое? Если нечто вроде «процент, на который увеличивается любой урон от оружия», то формула такая же, как у CRIT, т.е. у вас все правильно.
      Другой вопрос, что крит универсальный и работает всегда, а владение подразумевает, что есть разные типы оружия, значит его эффект ниже. Но тут слишком много неизвестно, включая то, где считается эта формула: если в бою, когда оружие уже выбрано и поменять уже нельзя — одно дело; если как универсальный индикатор силы на основе всех параметров — другое.
      В общем, надо понимать что за параметр и для чего считается формула.

      • Александр

        Два спасибо за ответы!

        Видимо я не так объяснил, прошу прощения. Я как раз делал прогрессию «насколько юнит силен здоровьем по отношению к урону», как у вас. И вот HP32 и HP33 — значения из этой таблицы, им соответствуют какие-то DMG32, 33. Так вот HP я на статы раскладываю:
        HP= (Vitality*10 +Defence) / (1 -Dodge%/100) / (1 — Resist%/100),

        получается в прошлом сообщении я пытался выяснить, правильная ли формула для расчета Dodge, если мы знаем все параметры, которые составляют HP на 32-м уровне и хотим догнать до расчетного значения HP33 именно Доджем. Просто выходит, каждое новое очко Dodge зависит от текущих составляющих HP и не совсем понятно, как эту стоимость рассчитать.

        С эффективностью, которая «процент, на который увеличивается любой урон от оружия» тоже не ясно что делать, если DMG оружия будет расти, в общем, проблема в оценке стоимости составляющих параметров при их прогрессии.

        • Значит вопрос я понял правильно.

          Смотрите, еще раз: у вас методика другая.

          В тексте предложен вариант, где вы сначала получаете расчетное значение, а потом из него выводите все остальные параметры, через коэффициенты. См. раздел «параметры из эффективности».

          И тогда вопроса «как догнать получившееся значение до расчетного через 1 параметр» просто не возникнет. Вы все решите через к-ты, а конкретно с доджем см. скриншот из предыдущего коммента.

          И чтобы ответить на ваш вопрос мне надо садится за эксель и подбирать новую формулу, это отдельная работа и к статье отношения не имеет.

          На счет вашей формулы. Выглядит приблизительно правильно, но есть нюансы: как считается дефенс, как срабатывает додж и резист. Параметры могут зависеть друг от друга и это влияет на формулу, поищите в тексте пример про ABSORB.

          Со эффективности владения оружием другой момент — если оно зависит от оружия, а оружие свободно меняется, то его просто невозможно заранее посчитать и надо поступать так, как описано в разделе «(не)очевидные параметры», т.е. исходить из логики и здравого смысла. Если стрелок имеет +10% к ружьям и в 100% ситуаций пользуется ружьями, то можно просто прибавлять ему +10% к уроню оружия, а дальше все зависит от ситуаций, при которых он не может или не захочет пользоваться ружьями.

          • Александр

            Еще раз спасибо за ваше время, попробую разобраться)

  • Алексей

    HP = HP / ( 1 — ( DODGE%+ABSORB%*DODGE% )

    Правильно ли я понимаю, что при увороте = 0% и 50% поглощении урона, по вашей формуле эффективное здоровье не изменится?

    • Алексей

      HP = HP / ( 1 — ( DODGE%+(1-ABSORB%)*DODGE% ) выглядит лучше

      • Алексей

        А вообще спасибо большое за всю работу, очень помогло

    • Верно заметили. Ваш вариант тоже с ошибкой:
      10 / ( 1 — ( 0 + ( 1 — .5)*0 ) = 10
      Правильный: HP = HP / ( 1 — ( DODGE%+ ABSORB%*(1-DODGE%) )
      Спасибо!

      • Алексей

        Да, интересно, что ломанулся проверять свои расчеты, а там все верно)