Хм, кто-то написал «увеличивает вдвое» в поле - но движку нужно число 2

Задайте каждому полю настоящий тип, чтобы его значение вело себя предсказуемо и проверялось - строка, текст, число, целое число и флажок (булево). Типизированное значение несёт своё поведение от редактора, через таблицу баланса, до движка

Этот туториал — часть серии Начало работы — День 1, Неделя 2.

Проблема: значение без типа не имеет поведения

К этому моменту враги живут в одной коллекции Враги, каждый из них - игровой объект с одинаковыми полями. Поля хранят значения - Здоровье = 60, Скорость = 30, Урон = 8, Размер = 1. Это огромный шаг. Но в этих числах прячется одна загвоздка.

Смысл значения мы задаем в названии поля: Урон = 8 - это явно урон, Здоровье = 60 - явно здоровье. А вот как задать поведение поля? Что в него можно записывать и что с ним можно делать.

Без типа каждое поле - просто свободный текст, и ни на один базовый вопрос нельзя ответить:

  • Можно ли его сортировать или сравнивать? Текстовое поле сортирует "10", "8", "60" как слова, а не как числа - так "10" окажется перед "8", и таблица баланса упорядочит значения неправильно.
  • Значение вообще валидно? В поле здоровья можно написать пять буквами, булевое (логическое) значение можно написать по-разному (True, true, да), а целое молча принимает 8.5. И никто не поймает эту ошибку в момент ввода.
  • Поймет ли движок введенное значение? В коде вещественные, целые и булевые типы ведут себя совершенно по-разному. Если тип неизвестен, движку приходится гадать - а это ровно то, с чего геймдизайн и код начинают расходиться.

Решение - задать каждому полю тип. Типизированное поле не меняет смысл значения - оно всегда было уроном или здоровьем. Тип добавляет поведение: значение можно проверять, сортировать, сравнивать и отдавать движку как ровно то, чего он ждёт. 10 остаётся 10; тип определяет то, что с ним можно делать.

Почему типизированные поля

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

  • Строка - одна строка текста, например имя.
  • Текст - более длинный многострочный текст, который можно форматировать.
  • Число - значение с десятичной частью (float), например 8.5.
  • Целое число - целое значение, например 60.
  • Флажок - переключатель true/false (булево значение).

Смысл типа не в формальности. Каждый тип меняет поведение поля:

  • Строка и Текст хранят слова, а не числа - так в поле имени не окажется случайно вычислений.
  • Число и Целое число хранят значения, с которыми можно работать математически - их можно сортировать, сравнивать и балансировать как числа, а не как текст.
  • Число (float) сохраняет десятичные части, а Целое число ограничивает значения целыми - так здоровье 60 остаётся чистым целым, а урон 8.5 допустим.
  • Флажок строго хранит true или false - никакой записи текстом и никакой двусмысленности.

Когда у поля есть тип, его поведение явное - движку не нужно гадать, как использовать это поле

Добавьте типизированные поля врагу

Применим это к одному из врагов - тому самому из бестиария прошлой недели. Зададим врагу следующие типы:

  1. Имя - поле Строка. Хранит имя врага одной строкой текста.
  2. Описание - поле Текст. Более длинное многострочное описание, которое можно форматировать.
  3. Здоровье - поле Целое число. Хранит целое количество очков здоровья - 60 у Посетителя-ходячего остаётся чистым целым.
  4. Скорость - поле Число. Скорость движения может быть дробной, поэтому десятичное значение допустимо.
  5. Урон - поле Число. Здесь допустимо десятичное значение, потому что урон может быть дробным.
  6. Размер - поле Число. Враги могут быть меньше единицы - у бронированного врага Размер = 1.5, и такое значение помещается только в десятичное поле.

Чтобы задать тип поля: в блоке Свойства откройте меню поля (нажав три вертикальные точки в ячейке поля), выберите Изменить настройки и укажите Тип. IMS Creators предлагает Строку, Текст, Число, Целое число, Флажок и другие типы, так что вы можете смоделировать ровно то, что нужно полю.

Блок «Свойства» врага с типизированными полями: Имя (Строка), Описание (Текст), Здоровье (Целое число), Скорость (Число), Урон (Число) и Размер (Число)

Вот и всё. Теперь каждое значение знает, что оно такое. Здоровье - целое число, Урон и Размер - десятичные - гадать больше не нужно.

Дизайнер пишет «×2» и «+100» в одно поле. А числовое поле не даст

Дизайнер мыслит эффектами: одна способность заставляет врага получать двойной урон, другая добавляет +100. Они не набирают 2 и 100 - они пишут ×2 и +100, потому что именно так эффект звучит у них в голове.

И вот тут тип начинает приносить пользу. Поле Число не примет ×2. Редактор просто откажется: «это не число». И этот отказ - суть. Он должен случиться сейчас, а не позже. Он заставляет дизайнера решить, чем на самом деле было ×2 - множителем, сложением, процентом, - прежде чем это станет строкой в таблице баланса или полем в JSON, который загрузит движок.

Поместите оба эффекта в одно поле Урон текстового типа - и решение отложится: x2 и 100 оба подойдут, и никто не жалуется. А программист, который до этого видел в этом поле только значения вроде 100, напишет логику, которая просто прибавляет значение к урону. В момент, когда кто-то добавит способность с x2, это предположение сломает систему. Тип Число ловит это намного раньше - он просто отказывается принимать x2 в момент ввода, когда исправить это ничего не стоит, вместо того чтобы пропустить неверное предположение, которое сломает игру позже.

Поэтому проектирование структуры - часть работы, а не формальность. Чтобы дать движку однозначную логику, одного поля мало: либо разделите операции по своим типизированным полям - Множитель урона (Число) и Бонус урона (Число), - либо добавьте поле, которое называет операцию, например перечисление Тип эффекта со значениями Умножение и Сложение. Теперь ×2 можно выразить: поле множителя хранит 2, а структура говорит, что это множитель.

Именно это значит «проектировать систему». Написать ×2 было легко; сделать этот ×2 реализуемым - как множитель, в поле, которое читает движок, - это и есть проектирование игры. Структура, которую вы выбираете в редакторе, становится той логикой, под которую программист сможет писать код, - без переделок и без догадок.

Результат: значения понятны и проверяемы

Типизация полей меняет то, что вы можете делать с данными.

  • Редактор проверяет значения. Раз поле знает свой тип, вводимое проверяется по ходу. Поле целого числа молча не примет "abc", а флажок останется чистым true/false вместо дрейфа в текст. Ошибки всплывают в момент ввода, когда их дёшево исправить.
  • Таблица баланса понимает числа. Когда значения типизированы и сравнимы, сортировка и сравнение "Здоровья" или "Урона" работают с настоящими числами - таблица знает, что 10 это число, а не строка, и как его упорядочить.
  • Движок знает, что это за значение. Когда вы позже загрузите JSON элемента в движок, типизированное поле несёт свой тип - вещественное, целое, булево. Движку больше не нужно гадать, текст это, число или флаг, и решать, как с ним обращаться в коде.

Это та же структура, что вы строите всё это время, но уровнем глубже: поля прошли путь от теста до структурированных значений - и теперь от сырых значений до значений с объявленным типом. Поведение ваших данных становится частью самого файла вместо того, чтобы жить в догадках и условностях.

Дальше: базовые объекты

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

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

Готовы дать своим показателям настоящие типы? Скачайте IMS Creators, откройте ims.cr5.space/desktop, откройте врага в своём проекте и задайте каждому полю тип - Строку для имени, Текст для описания, Целое число для здоровья и Число для скорости, урона и размера. Две минуты типизации - и ваши числа начинают что-то значить.

Готовы? Определите тип один раз и создавайте его много раз - следующий пост в этой серии.


FAQ

Почему тип поля важен?

Тип сообщает редактору, таблице баланса и движку, как ведёт себя значение - число, которое можно сортировать и складывать, текст или переключатель true/false. Смысл («это урон») уже приходит из названия поля; тип решает, что разрешено хранить и как пайплайн может использовать значение. Без типа ничто не может проверить, сравнить или доверять значению.

Какие типы полей доступны?

Самые распространённые: Строка (одна строка текста), Текст (многострочный, форматируемый), Число (десятичное значение), Целое число (целое значение) и Флажок (true/false). IMS Creators также предлагает более богатые типы полей, которые рассмотрим позже

Должны ли эффекты «×2» и «+100» записываться в одно поле?

Нет. Поле Число даже не даст вам ввести x2 - редактор откажется, заставив вас прямо здесь решить, множитель эффект или плоский бонус. Этот отказ и есть раннее предупреждение. А если втиснуть оба эффекта в одно нетипизированное поле, проблема всплывёт позже - когда способность с x2 дойдёт до программиста, который реализовал только сложение. Держите операции раздельно: поля Множитель урона и Бонус урона либо перечисление Тип эффекта со значениями Умножение / Сложение.

В чём разница между Числом и Целым числом?

Число хранит значения с десятичной частью, например 8.5. Целое число ограничивает значения целыми числами, например 60. Выбирайте по тому, что должно храниться: урон может быть десятичным, здоровье обычно целое.

Флажок - это то же самое, что "boolean" в коде?

Да. Флажок хранит значение true/false - булево значение. В интерфейсе он представлен как флажок, но хранимые данные - это булево (true/false) значение, которое движок читает напрямую.

Как задать тип поля?

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

Могут ли типизированные поля предотвратить неверные записи?

Да, в определённой степени. Так как редактор знает тип поля, он проверяет значения при вводе - поле целого числа не примет молча текст, а флажок останется чистым true/false. Это выявляет ошибки рано, когда их дёшево исправить.

Меняют ли типизированные поля то, что загружает движок?

Да. Типизированное поле несёт свой смысл в данных - float, целое или булево, - поэтому при загрузке JSON элемента движок знает, как интерпретировать каждое значение, а не догадывается о нём.

Поделиться:
Назад к блогу