Каждый гейм-дизайнер рано или поздно сталкивается с необходимостью регулярно работать с таблицами.
Базовых знаний Google Sheets или Excel обычно достаточно для выполнения простых расчетов и работы над игровым балансом.
Но когда игра развивается и обрастает новыми сущностями, возникает необходимость организовать для себя удобную и эффективную структуру.
При этом нужно иметь возможность легко ориентироваться в нем, дополнять и модифицировать, он должен быть устойчив к ошибкам.
В этой статье я систематизировал собственный опыт работы с таблицами и их дополнительными функциями, которые могут быть полезны как новичкам, так и опытным гейм-дизайнерам.
Примеры представлены в Google Sheets, поскольку они чаще используются командами разработчиков, но большинство из них применимо и к MS Excel.
Итак, представим, что мы делаем игру, в которой используется несколько видов оружия, и нам необходимо создать баланс, который позже будет загружен на сервер.
Изначально у нас есть только обычный нож, у которого есть два параметра - урон( Повреждать ) и количество атак в секунду ( Атак/сек ).
На первом этапе этих параметров нам достаточно для расчета баланса, а таблица выглядит следующим образом:
Со временем мы понимаем, что одного ножа нам недостаточно, и добавляем еще несколько видов оружия: пистолет, автомат и снайперскую винтовку.
Обсуждаем каждый пистолет с программистами, пишем документацию и начинаем разработку.
В какой-то момент мы доходим до этапа, когда нам нужно внести значения для нового оружия в таблицу баланса.
А то получается, что для пистолетов с пулями сделан отдельный параметр урона на пулю( Урон/пуля ), и был добавлен новый параметр Время перезагрузки , отвечающий за продолжительность перезарядки.
В результате балансовая таблица преобразуется следующим образом:
Все работает хорошо, разнообразием мы довольны, но игроки говорят, что им все равно как-то скучно.
Это означает, что нам нужно добавить еще несколько орудий: например, ракетницу и лазерную установку, которые сильно отличаются от всего, что мы делали раньше.
В то же время, чтобы игрокам не было скучно, мы вносим быструю модификацию снайперской винтовки, позволяющую ее пулям отравлять врагов.
Винтовка получает дополнительный параметр урона в секунду ( Урон/сек.
).
Наша лазерная система начинает использовать этот же параметр.
Ракетная установка приобретает свои, совершенно новые параметры.
В результате получается следующая таблица:
Со временем мы добавляем все больше и больше новых опций.
Таблица растёт, но пока мы ещё можем без проблем её просматривать и редактировать:
Посмотреть в полном размере Внезапно после очередного обновления мы узнаём от игроков, что они не понимают, какой пистолет круче.
Мы решили решить эту проблему самым простым способом — отображением ДПС каждого оружия в интерфейсе игры.
И здесь возникают различные проблемы и неудобства.
Например, чтобы рассчитать ДПС ножа для отображения в интерфейсе игры, нужно значение умножить Повреждать И Атак/сек , для пистолета и автомата - умножить Урон/пуля И Атак/сек , а для ядовитой пушки, способной отравить врага, к основному урону прибавьте урон от отравления.
В конце концов, каждое оружие имеет значение визуальный_DPS по вашей же формуле, и вам нужно это помнить.
Но поскольку мы настоящие геймдизайнеры, мы настолько ленивы, что не хотим помнить такие вещи.
Мы хотим иметь одну формулу расчета ДПС, которую можно будет без лишних раздумий растянуть на весь столбец таблицы.
Конечно, кто-то может посмотреть на наш баланс и сказать: «А что тут думать? Пушек всего шесть, все равно просто, и даже если у каждого своя формула, не запутаешься».
Но стоит помнить, что мы делаем вымышленную игру с вымышленным балансом, и наша таблица теперь во много раз проще той, что используется в реальных играх.
Вот, например, небольшая часть баланса реального проекта, и это всего лишь один лист:
Посмотреть в полном размере Но вернемся к нашему примеру.
Мы пришли к выводу, что решили упростить себе жизнь и сделать одну формулу расчета отображаемого ДПС.
Можно пойти по пути «в лоб» и составить сложную многоуровневую формулу, умножающую и складывающую разные параметры в зависимости от названия пистолета.
Это будет работать, но нам придется корректировать формулу каждый раз, когда добавляется новое оружие.
Пока мы думаем над решением этой проблемы, возникает еще одна, о которой мы раньше не задумывались: ДПС, который отображается игроку, не обязательно отражает то, что на самом деле происходит в игре.
Оказывается, реальный ДПС для баланса нужно рассчитывать с учетом большого количества других параметров: от точности и скорости перезарядки до длины анимации рисования оружия и эмпирического коэффициента сложности механики в каких-то очень запущенные случаи.
Многие из этих параметров и коэффициентов нам вообще не нужны в итоговом балансе и служат только для расчетов, но их нужно где-то хранить и редактировать.
Они могут помочь нам в этом вспомогательные таблицы .
В них мы проведем сложные расчеты и добавим дополнительные параметры, которые нужны только нам.
Более того, в нашем итоговом балансе, который мы собираемся загрузить на игровой сервер, в параметре визуальный_DPS сделаем функцию, которая будет обращаться к вспомогательной таблице и вытягивать из нее готовое расчетное значение.
Сама вспомогательная таблица не будет загружена в игру и останется служить нам инструментом игрового дизайна.
Что такое вспомогательные таблицы и как ими пользоваться
Для нашего примера с расчетом ДПС мы сделаем вспомогательную таблицу, в которой разделим орудия по типам, добавим необходимые расчетные коэффициенты и рассчитаем итоговое значение - и просто возьмем это значение в итоговую балансовую таблицу с помощью одного из Google Таблицы функционируют без дополнительных вычислений.То же самое мы можем сделать и с ценой на оружие в магазине.
Обычно он также рассчитывается с учетом дополнительных коэффициентов, и параметры для его расчета удобно хранить отдельно от боевых.
Следующие таблицы получены со вспомогательными параметрами.
Я поместил их на отдельный лист и назвал его Расчеты .
Естественно, ДПС здесь рассчитывается иначе, чем в реальной игре, но сейчас для нас это не так важно:
Посмотреть в полном размере После того как мы посчитали ДПС во вспомогательной таблице, нам нужно перенести его в основную таблицу, которая в итоге будет залита в игру.
Для этого мы используем ВПР.
ВПР
Функция ВПР позволяет получить искомое значение из таблицы по значению в первом столбце этой таблицы и номеру столбца.
Простой пример Допустим, мы хотим получить значение размера банана из таблицы фруктов.
- Ключ_поиска в нашем случае – Банан;
- Диапазон — вся таблица, кроме заголовков;
- Индекс — 3, т.к.
Размер — третий столбец таблицы;
- Is_sorted - false, потому что мы ищем точное совпадение.
Так мы получили длинное значение — именно то, что искали.
В итоге, чтобы вставить нужный нам параметр из вспомогательной таблицы в основной баланс, пишем в поле Visual_DPS формулу ВПР и получите следующий результат:
Вот как выглядит эта формула в нашей таблице баланса, которую мы собираемся использовать в игре:
Посмотреть в полном размере
- А2 — имя, которое будем искать во вспомогательной таблице (на скриншоте выше — Нож);
- Расчеты!$A$1:$O$10 — вспомогательная таблица, исключая заголовки;
- 12 — номер графы «ДПС» во вспомогательной таблице;
- ЛОЖЬ — для поиска по точному значению.
Подводные камни VLOOKUP – индекс
Базового функционала ВПР достаточно, чтобы значительно ускорить работу гейм-дизайнера, и в принципе многие на этом могут остановиться.Но если наш проект достаточно большой или развивается с большой скоростью, всплывают проблемы, которые раздражают и увеличивают вероятность совершения ошибок.
Первый из них — параметр index, отвечающий за номер возвращаемого столбца.
Когда основной баланс вырастает до 30-40 столбцов, базовые параметры во вспомогательных таблицах легко могут быть в полтора раза больше.
Кроме того, время от времени возникает желание изменить формулы расчета и добавить новый коэффициент, а то и несколько.
В результате раньше мы с помощью ВПР отбирали параметр в 13-м столбце, и это был урон, а теперь в 13-м столбце появился новый коэффициент, и урон переместился в 15-й столбец.
Если мы это вовремя заметили, то можем изменить индекс вручную.
А что, если сместилось сразу 10-15 параметров? Что если взять один и тот же параметр и использовать его в нескольких местах основного баланса? Получается, что основное неудобство для нас — указание параметра индекса в виде числа.
Если бы можно было указать конкретный столбец вспомогательной таблицы по имени, а не по номеру, это было бы гораздо проще, ведь тогда нам не важно, какой это номер.
И для этого есть простое решение – мы можем добиться нужного нам результата, заменив числовой индекс на функцию ПОИСКПОЗ.
Эта функция возвращает порядковый номер заданного значения в заданном диапазоне.
В этом случае искомое значение можно указать в текстовом виде, и это именно то, что нам нужно.
Полученное отображение нужного параметра теперь можно сделать визуально более понятным, ведь мы проходим через функцию, в которой можем написать имя этого параметра.
В нашем случае параметр во вспомогательной таблице называется DPS, а конечный результат будет следующим:
Стоит отметить, что указанные диапазоны в этих функциях разные.
ВПР использует для поиска всю таблицу.
Функция ПОИСКПОЗ использует только ту часть, в которой мы ищем имя параметра, то есть строку с заголовками параметров, по которым происходит поиск.
Итак, наша формула стала длиннее и, на первый взгляд, сложнее, но теперь мы можем добавлять любые новые параметры и менять их места во вспомогательной таблице – в основном балансе это ничего не нарушит. Первая трудность преодолена.
Что еще мы можем улучшить в нашей структуре?
Подводные камни VLOOKUP — фиксированные диапазоны
Другая проблема, аналогичная предыдущей, касается диапазона поиска, указанного в ВПР.Этот диапазон должен быть задан конкретным адресом из вспомогательной таблицы, и это предотвращает добавление в него новых строк и столбцов вне диапазона.
Мы добавляем новые строки каждый раз, когда хотим добавить новое оружие, и новые столбцы, когда появляются новые настраиваемые параметры.
Суть в том, что когда мы добавляем новое оружие в конец нашей таблицы настроек, нам нужно увеличить дальность поиска в основном балансе на строчку.
Со столбцами это решается достаточно просто: мы можем задавать диапазоны внутри ВПР и ПОИСКПОЗ с запасом, вообще не используя буквы столбцов.
Вот как похожая формула выглядит в основной таблице:
Посмотреть в полном размере Пунктирной линией выделены диапазоны, которые она просматривает с помощью ВПР и ПОИСКПОЗ во вспомогательной таблице.
Эти диапазоны не зависят от количества используемых столбцов.
Посмотреть в полном размере Для строк это тоже можно решить одним трюком: новые строки вспомогательной таблицы не добавляются в конец нужного диапазона, а вставляются между существующими строками.
То есть, добавляя во вспомогательную таблицу новую пушку, мы пишем ее не под последней пушкой, а между последней и предпоследней, вставляя между ними новую строку.
В Google Таблицах вставка строки или столбца в середину диапазона автоматически расширяет этот диапазон, где бы он ни использовался.
Но для некоторых случаев это не очень удобно – к тому же об этом нужно постоянно помнить.
Кроме того, для каждой новой логической части вспомогательной таблицы нам необходимо использовать свой отдельный диапазон.
Поэтому, несмотря на то, что эти методы работают, при длительной работе со вспомогательными таблицами они становятся достаточно неудобными.
Что можно сделать, чтобы это исправить?
Функция ФИЛЬТР
Мы решили, что главное неудобство для нас — это строго определенные диапазоны.Но на самом деле функционал таблиц позволяет свести разные диапазоны к одной понятной универсальной записи.
Для этого воспользуемся функцией ФИЛЬТР и парой дополнительных технических полей во вспомогательной таблице.
Функция ФИЛЬТР позволяет нам фильтровать любой диапазон на основе заданных условий.
При этом в результате она возвращает полный диапазон, который можно подставить в другие функции.
Например, если мы хотим вытащить из основной таблицы баланса только ту часть, в которой у пушек ДПС > 50, это будет выглядеть так:
Посмотреть в полном размере В этом случае нам не обязательно фильтровать всю таблицу — главное, чтобы количество строк в диапазоне поиска и диапазоне условий было одинаковым.
Условий может быть несколько — например, если мы хотим вернуть диапазон названий оружия, оставив только оружие с ДПС > 50 и для параметра StarterGear установлено значение false, это будет выглядеть так:
Посмотреть в полном размере Но вернемся к нашей проблеме: как сделать VLOOKUP более удобным? Для этого в нашу вспомогательную таблицу добавим служебный столбец с указанием типа диапазона и будем использовать фильтрацию по нему.
В качестве диапазона поиска мы будем использовать всю нашу таблицу, независимо от количества строк — от столбца A до Z. А в качестве параметра фильтрации мы будем использовать столбец с нашим новым параметром, поместим его в столбец B и назовем его Tag. Чтобы приблизить наш пример к реальности и немного разнообразить его, добавим еще одну вспомогательную таблицу на случай, когда нужно использовать некоторые коэффициенты, исходя из редкости оружия.
Вот как это будет выглядеть:
Посмотреть в полном размере Теперь, если мы хотим использовать какой-либо вспомогательный параметр таблицы в нашей основной таблице, мы получим к нему доступ с помощью VLOOKUP, MATCH и FILTER следующим образом:
Посмотреть в полном размере Да, формула стала еще длиннее и на первый взгляд это делает ее менее читабельной, но на самом деле теперь мы можем с первого взгляда понять, что в ней происходит. Если описать логику этой формулы словами, то она будет выглядеть так: «Во вспомогательной таблице найдите А2 с тегом Weapons_battle и верните для нее значение параметра ДПС».
При этом мы теперь можем добавлять столько таблиц, сколько захотим, помечая их уникальным тегом.
Вот как это выглядит с подсветкой в Google Таблицах для нашего расчета DPS:
Посмотреть в полном размере На самом деле мы не полностью решили нашу проблему, поскольку диапазон в функции ПОИСКПОЗ по-прежнему задается конкретной строкой.
Это значит, что нам нужно задать его вручную для случаев, когда мы хотим использовать значения из вспомогательной таблицы оружие_экономика или из нашего нового стола оружие_редкость .
Чтобы не думать об этом, создадим аналогичный служебный столбец для заголовков наших вспомогательных таблиц.
Чтобы избежать путаницы, мы будем использовать тот же тег, который уже использовали.
Вот как это будет выглядеть во вспомогательной таблице:
Посмотреть в полном размере А вот как меняется основная формула:
Посмотреть в полном размере В балансе это будет выглядеть так:
Посмотреть в полном размере Формула очень длинная, но если вы знаете, как она работает, ее все равно легче понять, чем указывать диапазоны по отдельности.
Кроме того, мы можем смело растянуть его на всю колонку баланса и быть абсолютно уверенными, что все данные будут корректно загружены в основную таблицу, которую мы планируем загрузить на сервер и использовать в игре.
Этой базовой структуры должно быть достаточно для удобного хранения данных, манипулирования ими и добавления новых вспомогательных таблиц с соблюдением макета вспомогательной таблицы с отдельными тегами для строк данных и заголовков.
Но эта запись все равно довольно длинная, особенно если в основном балансе используются более сложные формулы - например, когда нам нужно взять из вспомогательной таблицы два разных параметра и перемножить их в основном балансе.
Длинную запись сложно читать и сложно объяснить людям, которые впервые сталкиваются с таблицей.
Но оказывается, что мы можем значительно упростить его и сделать более понятным с помощью очень простых модификаций.
Улучшения структуры
Помимо того, что формула длинная, в ней есть еще одна нерешенная проблема: нужно помнить, что столбец A:A отвечает за теги заголовков, C:C — за отдельные теги таблицы, а вся таблица с данные помещаются в B:Z. Но бывают случаи, когда нужно брать не всю таблицу, а только названия элементов — то есть столбец B:B. Бывают и случаи, когда таблицы B:Z нам уже недостаточно, так как вспомогательных параметров больше.Чтобы не думать об этом и не запоминать сочетания букв, будем использовать именованные диапазоны.
Для этого в Google Таблицах выберите нужный диапазон и с помощью контекстного меню выберите опцию создания именованного диапазона.
В правой части экрана появится меню, где мы сможем присвоить имена всем нужным нам диапазонам.
В результате мы можем изменить нашу итоговую формулу так, чтобы в ней практически не осталось безымянных аргументов.
Зная общую структуру хранения данных и помня названия диапазонов, такие формулы можно писать вообще не заглядывая во вспомогательную таблицу.
Причём, если нам нужно изменить размер этих диапазонов — например, в случае, когда у нас параметров больше, чем букв английского алфавита — мы точно так же вызываем меню с именованными диапазонами и делаем это тут же — для например, заменив Расчеты! B:Z в основном диапазоне на Расчетах!B:AZ. Вот как будет выглядеть наша формула после добавления именованных диапазонов:
Посмотреть в полном размере Он стал короче, его теперь гораздо легче читать и редактировать, а также использовать в более сложных формулах соединений.
Для более живого примера немного усложним исходную задачу и добавим в основной баланс новое поле.
РедкостьЦена .
Предположим, что в нем мы решили использовать формулу, умножающую стоимость пистолета и коэффициент, зависящий от его редкости.
Для этого используем все, что мы создали ранее:
Посмотреть в полном размере Формулы извлечения параметров стали компактнее и понятнее: из них исчезли буквенно-цифровые обозначения дальностей, за исключением А2 (название оружия) и М2 (редкость оружия), необходимых для поиска во вспомогательной таблице.
Таким образом мы добились желаемого: основная таблица, которую мы планируем загрузить на сервер и использовать в игре, имеет четкие и читаемые формулы, которые можно растянуть на всю колонку при добавлении новых пушек.
При этом все расчеты вынесены в отдельную таблицу, которую мы можем смело редактировать.
Эту структуру и подход я до сих пор использую как для хранения расчетов баланса, так и для других калькуляторов, требующих вспомогательных данных.
Есть еще несколько приемов, которые используются специально, но это совсем частные случаи, поэтому подробно останавливаться на них не буду.
Надеюсь, эта статья поможет вам найти свой подход к таблицам.
Возможно, кто-то из вас сможет предложить другие улучшения структуры или свою собственную версию, решающую больше проблем.
В любом случае буду рад любой критике.
Если у вас есть вопросы, обязательно задавайте их в комментариях, я постараюсь на все ответить.
Теги: #Разработка игр #Игры и игровые консоли #Дизайн игр #разработка игр #работа с электронными таблицами #gamedev #googlesheets #баланс игры
-
Track Track — Библиотека Mousetrackapi.
19 Oct, 24