Unity Playmaker | Спаунер мобов без программирования

Unity Playmaker | Спаунер мобов без программирования

Делать игры без программирования на юнити возможно, легко, просто и непринужденно. И я расскажу как это можно делать с помощью Unity Playmaker.

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

О чем речь

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

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

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

Подготовительные работы

Плеймейкер работает по принципу скриптов - на игровой объект можно навесить сколько угодно компонентов плеймейкера (далее я буду именовать их как скрипты FSM, как сокращение от Finite State Machine), и в этих скриптах описать логику. Однако прежде чем мы начнем, для начала опишем логику результата, который хотим получить.

Планируется, что мы создадим универсальный спавнер мобов, который будет настраиваться следующим образом:

  • Мы сможем определить, будет ли спавнер повторно спавнить моба или нет.
  • Расстояние, на котором спавнер будет реагировать на игрока
  • Задержка повторного спавна моба.
  • Массив мобов, которых может заспавнить спавнер.

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

Для начала нам понадобится префаб, который будет выступать непосредственно спавнером, который мы будем ставить на уровне. Условимся, что делаем спавнер для ЭКШЕН ММОРПГ с видом от третьего лица. Я сделал вот такой агрегат:

Unity Playmaker | Спаунер мобов без программирования

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

С подготовкой покончили, приступаем к Визуальному Сквиртингу.

Простите, визуальному скриптингу

Для этого в родительском объекте нашего префаба добавляем компонент Playmaker FSM, именуем его к примеру "Spawner", и жмем Edit.

Настолько просто, что справится даже безрукий слепой сирота.
Настолько просто, что справится даже безрукий слепой сирота.

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

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

С чего начнем.
С чего начнем.

Не пугаемся, на экране нам показывает пустой стартовый стейт, то есть то состояние, в котором будет находиться игровой объект в момент инициализации. Хорошим тоном будет запихнуть в этот стейт всё, что нам нужно инициализировать, чтобы потом использовать в дальнейшем. Однако прежде всего, мы инициализируем лапками все необходимые нам переменные, которые будем использовать для настройки спавнера. Для этого идем в верхний правый угол скрина во вкладку Variables. Видим внизу инпут и селектор типа переменной. С помощью мозга и нехитрых движений пальцами, добавляем 4 переменные: две типа Float, одну булеву, и одну массив игровых объектов.

Когда мы создали переменную массива, нам нужно еще выбрать тип этого массива.
Когда мы создали переменную массива, нам нужно еще выбрать тип этого массива.

Получился набор переменных, которые мы осмысленно(!) именовали, и думаю смысл всем понятен. Через float переменные будем регулировать дальность обнаружения спавнером игрока, и время респауна моба, через булеву - сам респаун, и в массив будем загонять мобов. Ах да. Важный фокус.

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

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

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

Собираем логику

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

Первый стейт как я уже говорил - стартовый. В нем может происходить что угодно, но я предпочитаю в этом стейте инициализировать что-то, что в дальнейшем нужно будет использовать. Поэтому именую его всегда как INIT и крашу почему то в фиолетовый. Далее делаем следующее - определяем позицию спавнера, и корректируем её, чтобы моб нормально спавнился и не падал случайно под террейн в нашей ММОРПГ. В окне экшенов (которое открывается по кнопке Action Browser) ищем два экшена - сначала Get Position, а потом Vector3 Add XYZ. И настраиваем их как на скрине.

Unity Playmaker | Спаунер мобов без программирования

Расшифровываю. Сначала мы опредяем позицию нашего объекта (через Use Owner - имеется ввиду овнер скрипта), и сохраняем в переменную Spawned Position. Изначально переменной там нет, но мы нажимаем на дропдаун и выбираем пункт "New Variable..." . Обязательно ставим Space = World, чтобы нам вернуло нужные координаты. А вторым экшеном в этом стейте (то есть еще одним действием в пределах одного кадра) мы чуть корректируем Z координату для созданной нами переменной, добавляя к ней поллитра. Таким образом, у нас в Spawned Position будет значение X, Y, Z+0.5. То что надо.

Мы инициализировались, и стейт можно завершить. Для этого жмем ПКМ на стейте и выбираем Add transition - FINISHED.

Unity Playmaker | Спаунер мобов без программирования

Тем самым мы добавили событие перехода - мы объяснили автомату, что когда все действия в пределах стейта выполнены, мы его завершаем и можем перейти к следующему стейту. Создаем новый стейт через ПКМ, в котором мы будем проверять нашу первую настройку спавнера. Для этого в новый стейт добавляем экшн Bool test и выбираем в этом экшене переменную Repeatable, которую мы создали в самом начале. Теперь указываем событие (эвент так называемый) если переменная True и если она False - для этого выбираем в дропдаунах нижний пункт "New Event" и именуем осмысленно. Для тех кто умненький - да, это простейшая конструкция if/then/else. Для тех кто не очень умненький - не забудьте протянуть макаронину от FINISHED к новому стейту.

Unity Playmaker | Спаунер мобов без программирования

Мы создали 2 эвента, которыми может завершиться стейт, добавим их в качестве переходов в наш стейт через ПКМ, также, как добавляли FINISHED.

Супер просто. Вот наши новые эвенты.
Супер просто. Вот наши новые эвенты.

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

ЧТО ЗДЕСЬ ПРОИСХОДИТ
ЧТО ЗДЕСЬ ПРОИСХОДИТ

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

Первым делом мы обращаемся к заранее созданному нами массиву Mobs и берем из него случайный элемент. Если элементов будет всего 1 - то его и возьмет. Если больше - то выберется случайный. После этого, мы фиксируем выбранный элемент в виде локальной переменной (создаем также через пункт дропдауна New variable), именуя её SelectedEnemy. Далее мы непосредственно создаем новый игровой объект того типа, который мы взяли в массиве - то есть буквально создаем SelectedEnemy. И создаем его в той самой точке, которую мы определили в самом первом стейте. И записываем созданный объект в новую переменную (можно кстати в старую, не возбраняется и будет работать), которую именуем как SpawnedEnemy. И последним экшеном задаем SpawnedEnemy случайное вращение по оси Y, чтобы наш моб при появлении смотрел в произвольную даль.

Всё.

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

Вернемся на два стейта назад. Когда спавнер определялся, как он работает - многоразово или нет. И теперь сделаем ветку посложнее - многоразовую.

Делаем новый стейт. Для него нам понадобиться кастомный экшен Set enemy FOV by Tag, который мы возьмем из экосистемы Плеймейкера. Это такой "гитхаб", библиотека экшенов, которые делает коммьюнити. Обычно, если что-то нужно специфичное - там оно уже есть. Лезем в экосистему и через поиск находим нужный экшн, жмем Get. У меня уже этот экшен стоит. После компиляции, в экшен браузере плеймейкера появится новый экшен который можно будет также через поиск найти в списке. Добавляем его в стейт.

Unity Playmaker | Спаунер мобов без программирования

Настраиваем как на скрине. Вкрациях - мы говорим здесь автомату, что мы хотим, чтобы наш спавнер (use owner как мы помним), мог в радиусе дистанции, которая у нас выведена как переменная настройки, определял по кругу (Field of view может работать от 0 до 360 градусов, это фактически скрипт Глаз для объекта, то есть если мы ставим для FOV 360 градусов, значит у объекта будет обзор по кругу), определять игровой объект с тегом Player и в случае если объект попадает в обзор, отправляем событие Spawn.

Обязательно ставим галочку Every Frame - в этом случае стейт будет проверяться каждый кадр, пока в обзор спавнера не попадет игровой объект с тегом Player. Спавнить моба таким образом "дешевле" для сцены, нежели держать игровой объект созданным с самого начала исключительно потому, что выполнять проверку наличия игрока в поле зрения проще, чем держать созданным игровой объект со всей его внутренней логикой.

Добавляем переход Spawn для этого стейта (ПКМ на стейте, Add transition и тд), и добавляем новый стейт, который начнет выполняться когда спавнер увидит игрока в поле зрения. На деле можно скопировать стейт Spawn Enemy из соседней ветки - потому что мы по сути спавним моба, когда видим игрока. Все идентично.

Unity Playmaker | Спаунер мобов без программирования

Разница начинается дальше. Мы должны создать логику респауна моба. Причем я хочу сделать так, чтобы новый моб респавнился после смерти старого, когда игрок этого не видит. Мы же делаем крутую ММОРПГ, давайте делать всё по уму!

Делаем дальше два стейта. В первом ставим экшен Wait - и используем последнюю переменную настройки, которой определяем время задержки респауна.

Unity Playmaker | Спаунер мобов без программирования

А во втором стейте мы проверяем жив ли наш моб, которого мы спавнили, или нет. Для этого используем экшен Game Object is Null - здесь важная оговорка: мы предполагаем, что моб умирая, удаляется из игры. Если используем пулинг мобов, то нам нужно делать другую проверку (активен ли игровой объект). Когда моб умирает и мы удаляем его из игры, наша переменная SpawnedEnemy оказывается пустой. В данном случае это подходит нам для проверки.

Unity Playmaker | Спаунер мобов без программирования

Если моб жив, то переход будет через событие Wait, и нас вернет на предыдущий стейт еще подождать респавна. Еслиже в переменной пусто - то переход будет через событие Respawn, для него создаем новый стейт, в котором мы проверим, можем ли мы респавнить вообще моба, ведь по условию выше мы хотели респавнить моба когда игрок не находится возле спавнера, чтобы моб внезапно не появился перед игроком из пустоты. Поэтому в следующем стейте мы проверяем через экшен Game object Visible to Camera, видит ли наша игровая камера спавнер вообще или нет.

Unity Playmaker | Спаунер мобов без программирования

Здесь у меня в переменной GAME CAMERA определен игровой объект камеры, сама переменная глобальная. Но вы можете перетащить просто объект камеры со сцены в поле Camera и всё. Это не плохо, но не масштабируемо в перспективе (лучше глобальные объекты инициализировать в глобалки, к примеру камеру, интерфейс, игрока и тд.). В этом стейте мы заставляем автомат проверить, виден ли владелец скрипта для игровой камеры, и если да то немного подождать (переход на стейт Wait 1 sec в котором экшен Wait).

Если же спавнер не виден для камеры - то делаем переход через событие Respawn на стейт, в котором "высматриваем" игрока. Круг замкнулся.

Unity Playmaker | Спаунер мобов без программирования

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

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

3333
76 комментариев

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

16
Ответить

Слова человека, который никогда не делал игры xD

3
Ответить

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

2
Ответить

Сейчас анрильщики прибегут и докажут что "программирование" на blueprints это лучшее что придумала индустрия.

1
Ответить

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

1
Ответить

Уроки по разработке? На дтф, в 2023? Круто! Афтор писшы исчё)

3
Ответить

Спасибочки) будем писать))

2
Ответить