Как сделать прыжок в unity 3d

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

Часть 3: прыжки (и падения)

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

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

Загрузим наш проект и сцену. В папке AssetsSprites у нас остался последний неиспользованный спрайт Jump. Проделаем с ним уже знакомую операцию по нарезке спрайта на коллекцию изображений. Затем в окне Hierarchy выберем Character и перейдем в окно Animation. Для прыжка нам понадобиться несколько файлов анимаций, а точнее — семь. Это равно числу кадров в спрайте Jump. Давайте создадим эти анимации, называя их Jump1, Jump2 и т.д.


Теперь добавим в каждую анимацию по одному изображению из спрайта Jump, по порядку: спрайт Jump_0 в анимацию Jump1, спрайт Jump_1 в анимацию Jump2


В окне Animator (не Animation!) у нас автоматически создались элементы для новых анимаций, но они нам теперь не понадобятся. Выделим их и удалим клавишей Delete. Создадим в Animator'е два новых параметра: Ground с типом Bool и vSpeed с типом Float. Первый будет обозначать, находится ли персонаж на земле или в прыжке, а второй будет хранить текущее значение скорости персонажа по оси Y, то есть скорость взлета/падения. В зависимости от нее мы будем применять соответствующую анимацию из наших семи анимаций прыжка.


Теперь кликнем правой кнопкой по любому свободному месту в окне Animator и выберем Create StateFrom New Blend Tree. В окне Inspector переименуем созданный элемент как Jump.


Создадим два перехода между анимациями: Any State -> Jump и Jump -> Idle. То есть, из любого состояния мы можем перейти в состояние прыжка, а из состояния прыжка перейти в состояние покоя. Напоминаю, как делаются переходы: клик правой кнопкой по первой анимации, Make Transition, клик левой кнопкой по второй анимации. Для первого перехода зададим условие Groundfalse, для второго Groundtrue.


Теперь кликнем дважды по Jump. Откроется элемент Blend Tree. В него мы добавим наши семь анимаций прыжка, а переключение между ними будут происходить в зависимости от значения параметра vSpeed. По умолчанию в Blend Tree сейчас установлен параметр Speed — поменяем его на vSpeed в окне Inspector.


В этом же окне нажмем на плюсик и выберем Add Motion Field. Это нужно проделать семь раз. Создадутся семь полей для наших семи анимаций. Снимем флаг Automate Thresholds, чтобы можно было вручную устанавливать значения параметра vSpeed, при достижении которых будет производиться смена анимации в Blend Tree. Перетащим в каждое поле по анимации и зададим значения vSpeed. Вот что должно получиться:


С анимацией пока закончим. Теперь нам надо научится определять, когда персонаж находится на земле, а когда — в воздухе, то есть в прыжке. Перейдем в окно 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, созданном в предыдущей части. Давайте откроем его на редактирование.

//находится ли персонаж на земле или в прыжке?
private bool isGrounded = false;
//ссылка на компонент Transform объекта
//для определения соприкосновения с землей
public Transform groundCheck;
//радиус определения соприкосновения с землей
private float groundRadius = 0.2f;
//ссылка на слой, представляющий землю
public LayerMask whatIsGround;

А в начало метода FixedUpdate следующие строки:

//определяем, на земле ли персонаж
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
//устанавливаем соответствующую переменную в аниматоре
anim.SetBool ("Ground", isGrounded);
//устанавливаем в аниматоре значение скорости взлета/падения
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
//если персонаж в прыжке - выход из метода, чтобы не выполнялись действия, связанные с бегом
if (!isGrounded)
return;

Теперь добавим в скрипт метод Update, в котором будем обрабатывать нажатие клавиши прыжка. Мы будем делать это в методе Update для большей точности управления — этот метод вызывается каждый фрейм игры, в отличии от FixedUpdate, который вызывается через одинаковое определенное время и обычно, при хорошем FPS, вызовы происходят реже вызовов Update.

private void Update()
//если персонаж на земле и нажат пробел.
if (isGrounded && Input.GetKeyDown (KeyCode.Space))
//устанавливаем в аниматоре переменную в false
anim.SetBool("Ground", false);
//прикладываем силу вверх, чтобы персонаж подпрыгнул
rigidbody2D.AddForce(new Vector2(0, 600));
>
>

