Как сделать пинбол в юнити

Добавил пользователь Владимир З.
Обновлено: 05.10.2024

Unity — это среда, которая позволит детям почувствовать себя настоящими разработчиками игр! На движке Unity 3D ребята могут создавать анимацию, запрограммировать игровую сцену и полноценные игры. А также познакомиться с языком программирования "Си шарп", на котором в Unity пишутся скрипты.

Школа программирования для детей "Пиксель" подготовила бесплатные уроки Unity 3D, которые познакомят детей с программой и научат создавать первые игры. Поддержите нас, ставьте палец вверх, если наш бесплатный курс по Юнити окажется полезным для ваших детей.

Как скачать Unity 3D на ПК

Для начала скачаем и установим программу на компьютер.

Урок 1. Как сделать анимации в Unity 3D

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

Урок 2. Как сделать телепорт в Unity 3D

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

Урок 3. Как сделать спавн объектов в Unity 3D

Мы изучим 2 способа создания спавна объектов: на канвасе (canvas) и в пределах камеры. А еще узнаем, как создавать префабы.

Урок 4. Триггеры в Unity 3D | Столкновение персонажей

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

Урок 5. Как создать таймер в Unity 3D

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

Урок 6. Перемещение объекта мышью в Unity 3D

Функция Mouse Drag или, по-другому, метод перетаскивания нужен для того, чтобы перетаскивать объекты в игре. Например, как мы показываем в видео, чтобы перемещать еду на персонажа и кормить его.

Урок 7. Как сделать полосу здоровья персонажа в Unity 3D

Health Bar или полоса здоровья тоже неотъемлемая часть любой игры. Мы научимся ее программировать, так чтобы полоса плавно увеличивалась и уменьшалась.

Урок 8. Как сохранить игру в Unity 3D

Если мы хотим сохранять очки или уровни в нашей игре, то нужно воспользоваться методом PlayerPrefs.

Урок 9. Создаем игру "Раннер" в Unity за 30 минут

Урок 10. Как экспортировать игру из Unity на ПК или Android (как настроить для Play Market)

В этом видео расскажем, как собрать игру под ПК или под Android: в каком порядке собрать сцены, какие им дать номера, а еще какие настройки нужны, чтобы загрузить игру Play Market.

Урок 11. Как загрузить игру в Play Market

Мы собираем игру и заполняем все настройки для Play Market. Теперь другие пользователи смогут сыграть в вашу игру, а вы будете на этом зарабатывать.

Урок 12. Как сделать прыжок в Unity 3D

В этом уроке мы разберем, как сделать прыжок персонажа в 2D- и в 3D-проекте. Для этого мы создадим две сцены, напишем скрипты на языке Си Шарп.

Урок 13. Как управлять персонажем в Unity 3D

Давайте научим нашего персонажа двигаться. Для этого мы зададим переменные типа float, они будут отвечать за скорость, поворот и перемещение по горизонтали и по вертикали. И, конечно, напишем скрипты для 2D- и 3D-версии игры.

Урок 14. LineRenderer в Unity 2D

LineRenderer позволяет упростить рисование линий. В этом видео мы напишем два скрипта: Line Point позволит проводить прямую линию между любыми двумя точками, а с помощью Draw Line мы сможем рисовать неотрывную линию.

Урок 15. Как сделать автосимулятор в Unity 3D | Как сделать гонки в Unity 3D

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

Наши плейлисты регулярно пополняются, подписывайтесь на наш YouTube-канал , чтобы следить за выходом новых видео и открывать для себя мир IT-технологий!

Если же вам нужен наставник, загляните в Школу программирования для детей “Пиксель”: запишитесь на полный курс по разработке игр на движке Unity 3D .

Простая реализация многоступенчатого прыжка 2D-символа в Unity

Краткое введение

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

Может быть в моемБиблиотека GithubилиБиблиотека облака кодаЗагрузите, основной код управления ролями Asset/Scene/Example/ExamplePlayerController.cs 。

