{"id":3881,"url":"\/distributions\/3881\/click?bit=1&hash=e456b64697230d93edcda0dd20f3c8aa5d4abd88effca1a7571a12fa6564c38a","title":"\u0413\u0435\u0439\u043c\u0434\u0435\u0432-\u043a\u043e\u043d\u043a\u0443\u0440\u0441, \u0433\u0434\u0435 \u043f\u0440\u0438\u0437\u044b: \u0438\u043d\u0432\u0435\u0441\u0442\u0438\u0446\u0438\u0438 \u0438 \u043f\u0440\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435","buttonText":"\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c","imageUuid":"a410dbd1-804c-54dc-84ea-e6227d71d9b4","isPaidAndBannersEnabled":false}

Особенности прототипирования игр

Думаю, во многих компаниях есть свои R&D-команды, которые ищут новые продукты. Такую решили организовать и в нашей студии, и меня туда пригласили. Конечно же, поначалу мы все были окрылены идеей, что сейчас мы в команде экспериментальных проектов и будем писать ПРОТОТИПЫ. Звучит-то как! Мы будем экспериментировать с новыми библиотеками, так сказать «щупать» новые технологии и вообще делать что-то новое почти каждый месяц! Значит, нам не только не надоест какой-то проект, но и можно не заботиться о долгосрочной поддержке кода. Ведь это начальство разрешает забить на качество написания кода в угоду скорости разработки, ведь всё потом полетит в мусорку и будет переписываться с нуля. Но так ли всё радужно?

Меня зовут Андрей, я программист в студии IT Territory/My.Games, работаю в команде экспериментальных проектов. И хочу рассказать вам об особенностях нашего прототипирования игр.

Вообще я уже публиковал этот доклад на Habr. Но решил, что на DTF он зайдёт больше, да и мемосиками разбавить стоит)

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

До того, как меня позвали в команду, у меня уже был опыт создания прототипов. Но он касался, в основном, разработки проектов на различных GameJam’ах. Если кто-то не в курсе, то GameJam — это хакатон, но про разработку игр. Происходит это так: тебе описывают какую-то идею, дают двое суток, ты ночами не спишь, работаешь вместе с командой, и когда программируешь, то совершенно не думаешь о качестве кода. Главное — успеть сделать то, что можно показать жюри. А в IT Territory у нас иная задача: не просто сделать какой-то один прототип, в который поиграли и забыли (или начали готовить к Soft-launch), а поставить разработку прототипов на поток, чтобы можно было проверять различные гипотезы наших гейм-дизайнеров без особых затрат на создание полноценных проектов.

В общих чертах зависимость качества кода от времени разработки можно представить так:

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

Но увы, это идеалистическое представление. Реальность совершенно иная:

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

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

Так было на нашем первом прототипе, и это могло бы стать тенденцией в последующих проектах, но мы сделали выводы из проблем, с которыми столкнулись. И этими выводами я хотел бы с вами поделиться.

Не доверяй никому

В процессе разработки тебе могут сказать, что основная игровая механика будет таковой на протяжении всего прототипа. Она останется навечно. Однако ВСЁ может поменяться. В процессе одной из итераций к тебе может прийти гейм-дизайнер и сказать, что он никогда ещё так не ошибался, и нам надо сменить концепцию.

Дизайнер осознаёт необходимость переработки дизайна

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

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

В какой-то момент мы поняли, что нам необходимо вращать камеру. Но тогда придётся постоянно перерисовывать спрайты под разные углы, и вообще имелось несколько других нюансов, связанных с распределением нагрузки по участником команды. В итоге проект перешёл в 3D и постепенно стал таким:

Всё может полететь в мусорку

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

Делай универсальные компоненты

У нас в больших проектах гейм-дизайнеры заранее продумывают, что им нужно настраивать. Они вместе с программистами долго думают над тем, как создать внутренний редактор, на основе которого можно будет собирать различные игровые сущности. Программист просто отдает гейм-дизайнеру код, а тот собирает из него важный объект, который программист порой не предусматривал. Но с прототипами так не получится. Сложно взять и сходу придумать отдельные части некой сущности, из которых всё будет собираться. И всё же нужно пытаться выделять какие-то атомарные элементы. Например, можно выделить сущность логики поведения, чтобы гейм-дизайнеры или аниматоры могли просто накинуть этот компонент.

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

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

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

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