Итого, полностью скрипт будет выглядеть так:

CharacterControllerScriptusing UnityEngine;
using System.Collections;

public class CharacterControllerScript : MonoBehaviour
//переменная для установки макс. скорости персонажа
public float maxSpeed = 10f;
//переменная для определения направления персонажа вправо/влево
private bool isFacingRight = true;
//ссылка на компонент анимаций
private Animator anim;
//находится ли персонаж на земле или в прыжке?
private bool isGrounded = false;
//ссылка на компонент Transform объекта
//для определения соприкосновения с землей
public Transform groundCheck;
//радиус определения соприкосновения с землей
private float groundRadius = 0.2f;
//ссылка на слой, представляющий землю
public LayerMask whatIsGround;

///
/// Начальная инициализация
///
private void Start()
anim = GetComponent();
>

///
/// Выполняем действия в методе FixedUpdate, т. к. в компоненте Animator персонажа
/// выставлено значение Animate Physics = true и анимация синхронизируется с расчетами физики
///
private void FixedUpdate()
//определяем, на земле ли персонаж
isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
//устанавливаем соответствующую переменную в аниматоре
anim.SetBool ("Ground", isGrounded);
//устанавливаем в аниматоре значение скорости взлета/падения
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
//если персонаж в прыжке - выход из метода, чтобы не выполнялись действия, связанные с бегом
if (!isGrounded)
return;
//используем Input.GetAxis для оси Х. метод возвращает значение оси в пределах от -1 до 1.
//при стандартных настройках проекта
//-1 возвращается при нажатии на клавиатуре стрелки влево (или клавиши А),
//1 возвращается при нажатии на клавиатуре стрелки вправо (или клавиши D)
float move = Input.GetAxis("Horizontal");

//в компоненте анимаций изменяем значение параметра Speed на значение оси Х.
//приэтом нам нужен модуль значения
anim.SetFloat("Speed", Mathf.Abs(move));

//обращаемся к компоненту персонажа RigidBody2D. задаем ему скорость по оси Х,
//равную значению оси Х умноженное на значение макс. скорости
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);

//если нажали клавишу для перемещения вправо, а персонаж направлен влево
if(move > 0 && !isFacingRight)
//отражаем персонажа вправо
Flip();
//обратная ситуация. отражаем персонажа влево
else if (move
/// Метод для смены направления движения персонажа и его зеркального отражения
///
private void Flip()
//меняем направление движения персонажа
isFacingRight = !isFacingRight;
//получаем размеры персонажа
Vector3 theScale = transform.localScale;
//зеркально отражаем персонажа по оси Х
theScale.x *= -1;
//задаем новый размер персонажа, равный старому, но зеркально отраженный
transform.localScale = theScale;
>
>

Сохраняем скрипт, возвращаемся в Unity. В Hierarchy выделяем Character. Перетаскиваем объект GroundCheck в поле Ground Check скрипта CharacterControllerScript, а в поле What Is Ground устанавливаем Ground.


Итак, в нашем скрипте, в методе FixedUpdate проверяется пересечение объекта GroundCheck с объектами, принадлежащими слою Ground. Это достигается при помощи метода Physics2D.OverlapCircle. В аргументах этого метода также задан радиус определения пересечения. Затем, в переменную аниматора Ground устанавливается результат определения нахождения на земле, а в переменную vSpeed — текущая скорость персонажа по оси Y. В зависимости от этой скорости применяется та или иная анимация прыжка из семи анимаций в Blend Tree. Сам прыжок задается в методе Update при нажатии на пробел, путем придания вертикальной силы компоненту Rigidbody2D.

Прежде чем запускать игру давайте немного изменим значение гравитации, а то скорость прыжков получится медленной, как на Луне. Заходим в меню EditProject SettingsPhysics 2D. В окне Inspector устанавливаем значение Gravity Y = -30. Запускаем игру! Если все сделано правильно, увидим примерно следующее:

Капитан Коготь умеет бегать и прыгать. При прыжке, в зависимости от состояния (взлет/падение) и от скорости применяется соответствующая анимация. На видео хорошо заметно, что при прыжке в окне Animator происходят переключения между анимациями в элементе Blend Tree. При этом, если персонаж просто падает с платформы (т.е. в прыжке нету фазы взлета, пробел не нажимался) — работают только те анимации, для переключения которых заданы отрицательные значения скорости, что делает поведение персонажа более реалистичным. Конечно, для лучшего эффекта необходимо больше анимаций и более тонкая настройка значений скорости.

Что ж, на этом все. Основа для 2D персонажа создана. Какие к ней прикрутить дополнительные возможности — зависит уже от конкретной игры. Спасибо за внимание!

Мы покажем, как запрограммировать движение персонажа в 2D- и 3D-проектах на Unity. Урок будет полезен детям и подросткам, которые начинают изучать Unity.

Начнем урок по Unity с разделения игровой сцены на два компонента, где первый — это площадка, по которой персонаж будет перемещаться. Иначе говоря, это Plane. Второй компонент — объект самого героя, Sphere.

Далее переходим к оживлению объектов. Управление персонажем на Юнити должно быть физически правильным. Обеспечить это позволяет компонент RigidBody. В инспекторе нажимаем Add Component, затем Physics и RigidBody.

Создаем пустой скрипт и прописываем переменные, которые будут отвечать за скорость движения, быстроту поворота, передвижение по вертикали и горизонтали. В нашем случае переменные в Си Шарп будут названы MovementSpeed, TurningSpeed, vertical и horizontal соответственно.

В функции Update прописываем поворот персонажа по оси Y и движение по оси Z.

Остается только сохранить и скомпилировать созданную программу.

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

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

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


Цикл статей

​Туториалы можно скачать бесплатно с Гитхаба. Каждый туториал будет отдельной папкой в проекте. Конкретно этот туториал будет лежать в директории Assets/Tutorials/02 — Platformer.

Оглавление

Подготовка

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


В инспекторе добавляем к объекту компонент Flow Machine.


Нажимаем Edit Graph и приступает к настройке графа.

Движение персонажа

Мы хотим, чтобы персонаж двигался влево и вправо в зависимости от горизонтальной оси ввода, для которой предварительно настроены сочетания клавиш A и D на клавиатуре или левый джойстик на контроллере. Когда вы идёте влево, возвращается -1 , а когда вправо, то +1 . Скорость движения зададим в переменной.

Для начала можно зайти в настройки и задать необходимое управление в Edit > Project Settings > Input Manager, если не нравятся дефолтные настройки.


Теперь добавим переменную, откуда будем читать скорость. В инспектора объекта игрока добавим переменную в компоненте Veriables. Подробнее можно почитать в документации.

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

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


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

  1. От выхода узла GetAxis тащим указатель и создаём узел Multiply.
  2. От второго входа нового узла тянем указатель и создаём узел для чтения переменной Variables > Object > Get Object Variable.
  3. Выбираем там Speed.
  4. Выход узла Multiply соединяем с новым узлом Variables > Graph -> Set Graph Variable.
  5. Дадим новой переменной имя Movement.
  6. Соединяем управляющий вход с Update.

Каждый кадр (событие Update) мы получаем значение инпута по оси X в диапозоне [-1;1], домножаем на скорость и сохраняем в переменную Movement.

Теперь нужно задать компоненту Rigidbody 2D персонажа скорость. Скорость состоит из двух составляющих — по осям X и Y, которые пакуются в Vector2 .

  1. Добавляем узел Get Variable для получения Movement из предыдущего шага.
  2. Это передаёт на вход X координате новой ноде Vector2.
  3. А в Y передаём считанную Y координату из текущей скорости (Codebase > Unity Engine > Rigidbody 2D -> Get Velocity).
  4. Полученный вектор передаём на вход узлу для установки нового значения скорости (Codebase > Unity Engine > Rigidbody 2D -> Set Velocity).

Остаётся теперь связать выход узла по установке Movement со входом узла, устанавливающего скорость.

Ну и заодно сгруппируем узлы. Это делается выделением с зажатой клавишей Ctrl .

Если запустить редактор, можно увидеть, как персонаж двигает при нажатии на клавиши. Обратите внимание на граф и то, как меняется значение скорости на нём в режиме реального времени.

  1. Если двигаемся вправо (значение Movement больше 0), значение Scale должно быть положительным.
  2. Если движемся влево (значение Movement меньше 0), значение Scale должно быть отрицательным.
  3. Если стоим на месте (значение Movement равно 0), то ничего не делаем.

Значение Y и Z оставляем как есть.


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

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

Анимация

Возьмём готовые спрайты и анимации из примера проекта Penny Pixel.

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

Ну и флажок grounded пока в true выставим, чтобы не запускалась анимация полёта.


На графе, как я уже сказал, нам нужно всего лишь передать значение скорости аниматору и записать в переменную velocityX.


Остаётся только соединить с остальным графом и запустить.

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

Придание силы объекту для прыжка

  1. Добавим глобальную переменную для силы прыжка и назовём JumpPower.
  2. Events > Input, а там On Button Input.
  3. Вместе со считанной силой прыжка передаём в Codebase > Unity Engine > Rigidbody 2D > Add Force (Force, Mode).

Если запустить, то по нажатию на Space персонаж будет прыгать. Но есть одна проблема…

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

Создадим новый слой и назначим его платформам.


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

Переиспользование логики

Так как эта проверку нужна в двух местах, то выделим всю логику в отдельный юнит Assets > Create > Bolt > Flow Macro.

Для каста использовать будем CircleCast . Хотя это не так принципиально.

  1. Получаем позицию текущую.
  2. Делаем рейкаст по слою Platform, направляя вниз с радиусом 2 и дальностью 2.
  3. Результат получаем в отдельную ноду.
  4. Делаем проверку на то, было ли столкновение.
  5. Результат проверки столкновения луча с платформой пишем в bool переменную IsGrounded на выход.

Теперь в графе персонажа нужно немного изменить узлы, обрабатывающие прыжок.

  1. Перетаскиваем на граф персонажа граф GroundCheck.
  2. Добавляем ветвление.
  3. Соединяем с узлом, задающим силу.

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

Точно также добавим проверку к анимации.


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

Хотелось бы как-то визуализировать дебажную информацию для отладки.

Отладка и OnDrawGizmos

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

В нашем случае просто будет рисовать линию. Увеличим дальность луча до 50 и добавим соответствующие узлы для отрисовки линии.

  1. Вытаскиваем информацию о текущем положении.
  2. Создаём Vecto3 на основе X и Z координаты. Эта позиция будет конечной при отрисовки линии.
  3. Рейкаст мы делаем вниз, поэтому в Y координату вписываем Y координату текущего положения персонажа с за вычетом дальности луча.
  4. Добавляем ивент, который каждый кадр рисует информацию.
  5. На вход узла по отрисовке в начальную координату передаём текущее положение персонажа, а конечной точкой будет новое вычисленное значение позиции.

Ещё нужно в Scene View включить отображение Gizmos.


Теперь запустим и посмотрим.

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

В следующей статье поработаем с окнами и сделаем экран смерти персонажа с перезапуском сцены.

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

есть ли у кого-нибудь хороший сценарий прыжков для 2d-игр в unity? Код, который у меня есть, работает, но все еще далек от прыжка, похоже, что он летит.

обычно для прыжков люди используют Rigidbody2D.AddForce С Forcemode.Impulse . Может показаться, что ваш объект толкнут один раз по оси Y, и он автоматически упадет из-за силы тяжести.

ответ выше теперь устарел с Unity 5 или новее. Используйте это вместо этого!

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

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

примечание-Я хотел прокомментировать ответ выше, но я не могу, потому что я новичок здесь. :)

используйте Addforce () метод Rigidbody compenent, убедитесь, что rigidbody прикреплен к объекту и гравитация включена, что-то вроде этого!--2-->

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

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

Обновление: они могут прыгать сейчас, но все равно не могут дважды прыгнуть.

Это весь мой сценарий движения:

Я не знаю, связано ли это с моим скриптом прыжка или скриптом игрока:

3 ответа

Насколько я вижу, ты никогда не сбрасываешь

Надеюсь, что это работает ;).

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

Вместо этого используйте:

GetKeyDown возвращает true при нажатии кнопки. GetKey возвращает true, пока кнопка нажата.

Надеюсь, это работает сейчас;)

Я бы реализовал это со счетчиком, вы можете установить желаемое количество прыжков.

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