Ниже показан эффект тройного прыжка в сцене Example в проекте:

Конфигурация проекта

2D-характер этого проекта принимаетUnity Asset StoreО материале. Если читатель хочет попрактиковаться в коде, как описано в этой статье, вы можете открыть тестовую сцену.В этой сцене, помимо кода, были настроены анимация персонажей, эффекты частиц и управление камерой.


Среди них Main Camera и CM vcam1 - это контент, связанный с камерой, Ground и Platforms - это карты, BlackBall - это 2D-персонаж, а его подобъект Texture - это спрайт 2D-персонажа, Particle System - эффект замыкающих частиц и Cloud. - это когда 2D-персонаж прыгает в воздухе. Объект облачного эффекта по умолчанию находится в неактивном состоянии, и реализация облачного эффекта будет рассмотрена позже в этой статье. Конечный автомат анимации BlackBall имеет 3 параметра SpeedH 、 SpeedV 、 IsGrounded , Соответственно укажите горизонтальную скорость, вертикальную скорость и возможность касания земли.

Я установил [Edit] - [Project Settings] - [Physics2D] - [Gravity] - [y] равным -49.05 вместо значения по умолчанию -9.81. Это сделано для улучшения динамизма прыжка 2D-персонажа по сравнению со значением по умолчанию, При этой настройке 2D-персонаж более подвижен при падении.

Реализация горизонтального движения

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

Создайте PlayerController Скрипт добавлен в объект BlackBall, код следующий:

Установите соответствующий в окне инспектора moveSpeed Ценить. На этом этапе должно быть возможно управлять горизонтальным перемещением персонажа с помощью клавиш со стрелками влево и вправо.

Осуществление прыжка

Прежде всего, реализуйте одну из простейших функций прыжка: нажмите кнопку прыжка, и персонаж сможет прыгать.

Добавьте следующие поля:

в Update() Добавьте следующий код:

Создайте следующие методы для управления прыжками:

к FixedUpdate() Добавьте следующий код:

Установите соответствующий в окне инспектора jumpUpSpeed Ценить. На этом этапе вы можете прыгать с помощью клавиши пробела.

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

Предположим, что персонажу разрешено совершить n последовательных прыжков.

Если n 0, персонажу разрешается совершить прыжок хотя бы один раз. Поскольку взлет с земли нужно подсчитывать один раз, допустимое количество прыжков в воздухе равно n-1, а общее количество прыжков в воздухе после того, как персонаж отрывается от земли, равно k.

  • Когда персонаж касается земли, в это время k = 0, персонаж может прыгать.
  • Когда персонаж в воздухе
    -Если k = n -1, персонаж не может продолжать прыгать.

Согласно приведенному выше анализу, для достижения настраиваемых многоступенчатых прыжков необходимо реализовать следующие части: обнаружение касания персонажа (то есть, чтобы определить, находится ли персонаж на земле), запись и управление количеством прыжков в воздухе. .

Обнаружение приземления

Реализация обнаружения касания в Unity очень проста. Основная идея состоит в том, чтобы определить расстояние между нижней частью персонажа и землей. Когда расстояние достаточно мало, мы думаем, что персонаж касается земли, в противном случае мы думаем, что персонаж находится в воздухе. В основном полагаться на Physics2D.OverlapCircle(Vector2 point, float radius, int layerMask) Метод реализуется при point против layer для layerMask Расстояние между объектами меньше radius Время означает point Достаточно близко к объекту конкретная реализация выглядит следующим образом:

Добавьте пустой подобъект GroundCheck для объекта BlackBall и поместите его внизу персонажа, как показано в форме ромба:


Добавьте слой "Земля" в окне инспектора и установите для слоя всей травы и платформы в сцене значение "Земля".

Добавьте следующие поля:

в FixedUpdate() Добавьте следующий код:

И изменим код переключения состояний анимации:

