В этом уроке займёмся нашим главным героем - сделаем ему визуальное воплощение, научим его передвигаться и сделаем поверхность, по которой он сможет ходить. Если вам интересна эта тема, то не забудьте подписаться на канал и давайте уже творить!
Модель для нашего главного героя
Чем особенно хорош Unity для начинающего разработчика игр, так это своим магазином "ассетов". Что такое asset? Самый подходящий для нас перевод этого слова - это "ресурс", т.е. то из чего будет строится наша игра. Поэтому поищем модель для нашего главного героя там, благо бесплатных моделей там предостаточно.
Заходим на сайт https://assetstore.unity.com/ и выбираем там критерии поиска 3D, ведь мы решили сделать 3D-проект. Выбираем поиск по персонажам Character и находим заветную галочку "Free", чтобы сайт показал нам всех бесплатных персонажей. Никакой особой идеи у нас нет, кроме того, что это казуальная выживалка, а значит, вот такой низкополигональный бородатый джентельмен вполне подойдёт)
Поскольку мы хотим сделать игру и для пк, и для телефона, то нам лучше не использовать крутые детально проработанные модели, чтобы не раздувать вес игры и чтобы проще было ее оптимизировать под слабые телефоны. Низкополигональные модели вполне подойдут.
Кликнув по иконке, мы видим, что в бесплатной версии у нас даже есть комплекты моделек одежды для этого персонажа и набор анимаций. Замечательно! Берём! Добавляем его к себе в ассеты и во всплывающем окошке выбираем "Открыть в Unity".
Если наш проект открыт, то мы сразу попадём в Package Manager, который откроет нам окошко с этой моделькой, где будет кнопка, чтобы её скачать. Если по каким-то причинам этого не произойдёт, то мы сами легко можем в Unity открыть этот Package Manager во вкладке Window. Главное потом выбрать в поле Packages именно наши ассеты (My Assets):
Жмём Download, чтобы скачать, после чего рядом появится кнопка Import. С ней поступаем аналогичным образом и импортируем всё, что нам сей ассет предлагает. Если там окажется что-то, что нам не нужно, то мы сможем потом легко это удалить из проекта.
Теперь в окошке файлов нашего проекта, которое внизу, появилась новая папка. Находим в ней префаб персонажа. А что такое префаб? Это слово можно перевести как "заготовка" и по смыслу так и есть: это игровой объект с заготовленным набором настроек (это могут быть размеры, добавленные компоненты или скрипты и т.д.). Ну и собственно перетаскиваем этот префаб прямо в основное окно редактора (окно сцены):
Ура! Наш "лунтик" родился и теперь мы его даже видим - вон болтается в пустоте в позе буквы Т. Но если мы нажмём кнопку Play, то мы увидим его в совсем другом месте, с опущенными руками, да еще и немного двигающегося.
Что за магия вне Хогвартса?! Эта магия вполне объяснима. Во-первых изначально в проекте уже присутствует объект MainCamera и это то, через что мы будем видеть игру. Именно через "объектив" этой камеры мы смотрим в режиме Play. А вот в окошке сцены уже как бы своя, "рабочая" камера, которая в игре никак не участвует, но позволяет нам видеть мир в режиме редактирования.
Ну ладно с видом теперь понятно, но почему этот джентельмен внезапно ожил и задвигался? А все потому что в этом префабе уже присутствует настроенный компонент Animator, который и отвечает за анимации персонажа. Мы видим справа в инспекторе этот компонент с его настройками. И первое его поле Controller содержит название файла этого контроллера. Если по нему кликнуть при открытом снизу окне проекта с файлами, то мы сразу перейдем к этому файлу в какой бы папке он не лежал. Теперь если кликнуть двойным кликом по этому файлу, то у нас откроется окно Аниматора и мы увидим, что у персонажа уже присутствует одна анимация Idle (состояние покоя).
Пока что, наш "лунтик" умеет только находиться в состоянии покоя. Всем бы так уметь! Где эта волшебная кнопка, чтобы перейти в это состояние?) А в окне аниматора мы видим цветные прямоугольники, соединяемые стрелками. Entry - это начало, точка входа. Как только персонаж появится на сцене в режиме игры, то из этой точки он автоматически попадает в состояние своей первой анимации Idle. Все остальное мы уже будем делать сами из кода.
Управление и передвижение нашего персонажа
Давайте переименуем префаб персонажа, например в Player, и с помощью кнопки под аниматором, добавим ему стандартный компонент Character Controller, легко его найдя там через поле поиска:
Character Controller нужен нам, чтобы не изобретая велосипед, сделать управление персонажем и научить его уже ходить. Компонент стандартный и для нас, как для новичков, вполне подойдёт. Вообще, в создании игр, использование готовых решений - это нормальная практика, т.к. это позволяет ускорить процесс разработки игры, который, порой, может растягиваться на годы, если делать все с нуля самостоятельно.
Раз уж в нашей игре появился новый игровой объект в лице персонажа, то давайте не будем запихивать весь наш код в один скрипт, чтобы не получить "простыню", в которой сложно "что либо найти, легко потерять и невозможно забыть". Никто не любит бесконечные "простыни" текста на Дзене, если они, конечно, не снабжены картинками. Но в коде картинки не предусмотрены, поэтому для удобства лучше разделять код по разным скриптам и классам в зависимости от того, к чему эти поля и методы относятся.
Создадим новый скрипт, кликнув в окне проекта с файлами и перетащим его на объект Player. Либо, как вариант, добавим на этот объект в качестве нового компонента новый скрипт (New Script).
Назовём этот новый скрипт Player. Будем писать в нём, только то, что относится непосредственно к игроку. Предлагаю пока оставить всё что касается параметров персонажа в скрипте Game, а в Player напишем методы управления игроком. Получается вполне логично: игрок может управлять персонажем, но следить за параметрами и принимать решение о проигрыше будет сама игра.
Но чтобы перетащить скрипт получилось, придётся сначала "распаковать" префаб кликнув на объекте Player и выбрав Unpack Completely (почему так - разберемся позже).
Итак, вот он наш новый скрипт:
Предлагаю сразу же познакомить два наших скрипта между собой, чтобы они могли хотя бы узнавать о состоянии друг друга (например, достаточно ли персонаж жив, чтобы передвигаться). Для этого в скрипте Player (удалив ненужные нам комментарии) добавим публичное поле, чтобы иметь доступ к нему из инспектора (пока не будем заморачиваться с "правильной" приватностью всего и вся). Заодно сделаем ссылку на компонент CharacterController.
Не забывая после всех изменений сохранять скрипт, добавляем публичное поле типа Game. А что это за тип такой? А это тот скрипт, который мы с вами создали и который следит за здоровьем персонажа. Прелесть в том, что мы можем теперь сколько угодно его вешать, на какие угодно объекты и создавать его независимо работающие копии (экземпляры).
Но нам хватит одного и ссылку на него мы, как раз, получим, перетащив в окошко значения сам объект на котором висит скрипт Game. А CharacterController можно перетащить в соответствующее окно, просто потянув за название компонента, которое идёт после галочки ниже.
А теперь давайте наконец-то научим нашего героя передвигаться. Для этого воспользуемся простейшей системой ввода и доставшимся нам в комплекте со всем остальным классом Input (ввод), у которого есть метод GetKey() проверяющий нажата ли та или иная клавиша на клавиатуре. В качестве аргумента в этот метод вписываем одно из значений перечисления KeyCode, которые Visual Studio нам дружелюбно подсказывает, стоит только начать набирать внутри скобок название этого перечисления.
В методе Update() каждый кадр будем проверять нажата ли выбранная нами клавиша и если да, то в метод Move() контроллера, который мы повесили на персонажа (CharacterController), впишем вектор желаемого направления.
Что за вектор? В нашем 3D-проекте присутствует 3 измерения, которые легко представить в виде осей X, Y и Z. Как видно на примере нашего персонажа движение вперёд-назад будет осуществляться по оси Z (синяя стрелка), вверх-вниз по оси Y (зелёная стрелка), а влево вправо по оси X (красная стрелка).
Вектор в Unity задаётся тремя координатами, например Vector3(1, 1, 1). Но те кто помнит геометрию знаю, что тремя координатами можно, разве что, описать точку в пространстве, но уж никак не вектор. В Unity же имеется ввиду луч направленный из начала координат в указанную нами точку, а это уже вектор. Например, вектор представленный синей стрелкой в записи будет выглядеть как Vector3(0, 0, 1).
Есть глобальные координаты направления в которых неизменны (на юг это всегда на юг) и локальные для каждого объекта, направления которых меняются в зависимости от того, куда объект повернут (повернись и иди вперёд). Для удобства давайте решим, что глобальная ось Z (синяя стрелка) указывает на север, а ось X (красная стрелка) указывает на восток. Теперь с нашей легкой руки в нашей игре появились стороны света!
Итак, проверяем нажата ли кнопка и передвигаем нашего героя в нужном направлении. Для удобства в Unity есть готовые векторы глобальных направлений (например, Vector3.forward будет направление по оси Z и на север) - по ним и будем двигать.
Давайте проверять. Возвращаемся в Unity, жмём Play, нажимаем W. Ура! Наш персонаж поплыл в пустоте куда-то вперёд, куда глаза глядят. Но очень лениво и не торопясь, надо бы как то его ускорить.
В Unity единицы координат для удобства приравниваются к единицам метров и получается, что наш персонаж перемещается на метр в секунду. Это довольно медленно, поэтому давайте создадим поле speed, в котором через инспектор сможем менять скорость движения персонажа. Ну и умножим эту переменную speed на вектор движения. А заодно добавим ему возможность двигаться вправо и влево.
Вот это другое дело. Два метра в секунду уже лучше. К тому же теперь можно играться, меняя скорость в инспекторе, сколько угодно. Наш выживальщик, где то с краю экрана, парит в пространстве во всех направлениях не зная преград.
Расстановка и настройка игровых объектов
Давайте поставим нашего героя в центр кадра, обнулив координаты его позиции.
Поскольку мы решили делать вид сверху, то давайте поднимем камеру повыше и зададим ей угол наклона где-то 45 градусов.
Теперь другое дело, но неплохо бы добавить, какую то поверхность по которой будем ходить. Правой клавишей кликнем в окне иерархии и выберем 3D Object - Plane. На нашей сцене появилась плоскость. Поиграем с её настройками, обнулив координаты и увеличив масштаб.
В режиме Play мы видим даже тень главного героя и судя по ней, сей почтенный джентельмен во время движения решил позволить себе левитацию вне Хогвартса! Предлагаю его немного приземлить. Это произошло потому-что в компоненте CharacterController его коллайдер отвечающий за столкновения оказался смещён относительно модели персонажа.
Давайте это исправим. Выбрав игрока, найдем на нём компонент CharacterController и в поле Center - Y зададим значение 1 - это будет примерно центр персонажа по высоте. Точнее настроим потом.
Теперь в режиме Play персонаж больше не ливитирует над поверхностью. Но что-то его эти скольжения боком и задом, без передвижения ног, выглядят не особо реалистично, да и ходить босиком по снегу дело небезопасное - было бы неплохо для начала дать ему погулять по какой-нибудь траве или песку. Этим, и не только, займёмся в следующем нашем уроке! В этом возможно мы сделали и не так много, зато сколько полезной информации узнали без которой дальше двигаться было бы просто невозможно! Так что все самое интересное еще впереди!
А пока если тебе интересна эта тема, то обязательно подпишись на канал, чтобы не пропустить продолжение. Если тебе нравится как я подаю материал, то поставь лайк - мне будет приятно, ведь я стараюсь) Ну, а если остались какие-нибудь вопросы или есть какие-нибудь предложения, то смело пиши в комментариях - обязательно отвечу!
Начало разработки нашей игры в первой статье, где мы на практике разбираем основы программирования: