Основы создания 2D персонажа в Unity 3D 4.3. Часть 3: прыжки (и падения)
Всем привет. Продолжаем серию уроков по созданию 2D персонажа. В предыдущих двух частях мы сделали персонажа, который может находиться в двух состояниях: покой и бег вправо-влево. Возможно, для очень простой игры этого будет достаточно. Но мы не будем останавливаться на достигнутом и сегодня научим нашего персонажа прыгать.
Наша цель звучит просто, но в ее реализации будут некоторые тонкости. Во-первых, нам надо как-то определить, что персонаж находится в состоянии прыжка. Это будет немного сложнее, чем определение состояния бега. Во-вторых, нужно прикрутить соответствующую анимацию. Здесь мы могли бы поступить аналогично анимациям покоя и бега — циклично воспроизводить соответствующие кадры анимации, пока персонаж находится в состоянии прыжка. Но мы реализуем более гибкий вариант. Состояние прыжка на самом деле состоит из двух состояний: взлет и свободное падение. Кроме того, бывают частные случаи — только взлет и только падение. Если мы прикрутим одну общую анимацию для этих двух состояний (например, поджатые ноги и развевающийся на ветру плащ) — это может выглядеть нормально, но не совсем реалистично. В реальности, когда человек прыгает, положение его тела, рук, ног отличается при взлете и при падении. Мы создадим такую анимацию, которая будет учитывать скорость взлета/падения и в зависимости от нее переключать соответствующий кадр анимации.
Загрузим наш проект и сцену. В папке Assets — Sprites у нас остался последний неиспользованный спрайт Jump. Проделаем с ним уже знакомую операцию по нарезке спрайта на коллекцию изображений. Затем в окне Hierarchy выберем Character и перейдем в окно Animation. Для прыжка нам понадобиться несколько файлов анимаций, а точнее — семь. Это равно числу кадров в спрайте Jump. Давайте создадим эти анимации, называя их Jump1, Jump2 и т.д.
Теперь добавим в каждую анимацию по одному изображению из спрайта Jump, по порядку: спрайт Jump_0 в анимацию Jump1, спрайт Jump_1 в анимацию Jump2…
В окне Animator (не Animation!) у нас автоматически создались элементы для новых анимаций, но они нам теперь не понадобятся. Выделим их и удалим клавишей Delete (анимации также удалятся из соответствующего списка в окне Animation, но чуть позже мы их вернем). Создадим в Animator‘е два новых параметра: Ground с типом Bool и vSpeed с типом Float. Первый будет обозначать, находится ли персонаж на земле или в прыжке, а второй будет хранить текущее значение скорости персонажа по оси Y, то есть скорость взлета/падения. В зависимости от нее мы будем применять соответствующую анимацию из наших семи анимаций прыжка.
Теперь кликнем правой кнопкой по любому свободному месту в окне Animator и выберем Create State — From New Blend Tree. В окне Inspector переименуем созданный элемент как Jump.
Теперь кликнем дважды по Jump. Откроется элемент Blend Tree. В него мы добавим наши семь анимаций прыжка, а переключение между ними будут происходить в зависимости от значения параметра vSpeed. По умолчанию в Blend Tree сейчас установлен параметр Speed — поменяем его на vSpeed в окне Inspector.
В этом же окне нажмем на плюсик и выберем Add Motion Field. Это нужно проделать семь раз. Создадутся семь полей для наших семи анимаций. Снимем флаг Automate Thresholds, чтобы можно было вручную устанавливать значения параметра vSpeed, при достижении которых будет производиться смена анимации в Blend Tree. Перетащим в каждое поле по анимации и зададим значения vSpeed. Вот что должно получиться (кстати, после этих действий удаленные из списка в окне Animation анимации Jump1—Jump6 вновь появятся):
С анимацией пока закончим. Теперь нам надо научится определять, когда персонаж находится на земле, а когда — в воздухе, то есть в прыжке. Перейдем в окно Scene. Создадим пустой игровой объект, назовем его GroundCheck. Выделяем его в окне Hierarchy и перетаскиваем мышью на Character (все в том же окне Hierarchy!). Теперь объект GroundCheck будет дочерним по отношению к Character и будет перемещаться вместе с ним, а объект Character приобретет соответствующую стрелку, скрывающую дочерние объекты. Кликнем по стрелке и вновь выберем объект GroundCheck. Назначим ему иконку, чтобы видеть объект на сцене. На скриншоте я указал, как это сделать:
В окне Scene переместим GroundCheck в ноги персонажа. Тем самым, мы сделали объект, который будет использован для определения нахождения персонажа на земле.
Теперь нам надо определить, а что же является землей? Очевидно, это наша платформа, но игра об этом пока не знает. Кстати, давайте создадим копию платформы для тестирования прыжка (лучшим способ будет создание префаба на основе платформы, но сейчас давайте просто выделим Platform и нажмем Ctrl+D). Разместим вторую платформу правее и выше первой.
Выделим любую из платформ и обратим внимание на верхнюю часть окна Inspector. Там есть поле Layer со значение Default. Оно обозначает принадлежность объекта к тому или иному слою. Кликнем на Default, выберем Add Layer, зададим в поле User Layer 8 имя Ground. Снова выделим платформу, и вместо слоя Default установим слой Ground. Для второй платформы тоже установим слой Ground.
Таким образом мы определили, что наши платформы будут землей. Объект GroundCheck будет проверяться на предмет пересечения с объектами слоя Ground, т.е. с нашими платформами. Если будет обнаружено пересечение — персонаж находится на земле. Делаться это будет в скрипте CharacterControlleScript, созданном в предыдущей части. Давайте откроем его на редактирование.
В начало скрипта добавим новые переменные в добавок к уже существующим:
А в начало метода FixedUpdate следующие строки:
Теперь добавим в скрипт метод Update, в котором будем обрабатывать нажатие клавиши прыжка. Мы будем делать это в методе Update для большей точности управления — этот метод вызывается каждый фрейм игры, в отличии от FixedUpdate, который вызывается через одинаковое определенное время и обычно, при хорошем FPS, вызовы происходят реже вызовов Update.
Итого, полностью скрипт будет выглядеть так:
Сохраняем скрипт, возвращаемся в Unity. В Hierarchy выделяем Character. Перетаскиваем объект GroundCheck в поле Ground Check скрипта CharacterControllerScript, а в поле What Is Ground устанавливаем Ground.
Капитан Коготь умеет бегать и прыгать. При прыжке, в зависимости от состояния (взлет/падение) и от скорости применяется соответствующая анимация. На видео хорошо заметно, что при прыжке в окне Animator происходят переключения между анимациями в элементе Blend Tree. При этом, если персонаж просто падает с платформы (т.е. в прыжке нету фазы взлета, пробел не нажимался) — работают только те анимации, для переключения которых заданы отрицательные значения скорости, что делает поведение персонажа более реалистичным. Конечно, для лучшего эффекта необходимо больше анимаций и более тонкая настройка значений скорости.
Что ж, на этом все. Основа для 2D персонажа создана. Какие к ней прикрутить дополнительные возможности — зависит уже от конкретной игры. Спасибо за внимание!
Unity 2d jumping script
Does anyone have a good jumping script for 2d games in unity? The code I have works but still is far from jumping, it looks like it is flying.
3 Answers 3
The answer above is now obsolete with Unity 5 or newer. Use this instead!
I also want to add that this leaves the jump height super private and only editable in the script, so this is what I did.
This makes it to where you can edit the jump height in Unity itself without having to go back to the script.
Use Addforce() method of a rigidbody compenent, make sure rigidbody is attached to the object and gravity is enabled, something like this
See which combination and what values matches your requirement and use accordingly. Hope it helps
Not the answer you’re looking for? Browse other questions tagged c# unity3d physics or ask your own question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
site design / logo © 2021 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2021.11.10.40714
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Прыжки игрока на Unity в 2D
Я вернулся к вам спустя долгое отсутствие, зато статья будет целиковой, поэтому никаких продолжений по этой новой теме не будет. Как и движение, прыжок одно из основных игровых механик, что может делать игрок. А так как это вид сбоку, то его нельзя пропускать. Именно поэтому я сегодня расскажу, что нужно знать для того, чтобы ваш персонаж начал прыгать, много прыгать. Также будет немало мелких дополнений по самому Unity, а не по коду. Хоть какое разнообразие появиться, да? Что-ж, давайте не будем затягивать вступление и наконец начнем!
Перво-наперво мы сделаем так, чтобы наш герой начал перемещаться по оси y. Чтобы это сделать мы будет использовать знакомые нам функции Rigidbody2D.velocity и Input.GetKey().
Как видно, ничего нового я не добавлял, а уже появились зачатки прыжка, но нам также нужны некоторые исправления в rigidbody2D нашего персонажа в Unity. Нам нужен тип «динамика», значение гравитации на ту, которая нужна и выслеживание колизии «непрерывный», чтобы он останавливался сразу, после падения на твердую поверхность. Вот мои настройки:
Для начала это будет вполне достаточно, поэтому теперь посмотрим, что у нас получилось.
Подойдем к середине нашего пути, ко второму этапу. К тому, где наш персонаж уже будет прыгать, только находясь на земле. А также мы исправим небольшую проблему со стенами. Это проблема связана с тем, что персонаж застревает в стенах. Об этом мы сейчас и поговорим.
«Второй день написания — я заблудился»
Для начала я расскажу о понятиях, чтобы вы вошли сразу в суть кода. Вот, собственно, и они: [SerializeField], Transform и LayerMask.
[SerializeField] — заставить сериализовать частное поле. Когда Unity серилизует ваши скрипты, он сериализует только общедоступные поля. Если вы также хотите, чтобы Unity сериализовала ваши частные поля, вы можете добавить к этим полям атрибут SerializeField.
Transform — объект, с которым мы можем взаимодейтсвовать, как положение поворот, масштаб объекта.
LayerMask — слой маски. Для GameObject можно использовать до 32 масок поддерживаемого редактора.
Для нашей дальнейшей игры нам понадобится своя маска, я ее назвал Ground и поместил в поверхности. Так это выглядит в программе:
А также немного о том, зачем же нам Transform. Мы создаем в Unity пустой объект, которому будем давать некоторые свойства. Мы его помещаем снизу и прикрепляем его к нашему игроку.
А самая первая функция нам позволит изменять значения уже в самом Unity, что упростит эксперементы, например, со скростью бега или прыжка.
Теперь мы поработаем с самой главной функцией, которая заствит все это работать вместе. В этом нам поможет Physics2D.OverlapBox().
Physics2D.OverlapBox() — коллайдер, перекрывающий поле. Проверяет, попадает ли коллайдер в область прямоугольника. В ней есть такие параметры, как point — центр коробки; size — размер коробки; angle — угол коробки; layerMask — фильтр для проверки объектов только на определенных слоях; minDepth — только включает объекты с координатой z больше, чем это значение; maxDepth — только включает объекты с координатой z меньше этого значения.
Все, что мы делаем на второй этапе — это работаем с нашей функцией. Даем ей начальную точку — наш персонаж. Размеры нашего коллайдера (не обращайте внимания на название переменной, я сначала пробовал работать с OverlapCircle, но понял, что мне эта функция не подойдет). Угол мы не меняем. И даем знать, что наш пустой объект реагировал только на маску Ground. И в итоге мы получаем, что мы сможем прыгать только при прикосновении с землей.
Ах да, чуть не забыл. Вот, что будет, если на этом остановится. Можно даже сказать в буквальном смысле.
Я покажу, что нужно сделать, чтобы этого избежать, здесь сработала физика трения, которая нам не дает спуститься вниз, поэтому нужно это трение уменьшить или совсем отключить. Если просто понизить, то он будет медленно спускаться, что здорово, но подобрать такой баланс очень проблематично, так что мы постораемся написать это ручками. А для всего этого, нам понадобится Physics Material 2D. Так выглядит это у меня:
И перемещаем это все к нашему игроку в материал.
Теперь все работает, как надо. 2 этап закончен. Что же дальше? На этом я не закончу, потому что герои платформеров и не на такое способны. Мы добавим прыжки от стен и дополнительные прыжки. Приступим же к последнему, к 3 этапу.
Быстро пройдем к дополнительным прыжкам, так как ничего сложного в этом нет. Мы начинаем на земле с каким-то количеством прыжков при себе и восстанавливаем их только на земле. Тратим же мы прыжки в воздухе, пока все прыжки не закончатся. Еще могу добавить, что я прыжки делал в Update(), так как второй не успевает за нажатием space, может быть, в будущем найду способ настраивать время обновления его.
А теперь перейдем к довольно сложному делу, свое созданное скольжение по стенкам. Здесь я не стал делать одно и тоже и уже не применял Physics2D.OverlapBox. Решил пойти более изощренным способом, но также эффективным. Здесь я уже застрял на долгие часы раздумий. Для начала немного информации о новых функциях. Их будет две: Physics2D.Raycast и Mathf.Clamp.
Physics2D.Raycast — бросает луч против коллайдеров в сцене. Любой объект, контактирующий с лучом, можно обнаружить и сообщить о нем. Параметры функции: origin — точка в пространстве, откуда исходит луч; direction — вектор, представляющий направление луча; distance — максимальное расстояние, на которое нужно бросить луч; layerMask — фильтр для обнаружения коллайдеров только на определенных слоях; minDepth — только включает объекты с координатой z больше, чем это значение; maxDepth — только включает объекты с координатой z меньше этого значения.
Mathf.Clamp — результат с плавающей точкой между минимальным и максимальным значениями.
«Видимо, придется в следующий раз придумывать, как вместить код в статью по другому»
Так, а теперь мы будем медленно спускаться по коду и разбираться, что я там нахимичил. Новые переменные у нас такие: время зацепа (действует только тогда, когда кнопка в сторону опущена), скорость скольжения, и расстояние луча. Для удобства, я разделил «подглавы» для кода.
И первую мы уже видели. А на второй мы уже остановимся. Мы сделаем так, чтобы луч был на той стороне, на которую мы смотрим в данный момент. После чего мы уже строим луч и дебаг, который на будет его рисовать. Хочется увидеть, что луч на месте и работает. Так что после того, как вы его использовали для проверки, его можно будет спокойно убрать. Третью и четвертую мы также видели. Осталось теперь только сделать так, чтобы игрок скользил по стене, когда луч касался стенки, не касался земли и двигался в ее сторону. Отмечаем, что игрок скользит и мереем время. Когда время запуска игры превысит установленное, то игрок больше не скользит и начнет падать. И в конце, чтобы игрок все-таки скользил, а не стоял, мы должны заставить его двигаться вниз. Для того, чтобы мы действительно скользили, а не двигались с полной скоростью вниз, мы используем Mathf.Clamp. И вот так это у нас выглядит в Unity.
Теперь мы можем проверить, как же это работает на практике.
Как мы видим, все работает. Конечно, в этом способе есть небольшие недочеты, но для первого раза, так отлично получилось. Со временем все будет улучшаться, не забывая об основном, о прыжках. Пора бы нам уже заканчивать. Эта тема исчерпала себя, поэтому ждите чего-то нового от непредсказуемого меня. Пара ссылок, как всегда внизу, а я отхожу немножко на покой. Спасибо, что дочитали до конца. И я с вами не прощаюсь, а вы оставайтесь со мной!
Система управления в 2D платформерах
Конечно, когда мы говорим о жанре платформер, тем более в 2D играх, то система управления здесь реализуется на порядок проще, чем в более крупных 3D играх, к тому же, Unity предлагает множество уже готовых решений и все, что вам требуется – только правильно их использовать.
Если на ПК управление в большей части реализуется за счет мыши и клавиатуры, то с сенсорными экранами все немножко сложнее. На экране не расположишь все кнопки, поэтому приходится прибегать к дополнительным системам отлавливания действий игрока и управления персонажем.
В этой статье попробуем рассмотреть один из примеров такой системы управления.
И так, начнем с небольшой программной части, а именно – с событийной части взаимодействия игрока и персонажа через команды.
Система команд
Создаем скрипт с перечислениями ActionType в котором будут находится команды.
Добавим в этот скрипт метод, через который будут поступать команды персонажу.
Дальше создадим персонажа на сцене.
Дальше кидаем скрипт Character на персонажа на сцене и возвращаемся к канвасу, где продолжим настраивать наши кнопки.
Так как мы не используем стандартные кнопки Button по причине того, что они могут отловить только событие нажатия, мы будем настраивать изображения через компонент EventTrigger, который позволяет отлавливать кучу других полезных действий.
Поэтому нажимаем кнопку AddNewEventType в компоненте EventTrigger и ищем эти события, после чего добавляем их.
Потому что персонаж будет передвигаться только пока вы “ зажали ” кнопку передвижения, после ее отпускания необходимо будет вызвать команду остановки, чтобы персонаж остановился.
Добавляем его в список действий.
После этого можно запустить и протестировать вызов команд в игре, нажатием на разные кнопки.
Обработка команд
Теперь, когда мы закончили с визуальной частью управления, переходим к самой обработке поступивших команд.
Возвращаемся в скрипт Character, где для начала добавим несколько переменных: переменную направления directionRight, и переключатели onMoving и onMakeJump для движения и совершения прыжка.
Теперь переходим к методу OnDoAction, где разберем действия персонажа на поступившие команды.
Перед тем как выполнить эту команду, необходимо дополнительно проверить, стоит ли на “ земле ” наш персонаж. Для этого добавим простой коллайдер BoxCollider2D персонажу и настроим его.
В методе CheckGround будем проверять, находится ли персонаж на поверхности. Для этого проверим коллайдер персонажа на соприкосновение с землей.
Для этого используем позицию point и размер size коллайдера персонажа.
Далее методом Physics2D.OverlapBox проверим наличие поверхности под “ ногами ”.
Вот так наш персонаж будет обрабатывать поступающие команды от игрока, теперь можно переходить ко второй части статьи – к методам передвижения персонажа.
Физический движок Unity – это самостоятельная система обработки физических объектов и чем больше этих объектов будет на сцене? тем больше ресурсов уйдет на их обработку, так что для лучшей работы игры следует максимально минимизировать их кол-во.
Для персонажа выделим его главные требования: он должен четко взаимодействовать с окружением, которое состоит из коллайдеров, в первую очередь это пол и стены.
Самое главное, с чего нужно начать, так это выбрать методы обработки перемещения персонажа.
Методы обработки
Для обработки движения двух разных типов объектов ( Transform и Rigidbody ) существует два разных метода Update и FixedUpdate – каждый из них используется для своих целей.
Общее у этих методов то, что они оба вызываются через определенное время, Update – каждый кадр, а FixedUpdate – каждый промежуток времени.
В первом случае метод Update вызывается столько раз, сколько позволяет частота кадров в игре, то есть если у вас частота к примеру 60 кадров в 1 секунду, значит, что и метод Update сработает 60 раз за 1 секунду.
Многие начинающие разработчики часто работают с Rigidbody в разных методах: ускоряют, замедляют их, придают им импульсы, бросают и так далее. Но с физическими телами рекомендуется работать именно в методе FixedUpdat. Даже если вы 10 раз измените позицию тела Rigidbody в том же методе Update или в любом другом методе, то все равно эти изменения вступят в силу только в момент вызова метода FixedUpdate, какая частота кадров у вас бы ни была.
В отличие от Transform’а у физического тела Rigidbody есть несколько способов перемещения.
Движение с ускорением
Теперь попробуем применить выбранный тип движения для персонажа, для этого вернемся в скрипт персонажа Character, где создадим новый метод FixedUpdate и пару переменных для перемещения: moveSpeed для скорости движения и jumpForce для силы прыжка.
Сначала определим, в какую сторону персонажу нужно совершать ускорение по оси X. Для этого с помощью переменной directionRight проверим направление персонажа, если ее значение true, значит ускорять объект нужно вправо с положительным значением, если же значение false, то будем ускорять объект влево с отрицательным значением.
Здесь ускорение по оси Y оставляем неизменным – персонаж сам будет обрабатывает вертикальное ускорение.
После проделанных действий наш персонаж сможет двигаться по горизонтали учитывая силу притяжения.
Чтобы проверить, добавим на сцену поверхность с коллайдером.
Теперь попробуем запустить игру и убедиться, что движение работает согласно командам.
Перекинем физический материал в поле Material коллайдера поверхности и снова тестируем.
Изменяя коэффициент трения Friction физического материала можно добиться нужно результата движения по поверхности.
Импульс
Теперь займемся прыжком персонажа. Как было сказано выше, для совершения прыжка физическим телом, будем использовать метод AddForce который придаст объекту импульс движения по вертикали.
Теперь снова вернем переменной onMakeJump исходное значение false для следующего прыжка. Наш персонаж может прыгать по поверхностям, попробуйте запустить и проверить результат.
Снова проверим результат.
Заключение
Вот так легко и просто можно создать систему управления персонажем с помощью команды игрока. Теперь вы запросто сможете подключить к готовому персонажу анимации и добавить в игру другие объекты.



