Устанавливается отдельно в окне Инспектора whatIsGround против groundCheck Для наземного слоя и объектов GroundCheck. На этом этапе, когда игра запущена, должна воспроизводиться соответствующая анимация, когда персонаж перемещается по земле горизонтально.

Многоступенчатая реализация

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

в Start() инициализация airJumpCount 0

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

модифицировать Jump() Методы, указанные ниже:

Измените код переключения состояния анимации следующим образом:

Установить в окне инспектора allowJumpTimes , На данный момент настраиваемая многошаговая функция в основном завершена.

Сделай прыжок красивее

В игре с прыжками с платформы, такой как Super Mario, мы обнаружили, что падение персонажа часто происходит быстрее, чем прыжок. На картинке ниже показан скриншот прыжка Марио. Каждый прыжок занимает 18 кадров для прыжка вверх и 10 кадров для падения. Кадр, падение Быстрее.


В нашей реализации время прыжков вверх и вниз одинаковое.Очевидно, прыжки в стиле Марио обладают большей маневренностью и игровым процессом. Так как же сделать падение быстрее? —— Ускорение падения персонажа больше, чем ускорение, когда он поднимается.

Конкретная реализация выглядит следующим образом:

в FixedUpdate() Добавьте следующий код

Приведенный выше код делает ускорение персонажа при падении ускорением при подъеме. fallGravityMultiplier Когда значение больше 1, персонаж падает быстрее, чем когда он поднимается.

В начале статьи упоминается, что подобъект Cloud of BlackBall используется для демонстрации эффекта прыжков персонажа в воздухе. Это может добавить некоторой визуальной обратной связи к прыжкам персонажа в воздухе и улучшить игровой процесс.

У объекта Cloud есть анимация взрыва, которая воспроизводится всякий раз, когда персонаж прыгает в воздух.

Конкретная реализация выглядит следующим образом:

Добавьте следующие поля

в Start() Добавьте следующий код

Создайте новый метод сопрограммы

И в Jump() Добавьте код для запуска сопрограммы в части кода, прыгающей в воздухе

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

Возникла внезапная проблема: пусть во время битвы герои и получают опыт, повышают уровень — но этот прогресс должен сохраниться только при успешном завершении уровня. А смена уровня у меня идет следующим пунктом плана работ!

Так что в этой части будет смена уровня вместо прокачки героев.

Взаимоисключающие цели

Вот какая штука. По моей задумке хочу сделать следующее:

1) Сделать выбор следующей битвы так же, как в AFK Arena сделан мистический лабиринт.


Краткое описание

Игрок может выбрать только ближайшую к себе точку. Например, он выбрал клетку с Мистиком. Тогда следующим шагом он может выбрать либо правую точку (карету), либо центральную. Крайний левый флаг будет для него недоступен

2) Сделать выбор следующей битвы максимально простым.

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

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

Грамотно озвученная проблема — часть решения

Хмм, в лабиринте игрок принимает решение… Делает выбор… Планирует маршрут… Стоило только озвучить проблему — тут же пришло в голову решение. Сочетает и простоту восприятия, и предоставляет игроку выбор, игрок ощущает, что он принимает решение. Встречайте!


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

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

Объекты или UI?

В юнити есть как игровые объекты (по сути, просто болванки, на которые можно повесить всякое), так и готовые кнопки интерфейса. И на то, и на другое можно нажать (но с объектами нужно извращаться для этого).

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

С другой стороны готовые кнопки уже имеют важную для дальнейшего реализацию — всякие красивости для нажатого состояния, отпускаемого, ну и так далее. Итак, выбираю! Следующие уровни будут отображаться в виде UI кнопок — как раз потому что они уже имеют нужную мне визуализацию нажатий.

Завершение биты — переход на экран выбора — начало битвы

Есть два варианта

Битва и экран карты— две отдельные сцены.

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

Переделка архитектуры объектов на сцене

Суть вот в чем. Будет примерно следующее

Но сейчас у меня при старте на сцене куча объектов безо всякого порядка — в основном из-за того, как сделан спавн героев игрока и противника

Решаю просто: перед вызовом спавна героев создаю два дополнительных объекта — для героев игрока и героев противника соответственно

Какое-то адское извращение, но работает же!

После этого при спавне героев достаточно указать, что соответствующий _goParent… их родитель. Это так мило — теперь у них есть родитель.

Главное, что мне это дало — как только spawner отключается, пропадают все герои и панель с их скиллом. И появляются при его включении.

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

А дальше что?

Ах да — забыл. Теперь архитектура объектов на сцене выглядит вот так


Дальше нужно добавить саму структуру кнопок / битв. Располагаться они будут как на одной из картинок выше.

Хммм, а как это сделать кодом?

Конечно же, первым делом полез в интернет! Наверняка уже кто-то такое делал) Только ничего подобного не нашел. Хорошо, придется думать.

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

В итоге придумал какую-то абсолютно хитровыдуманную конструкцию. Что-то мне подсказывает, что я перемудрил


Ну и что я натворил

Тогда я делаю что-то типа такого:

И да, в первом случае for не нужен, но это для меня. Иначе могу запутаться.

Разделение битв и особой сущности

По задумке с одной стороны будут битвы, с другой — будет находиться эта самая сущность. Но тут вообще просто — создаю функцию SetBtnType(int type)

И добавляю ее вызов в SpawnMap() куда-нибудь в конец

Тут я понимаю, что забыл повесить какой-нибудь скрипт на кнопку карты. Так что делаю новый скрипт ClickMapBtn и вешаю на префаб кнопки карты. Щас будет полное извращение, но в этом скрипте у меня будет в том числе храниться индекс этой кнопки 0_о

Конечно, и в самом спавнере еще нужно добавить массив с кнопками

Сброс параметров всего, что отключается

Помните DEBUG_SWITCH, которая просто отключает / включает объекты? Забудем о ней! Теперь на каждом объекте есть скрипт, который не просто отключает объекты, а еще делает что-нибудь с их параметрами, если это нужно.

И эта свитч вызывает нужную функцию из скрипта каждого такого. По сути, у моих объектов появился контроллер, отслеживающий их состояние. Круто же!

Какие типовые сущности у меня есть? Герои, кнопки их скиллов и кнопки карты.

Сходу наткнулся на интересное архитектурное решение. По какой-то причине контроль ползунков на кнопке использовании скила у меня находится… В скрипте Characteristics. Это гениально, не иначе. Значит, переношу всю эту систему туда, где ей самое место — в скрипт копки. А Characteristics будет туда только передавать актуальные данные.

Заодно исправил незамеченный баг с постоянным ускорением наполнения маны. И добавил шкалы здоровья с маной над всеми героями — ничем не отличается от аналогичных шкал на кнопках.

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

А всякие WakeUp вообще простейшие

В итоге получилось вот так

При респавне герои начинают с начальными характеристиками.

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

Но это еще не все!

Игра умеет менять состояние "битва / карта", теперь нужно сделать так, чтобы кнопки на карте запускали битву — причем разную в зависимости от кнопки!

Для этого вернусь в скрипт, спавнящий на карте кнопки боев и добавлю что-то типа такого

Гляньте, как классно все получается! Номер уровня увеличивается только у кнопок по центру и крайних левых

Подготовка завершена! Теперь, наконец, можно запускать битву, выбрав нужную кнопку на карте.

В бой!

В скрипте смены состояния делаю небольшие перестановки, вынеся кучу текста по разным функциям

И происходит магия!

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

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

Результат

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


Уф, теперь можно заняться прокачкой героев. Вернусь, когда с ней закончу!

Спрайт выстрела

Снаряд – объект, которым мы будем пользоваться очень часто. В игре будет несколько сцен, в которых игрок будет стрелять. Что мы должны использовать в этом случае? Префаб (Prefab), конечно же! Для этого проделайте следующие действия:

  1. Импортируйте текстуру
  2. Создайте новый спрайт в сцене
  3. Установите изображение на спрайт.
  4. Добавьте "Rigidbody 2D" с равныим нулю значениями "Gravity Scale" и "Fixed Angles".
  5. Добавьте "Box Collider 2D" размером (1, 1) .

Та-дам! У нас появился выстрел. Теперь настало время немного поскриптить. Создайте скрипт, назвав его "ShotScript":

Прикрепите "ShotScript" к спрайту. Также добавьте "MoveScript", т.к. ваши снимки будут двигаться. Теперь перетащите объект выстрел в панель "Проект" для создания Префаба. Он нам совсем скоро понадобится. Вы должны иметь следующую конфигурацию:

Конфигурация Выстрел 1

Если вы запустите игру с помощью кнопки "Play", вы увидите, что выстрел движется.

Столкновения и повреждения

Тем не менее, выстрел (пока) не наносит повреждений. Ничего удивительного, ведь мы не сделали скрипт обработки повреждений. Создадим его, назвав "HealthScript":

Добавьте "HealthScript" на префаб спрута.

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

Убедитесь, что выстрел и спрут находятся на одной линии, чтобы проверить столкновение. Напоминаю, что 2D движок ничего не знает про ось Z, поэтому ваши 2D коллайдеры всегда будут в той же плоскости. А теперь, запустите нашу сцену. Вы должны увидеть следующее:

Здоровье врага превосходит урон от выстрела, поэтому он выживет. Попробуйте изменить значение hp в "HealthScript" врага:

Стрельба

Удалите выстрел из сцены. Теперь, когда мы с ним закончили, ему нечего там делать. Нам нужен новый скрипт для стрельбы. Создайте его под именем "WeaponScript". Этот скрипт мы будем использовать везде (игроки, враги и т.д.) Его цель заключается в to instantiate снаряда перед игровым объектом, к которому он привязан. Вот полный код, больше, чем обычно. Объяснения ниже:

Прикрепите этот скрипт к игроку. Скрипт делится на три части:

Переменные во вкладке "Inspector"

Здесь у нас есть два члена: shotPrefab и shootingRate .

Первый необходим для установки выстрела, который будет использоваться с этим оружием.

Выберите игрока в сцене "Hierarchy". В компоненте "WeaponScript", вы можете увидеть свойство "Shot Prefab" со значением "None". Перетащите префаб "Shot" на это место:

Использование префаба

Unity автоматически дополнит скрипт это информацией. Удобно, не так ли?

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

Будьте осторожны: изменение значения переменной во вкладке "Инспектор" в Unity не приводит к сохранению этих значений в скрипте. Если добавите этот скрипт в другой объект, значение по умолчанию будет таким, которое написано в скрипте. Если же вы хотите сохранить отредактированные параметры, вы должны открыть свой редактор кода и записать эти значения там.

Оружие обладает определенной частотой выстрелов. Без этого параметра можно было бы выпускать неограниченное количество патронов в каждом кадре.

Поэтому нам нужен простой механизм охлаждения. Если его значение превышает 0 , мы просто не можем стрелять. Мы вычитаем прошедшее время из каждого кадра.

3. Публичный метод создания атаки

Главная цель этого скрипта – активироваться через другой скрипт. Поэтому для создания снаряда мы используем публичный метод.

Создав екземпляр снаряда, мы извлекаем скрипты объекта выстрела и оверрайдим некоторые переменные.

Внимание: С помощью метода GetComponent () можно создать точный компонент (а значит, и скрипт, потому что скрипт – тоже компонент) объекта. Используйте generic ( ) для обозначения конкретного компонента, который вам нужен.
Кроме того, у нас есть GetComponents () , вызывающий список вместо первого и т.д.

Использование оружия с классом игрока

Если вы запустите сейчас игру, то увидите, что ничего не изменилось. Мы создали оружие, но оно совершенно бесполезно.

В самом деле, если "WeaponScript" был бы привязан к классу, мы никогда не смогли бы использовать метод Attack(bool) .