Дифференцируй всю разработку в целом

Это касается не только разделения на отдельные компоненты в коде, но и работы с отдельными префабами. В прототипе очень мало пространства для манёвра, поэтому пока проект ещё не разросся, два человека могут обрабатывать одну сущность, что потом приведёт к конфликту при коммитах. Мы столкнулись с этим в первую же неделю работы над прототипами, так как то и дело случайно затирали правки друг друга. Решили, что нужно как можно чаще использовать prefab variant/nested prefab, то есть максимально отдалять отдельные элементы.

Думай о дизайнерах

Гейм-дизайнеры придумывают какие-то механики, которые им нужно настраивать. Для этого в больших проектах с длинным жизненным циклом можно даже написать качественный редактор. Например, при работе над одним из наших боевых проектов мы потратили где-то неделю на создание редактора самолетов. В нём достаточно было ввести имя и требуемые параметры, нажать «ок», и редактор за пару минут собирал крутой самолёт, на сборку которого вручную у дизайнера мог уйти день, а то и два.

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

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

Здесь мы учли прошлые ошибки и старались максимально упростить настройки механик, разделяя их на логические группы. То есть сделали набор конечных операций, вроде «прийти к точке», «прицелиться в противника», «выстрелить» и т.п. Эти действия помещали в отдельные группы, а какое действие нужно совершить, определяли через веса переменных, которые юнит считывал из окружающего мира. Конкретные группы выбирались точно так же, как и операции, в соответствии с переменными окружающего мира. Так дизайнер мог выделить отдельные группы действий вроде бега или стрельбы, а уже в самих группах определить их конкретные реализации. Например, бежать от укрытия к укрытию или же идти на пролом к врагу.

Расширяй багаж знаний

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

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

О важности такого подхода мы вспомнили на одном из первых прототипов. Он представлял из себя шутер с видом сверху, в котором персонаж путешествовал по миру, а карта состояла из отдельных тайлов. По-хорошему, нужно было взять тайловую систему Unity или любой другой движок из asset store, но у нас с ними ранее никто не работал. Сейчас мы понимаем, что стоило выделить время и предварительно изучить доступные варианты, поскольку у такого подхода очень широкие возможности, которые позволили бы собирать уровни быстрее. Но на тот момент мы решили не рисковать и в конечной реализации прототипа просто использовали отдельный набор игровых объектов, на которые накинуты компоненты sprite renderer, а они отрисовывали квадратные спрайты. Мы взяли неопытного дизайнера-стажёра, из-за чего скорость сборки уровня была очень низкая, при этом во время сборки эти объекты даже не вытаскивались в отдельные префабы. И когда по результатам игровых тестов нам сказали, что тайлы карты выглядят «не очень», для их изменения нам пришлось «вручную» менять каждый спрайт, вместо того, чтобы просто подсунуть карте новую тайловую палитру.

Поддерживай баланс кода

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

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

Итоги

1. Всё в прототипе может перевернуться с ног на голову.

2. Необходимо иметь возможность быстро включать и выключать отдельную функциональность без вреда для проекта.

3. Максимально унифицируй компоненты.

4. Дифференцируй разработку.

5. Старайся постоянно расширять багаж знаний для работы «на передовой».

6. Поддерживай баланс кода.

0
17 комментариев
Написать комментарий...
Нелепый кофе

Ммммммммм вкусно. Большое спасибо, очень интересно написано. 

Ответить
Развернуть ветку
Андрей Боронников
Автор

Ура! Хоть какой-то фидбэк от внешней аудитории)
Спасибо, сильно переживал, что масло масленное написал.

Ответить
Развернуть ветку
Аккаунт удален

Комментарий недоступен

Ответить
Развернуть ветку
Денис Денисов

"В одном из прототипов у нас были текстовые квесты с развитием вариативности"
Не уверен попадает ли это в рамки той задачи, но недавно меня познакомили с Ink. Он интегрируется с Unity и обладает своим редактором (не визуальным, текстовым) для написания квестов. 
https://www.inklestudios.com/ink/
https://assetstore.unity.com/packages/tools/integration/ink-unity-integration-60055
Из плюсов - можно тестить в реалтайме прямо в редакторе. Опенсорс. Очень гибкий в плане синтаксиса.
Вдруг будет полезно в подобных задачах.

Ответить
Развернуть ветку
Андрей Боронников
Автор

О, благодарю!

Ответить
Развернуть ветку
Tramp Coder

Похоже на мой обычный день. Одна игра как один долгий процесс прототипирования. Новые идеи каждый день. Новые сущности. Новые scriptableobjects. За несколько лет настройки врага разрослись до сотен значений... Наверное так у всех, особенно когда отсутствует геймдизайнер. 
Самое смешное это именование данных. Запилил новую логику, добавив поля в словарь. Показал как работает и забыл. А через месяц художник берется за настройку и задаёт умные вопросы. Что значит этот параметр из трех слов? А этот из пяти, где первые три слова как в том параметре. 
Спасибо за статью. Прочувствовал прям всё.

Ответить
Развернуть ветку
Ричард Уизли

Автору респект, описал процесс разработки прототипов именно так, как оно на самом деле есть. Сам долгое время занимался этим на галере, подписываюсь под каждым пунктом.

Ответить
Развернуть ветку
Under Three

Написано и правда интересно, как раз с командой входим в эру прототипов

Ответить
Развернуть ветку
Игнат Емельянов

Золотые слова!

Ответить
Развернуть ветку
Немое Поле

Спасибо за статью, очень приятная и полезная 

Ответить
Развернуть ветку
Upproret

А вы пробовали писать прототипы на ECS. Unity DOTS тут, наверное, не подойдёт, так как быстрая разработка - это пока не про него, но в сообществе есть много уже стабильных инструментов.

Ответить
Развернуть ветку
Андрей Боронников
Автор

Tолько на GameJam'ax) Увы на работе пока что слишком дорого переходить на такую архитектуру, не имея экспертизу в ней у вей команды. 

Ответить
Развернуть ветку
Евгений Онянов

Тема паттернов не раскрыта) Какие чаще всего используются у вас? 
И в догонку про ассеты - какие чаще всего?

Ответить
Развернуть ветку
Андрей Боронников
Автор

Ну так сразу достаточно сложно ответить на этот вопрос. В принципе на всех наших проектах так или иначе используются большое количество разных паттернов, если того требует решение поставленной задачи. Самые распространённые это Фабрика для создания игровых сущностей и Декоратор для накрутки модификаторов на них. Это вот какие прям очень часто. Самый наименее частый - это Одиночка. Стараемся всеми силами от него уходить, но на прототипах позволяли себе грешок такой)
А из ассетов - мы стараемся использовать всё своё, так как ассеты большинстве своем подходят только для проектов с коротким жизненным циклом, когда просто подключил, зарелизил и забыл. У нас же одному из самых старых проектов лет 5 и он активно поддерживается. За такое долгое время там столько всего переписывали, что смысла покупать ассеты в проекты просто нет. Все так или иначе подгоняется под требования проекта, которые постоянно меняются. Проще самому написать своё и это уже дорабатывать. Хотя Lunar Console есть на каждом проекте.

Ответить
Развернуть ветку
Андрей

Так не хватает подобных материалов
И такое преступно маленькое количество плюсов 
В тяжелые времена живем

Ответить
Развернуть ветку
Эдуард Кик

Шикарная статья, спасибо

Ответить
Развернуть ветку
Alexandre Varsteiner

Спасибо за статью, сам как хобби разработчик любимое занятие пробовать ассеты в сторе. И когда их втыкаешь тут надо понимать как они работают и какие ограничения ведут. Ну и в целом насколько хорош или плох код.
Геймдизайн как и код, когда придумываешь алгоритм, у тебя все отлично. Но когда начинаешь его имплементировать тут и там баг.

Ответить
Развернуть ветку
Читать все 17 комментариев
null