Игровой баланс #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 надо уменьшать на вероятность уворота: больше уворот — реже поглощение.
Дальше — по аналогии — можно рассчитывать не только параметры юнитов, но также предметов, заклинаний, зданий и прочего.
Позже я расскажу, как моделировать битвы между отрядами разной численности и распишу несколько нераскрытых нюансов. А пока считаем, что разобрались.
Та же логика работает для любого другого жанра, только вместо HP и DMG вы определяете другие параметры, из которых складывается эффективность юнитов/предметов/зданий и т.п.
Для фермы это может быть “польза”, поделенная на “скорость”, где польза — приносимый ресурс, умноженный на коэффициент ценности этого ресурса, а скорость — время, которое нужно для производства.
Параметры из эффективности
Возвращаемся к нашей прогрессии силы.
Мы уже разобрались, что такое сила и у нас уже есть прогрессия. Осталось только вывести из нее параметры юнитов.
Проще всего это делать с помощью коэффициентов к средним значениям: например, для «танка» нужно будет указать, что его здоровье в 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 (Все получилось, хоть и с погрешностью округления).
В итоге наши расчеты будут выглядеть примерно так:
Все остальное генерируется автоматически, ничего не надо заполнять и проверять, в этом и есть чудо автоматизации.
Кстати, также рекомендую помечать ячейки с задаваемыми параметрами — потом будет проще ориентироваться.
Заполнение вручную
Параметры можно вписывать и вручную, а формулой только «проверять», чтобы вписанное не сильно отличалось от расчетного.
Как это может выглядеть:
Теперь все значения внесены вручную, а под каждым юнитом есть столбик с проверкой. В нем — относительная разница между полученным PW и расчетным, которая подсвечивается красным (conditional formating), если превышает 10%.
- Плюсы вписывания: значения лучше смотрятся, их можно связать с эмоциями, например «Адская бомба с уроном 666″.
Еще я люблю использовать четные числа для «толстых» юнитов и нечетные для дамагеров.
А эпические юниты хорошо смотрятся с круглыми числами. - Минусы вписывания: больше работы, больше мусора в таблицах и выше риск ошибки.
Aвтоматическое заполнение с коэффициентами или ручное с проверкой — выбор за вами.
Если ваши юниты и способности могут прокачиваться на десятки уровней, в эмоциональных числах нет никакого смысла, все равно их почти не будет заметно.
Зато, если речь о каком-то уникальном контенте, который не меняется и не имеет сотню состояний, задумайтесь о ручном заполнении, с ним красивее.
Используя ручное заполнение, добавьте на главный лист результат всех проверок, чтобы не было нужды после каждого изменения проверять все листы.
На этом основы кончаются, а мы можем спокойно получить все параметры всех юнитов. Переходим к обещaнным нюансам.
Хардкорная часть баланса
Как я уже упоминал: автоматизация вносит погрешность.
Видя перед собой только цифры, мы забываем про вещи, казалось бы, очевидные. Их лучше проговорить заранее и учитывать при балансировке.
1. (Не)очевидные параметры
Да, все параметры сводятся к HP и DMG, это чистая математика.
Но в балансе всегда есть здоровая доля «магии» из-за невозможности предсказать и посчитать все возможные события и комбинации.
И не везде есть прямое математическое решение — иногда вам придется вносить изменения «на глаз» и проверять в прототипе.
Вот некоторые примеры.
Самый простой: лечение.
Легко догадаться, что для целителя DMG = силе исцеления. Однако, атакующий всегда найдет цель, а целитель может быть неэффективен, когда он один на поле или когда все здоровы. Плюс он не лечит выше максимального здоровья.
Поэтому при сравнении целителя и дамагера с одинаковыми параметрами расчетная эффективность целителя должна быть ниже.
Я обычно использую коэффициент 0.7–0.8 к DMG.
Другой пример: лучник атакует летающие цели, рыцарь — нет.
Лучник, очевидно, «эффективнее» и для правильного баланса ему надо заложить коэффициент к урону.
Но подбирать коэффициент придется «на глаз», опираясь на тестирование и некоторые соображения. Например:
- Количество летунов в игре. Если летун, допустим, всего один — к-т должен быть минимален.
- Эффективность самих летунов. Если все летуны заведомо слабые и легко выносимые, а «лучников» в игре много — к-т так же не должен быть слишком высоким.
Этот пример относится ко всем параметрам, подразумевающим определенный фильтр характеристик (у Шрайбера это зовется интранзитивными механиками).
Например, к «пробитию брони», при условии, что броня есть не у всех персонажей. Или к повышенному «урону по зданиям». Или к «стойкости против гоблинов».
В некоторых случаях есть возможность посчитать коэффициент математически: умножив чистую эффективность свойства на вероятность его использования. Например “+100 к урону против гоблинов” надо считать как “+100 * вероятность ударить по гоблину”, иначе говоря, “+100 * долю гоблинов среди ожидаемых врагов”.
Другой пример: атака на расстоянии.
В игре с перемещением или позиционированием побеждает тот, кто начал атаковать раньше; соответственно, ему нужен коэффициент к урону.
Вам может показаться, что у этой задачи есть математическое решение: мы можем посчитать среднее количество попаданий до прямого столкновения, опираясь на среднюю скорость врагов.
И в этом даже есть смысл. Но нельзя забывать:
- Во-1-х, далеко не всегда столкновение будет начинаться с максимального радиуса атака. В играх типа Clash Royal можно скидывать юнитов с ближней атакой прямо на юнитов с дальней — тогда весь эффект дальнего боя сводится к нулю.
В каждой игре свои ограничения — считая по максимуму, мы, скорее всего, завысим эффективность. - Во-2-х, мы не учитываем тактику комбинирования «жирных» юнитов спереди и дальнобойных сзади. В зависимости от игры эта тактика может быть выгодна по-разному, от «вообще не имеет смысла» (к-т минимальный), до «только так и нужно играть» (к-т максимальный). Определитесь, что нужно для геймплея, и подкрепите этот вариант коэффициентом.
Этот же пример можно отнести ко всем вопросам позиционирования, включая, например, преграждение пути, замедление, другие формы crowd-control’a.
И в каждом случае есть логичное, но не полное математическое решение: например, для мага с «заморозкий» можно посчитать среднее число поражаемых целей, умножить на среднюю атаку и на его силу замедления — получится обоснованное число «урона, который цели не смогли нанести из-за эффекта замедления», и это число смело можно плюсовать кDMG мага.
Но — в зависимости от механик и тактик игры — реальная эффективность может сильно отличаться от наших расчетов.
Так что без тестирования и правок «на глаз» не обойтись.
2. Эффективность группы
Этот вопрос уже упоминался: если в игре есть битвы с разным количеством юнитов или юниты типа «отряд из N персонажей» — мы должны знать, как посчитать их эффективность с учетом количества.
Просто умножить «силу» на количество недостаточно — наше число будет отражать «силу» отряда, в котором одновременно сражается только один юнит.
На количество (N) следует умножить отдельно HP, отдельно DMG:
PW(N) = ( HP*N ) * ( DMG*N )
Иначе это можно записать HP*DMG*N², что кажется даже логичнее — но мы так делать не будем, и вот почему: эта запись отражает эффективность отряда, который имеет общее здоровье и постоянный урон, не меняющийся от гибели членов отряда.
В реальности такое встречается редко, поэтому DMG надо понизить на коэффициент, отражающий смертность. А это уже зависит от конкретных механик игры: например, от распространенности AoE атак, от возможности отряда атаковать на расстоянии и т.д.
Возьмем навскидку коэффициент 0.7, и тогда формула выглядит так:
PW(N) при N>1 = ( HP * N ) * ( DMG*0.7*N )
Но если вы хотите использовать одну формулу и для отрядов и для одиночных героев, то её надо переписать:
PW(N) = ( HP*N ) * ( DMG + DMG * 0.7 * (N-1) )
3. Синергия
Очевидно, что с умом собранная колода сильнее, чем суммарная сила карт, из которых она состоит. И дело не только в эффекте группы: смысл декбилдинга (подбора колоды) в хорошем взаимодополнении. Например, мощные, но уязвимые карты можно сочетать с “защитниками”, которые принимают на себя урон.
Теоретически синергию можно посчитать в балансе — но зачем?
Допустим, мы выясним, что в игре есть ряд выгодных комбинаций. Мы можем сократить их пользу, но игрок потеряет мотивацию искать взаимодополняющие карты, а ведь это приятный игровой момент.
Сама по себе “синергия” — не проблема.
Проблема наступает тогда, когда выгода небольшого числа комбинаций настолько явная, что значительная часть игроков пользуется одинаковыми колодами. Это уменьшает разнообразие и снижает фан от находки хорошего сочетания.
Но “явная” — не математическая категория. К тому же поведение игроков часто не связано с реальным балансом. Например, они нередко считают какую-то комбинацию или стратегию “имбой” — от imbalanced, несбалансированной — только потому, что ею пользуется популярный киберспортсмен.
В итоге — синергию, которую нельзя предсказать заранее, руководствуясь только здравым смыслом, не имеет смысла и балансировать. Проблемы лучше решать тогда, когда они возникнут в игре: для этого потребуется хорошо настроить аналитику и исправлять проблемы раньше, чем игроки успеют заклеймить баланс.
Рейтинги вместо процентов
Это совершенно отдельная механика, в которую можно было бы и не углубляться, если бы не её распространенность и частая необходимость.
Начну с проблемы: допустим, мы делаем классический 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 полученный урон будет рассчитываться на сервере по той формуле, с которой сделаны прогрессии брони и пенетрации. Если для прогрессии вы использовали фибоначчи — вас, скорее всего, засунут в блендер и порвут на сотню маленьких геймдизайнеров.
________________
В следующем посте: модели и экономика.
Краткое содержание цикла про баланс:
— Введение и подготовка к работе
— Начало работы: константы и прогрессии
— Боевой баланс или расчет эффективности
— Матмодели и простая экономика
— Комплексная экономика: поведение и цикл
— Монетизация и экономика
— Дополнительно: тервер, кривая обучения, заключение
4 комментария
egorpcp
Нам надо умножить средний HP на ранее выбранный множитель = 24 * 1.5 = 37
соответственно DMG = 4 * ( 1 / 1.5 ) = 4 * 0.7 = 3
ОТКУДА взялось ЧИСЛО 0,7???
dev01s
1/1.5 = 0,666. Его округляем до 0,7
same2000
Ничего не понятно, но очень интересно.
sidestorm
Отличная статья. Спасибо.