Давайте вернемся к нашему "PlayerScript".

В функции Update() добавьте этот кусочек кода:

На данном этапе неважно, поставите вы его перед или после движения.

  1. Мы определяем нажатие кнопки стрельбы ( click или ctrl по умолчанию).
  2. Извлекаем скрипт объекта.
  3. Мы запускаем Attack(false) .

Button down: Вы уже наверняка заметили, что мы используем метод GetButtonDown() для обеспечения ввода. "Down" в конце позволяет нам ввести данные при нажании кнопки и только один раз. GetButton() будет выводить true в каждом кадре, пока гирок не отпустит кнопку. В нашем случае нам явно необходимо поведение, обеспечиваемое методом GetButtonDown() . Попробуйте использовать GetButton() и почувствуйте разницу.

Запустите игру с помощью кнопки "Play". Вот что вы должны получить:

Пули летят слишком медленно? Поэкспериментируйте с префабом "Shot" чтобы выбрать ортимальное значение. Попробуйте также добавить вращение игроку: (0, 0, 45) . Пули двигаються под углом 45 градусов, даже если вращение спрайта выстрела является некорректным – а ведь мы его не изменили.

Shooting rotation

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

Вражеский снаряд

Мы создадим новый снаряд с помощью этого спрайта:

Вражеский снаряд

Если вы так же ленивы, как я, продублируйте префаб "PlayerShot", переименуйте его в "EnemyShot1" и измените спрайт, как описано выше.

Для дублирования создайте экземпляр, перетащив его на сцену, переименовав созданный игровой объект и, наконец, сохранив его как `Prefab’.

Или можно просто продублировать Prefab напрямую внутри папки с помощью ярлыков cmd+D (OS X) или ctrl+D (для Windows).
Если вы не выбираете легких путей, вы можете создать новый спрайт с параметром rigibody, коллайдером с триггером и т.д.

Правильный масштаб - (0.35, 0.35, 1) .

Вот, что у вас должно получиться.

настойки для вражеского снаряда

При нажатии "Play" произойдет выстрел, который потенциально может уничтожить врага. Это из-за свойств "ShotScript" (которые по умолчанию плохо совместимы с Poulpi).

Не изменяйте ничего. Помните наш "WeaponScript"? Он то и установит правильные значения.

У нас есть префаб "EnemyShot1". Удалите экземпляры со сцены, если они есть.

Также, как мы делали для игрока, также нам нужно добавить оружие и врагу, а потом вызывать Attack() чтобы выстрелить. Вот, что нам надо сделать:

  1. Добавьте "WeaponScript" врагу.
  2. Перетащите префаб "EnemyShot1" в переменную "Shot Prefab" скрипта.
  3. Создайте новый скрипт под названием "EnemyScript". Он просто будет запускать стрельбу в каждом кадре. Что-то вроде автострельбы.

Прикрепите этот скрипт к осьминогу. У вас должно получиться следующее (заметьте, что частота стрельбы немного звеличилась до 0.75 ):

Настойка осьминога с оружием

Замечание: Если вы модифицируете игровой объект в сцене, не забудьте сохранить все изменения в префабе , использовав кнопку "Применить" справа сверху от панели "Инспектор".

Попробуйте сыграть и посмотреть!

Итак, мы сделали то, что хотели и теперь и по нам тоже стреляют.

Если повернуть врага, вы можете сделать его стреляющим в его слева, но, хм. спрайт повернулся вверх ногами, а нам это не нужно.

Перевернутый спрут

Давайте исправим это недоразумение.

Стрельба в любом направлении.

"WeaponScript" был написан особым образом: вы можете выбрать направление стрельбы, просто вращая прикрепленный игровой объект. Мы уже видели это раньше, когда вращали спрайт врага. Суть в том, чтобы создать пустой игровой объект как ребенка префаба врага. Итак, нам нужно:

  1. Создать пустой игровой объект. Назовем его "WeaponObject".
  2. Удалим "WeaponScript", прикрепленный к префабу врага.
  3. Добавим "WeaponScript" к "WeaponObject" и установить свойства префба выстрела как мы это делали раньше.
  4. Повернем "WeaponObject" вот так (0, 0, 180) .

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

Enemy with a new object

However, we have a small change to make on the "EnemyScript" script.

В своем нынешнем состоянии вызов GetComponent () в "EnemyScript" возвращает null. В самом деле, "WeaponScript" больше не привязан к одному объекту игры.

К счастью, в Unity также доступен метод, использующий детскую иерархию игрового объекта, который называется GetComponentInChildren () .

Для GetComponent<>() , GetComponentInChildren<>() также существует в форме множественного числа: GetComponentsInChildren () . Обратите внимание на s после "Component". Этот метод возвращает список вместо первого соответствующего компонента.

На самом деле, просто для удовольствия, мы также добавили возможность управления несколькими видами оружия. Мы просто манипулируем списком вместо одного экземпляра компонента. Взгляните на весь "EnemyScript":

Наконец, нужно обновить скорость выстрела путем настройки публичной пременной "MoveScript" из префаба "EnemyShot1". Скорость выстрела должна быть больше скорости движения спрута:

Мы сделали великого и ужасного осьминога. А давайте еще реализуем стрельбу в двух направлениях?

Стрельба а двух направлениях

Эта задача реализуеся всего в пару кликов. Для этого не нужны никакие скрипты:

  1. Добавьте другое оружие врагу (дублируя первый "WeaponObject").
  2. Измените угол поворота второго "WeaponObject".

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

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

Нанесение урона игроку

Наши осьминоги внушают ужас? Как бы не так! Да, они могут стрелять, но это не наносит повреждения игроку. Может, у них холостые патроны? Давайте разбираться.

Просто добавьте "HealthScript" на игрока. Убедитесь, что сняли галку с поля "IsEnemy".

Конфигурация скрипта, отвечающего за здоровье игрока

Запустите игру и почувствуйте разницу:

Бонус

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

Солкновения игрока с врагом

Давайте посмотрим, как мы можем обработать столкновения между игроком и врагом, поскольку сейчас они сталкиваются друг с другом без последствий. Столкновение - это результат пересечения двух не-триггерных 2D коллайдеров. Нам просто нужно обрабатывать событие OnCollisionEnter2D в PlayerScript :

При столкновении мы наносим урон как врагу, так и игроку благодаря наличию компонента HealthScript . К нему привязано все, что относится к здоровью/урону.

Массив снарядов

Когда вы играете, вы можете наблюдать ва вкладке "Иерархия" (Hierarchy), что игровые объекты создаются и удаляются только через 20 секунд (если они не сталкиваются с игроком или врагом).

Если ваша цель создание огневой завесы для которой требуется МНОГО пуль, эта техника вряд ли подойдет.

Один из способов увеличить количество пуль – использовать массив. По сути, это набор пуль ограниченного размера. Когда массив заполнен, удалите старый объект и замените его на новый.

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

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

Имейте в виду, что использование метода Instantiate довольно затратное удовольствие. Применяйте его осторожно.

Поведение пули

В хорошем шутере должны быть запоминающиеся боевые сцены.

Некоторые библиотеки вроде BulletML значительно упрощают определение сложных и зрелищных bullet patterns.

BulletML для Unity

Если вы хотите сделать полную версию игры в жанре Shoot'Em Up, ознакомьтесь с нашим плагином BulletML for Unity

Задержка выстрела

Добавьте несколько вооруженных противников в сцену и запустите игру. Вы увидете как синхронны все враги.

Можно просто добавить в оружие задержку: поставьте охлаждение на любое значение выше 0. Вы можете использовать алгоритм или просто поставить случайную цифру.

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

Еще раз, это зависит от вас. Все зависит исключительно от того, чего вы хотите достичь с вашим геймплеем.

В следующем уроке

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

Результат

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

Читайте также: