В данной статье мы рассмотрим несколько самых популярных способов обнаружения земли под ногами персонажа, которые обычно используют перед прыжком. Рассматривать мы будем следующие способы проверки:
- Collider2D.OnCollisionEnter2D
- Collider2D.OnTriggerStay2D
- Physics2D.OverlapCircle
- Physics2D.Raycast
И для начала для нашего персонажа объявим переменную isGround, которая будет использоваться во всех наших способах:
private bool isGround;
Данная переменная будет хранить информацию о том, находится ли наш персонаж на земле, или нет. true - да, false - нет.
Теперь рассмотрим по порядку каждый из способов.
Collider2D.OnCollisionEnter2D
В данном способе мы будем использовать метод OnCollisionEnter2D() – который срабатывает тогда, когда наш объект соприкасается с другим объектом:
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.CompareTag("Ground"))
{
isGround = true;
}
}
Когда наш персонаж соприкасается с другим объектом, происходит проверка на тег данного объекта, с которым соприкаснулся наш персонаж. И если тег данного объекта будет равняться Ground, то в нашу переменную isGround занесётся значение true – что будет означать, что наш персонаж находится на земле. Поэтому, не забудьте создать новый тег Ground, и присвоить его тем объектам, с которых может прыгать наш персонаж.
Когда мы осуществим прыжок, и взаимодействие персонажа с землёй будет разорвано, то нам необходимо указать переменной isGround, что персонаж уже не находится на земле. Для этого используем метод OnCollisionExit2D () – который срабатывает тогда, когда соприкосновение двух объектов разрушается.
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.CompareTag("Ground"))
{
isGround = false;
}
}
Готово! Так же убедитесь, что у объектов имеется компонент Collider2D. Без этого компонента, коллизия работать не будет.
Данный способ прост в использовании, не есть серьёзный недостаток. Чтобы isGround получило значение true, коснуться земли можно с любой стороны, что полностью нарушает логику и весь смысл.
Collider2D.OnTriggerStay2D
Данный способ очень схож на предыдущий, но с одним лишь отличием. Он устраняет тот недостаток, о котором мы говорили в предыдущем примере.
Методы типа Trigger2D срабатывают тогда, когда объект входит в область другого объекта. Например, используя метод OnTriggerStay2D(), мы проверяем, вошёл ли наш персонаж в другой объект, имеющий тег Ground:
private void OnTriggerStay2D(Collider2D col)
{
if (col.CompareTag("Ground"))
{
isGround = true;
}
}
Аналогичный код необходимо прописать и для выхода объекта из другого объекта, используя метод OnTriggerExit2D()
private void OnTriggerExit2D(Collider2D col)
{
if (col.CompareTag("Ground"))
{
isGround = false;
}
}
Как видите, метод аналогичен предыдущему. Но чтобы этот способ работал, необходимо проделать ещё несколько дополнительных действий, а именно:
- Создать новый тег, например, Ground, и присвоить его к земле, то-есть к тем объектам, с которых можно будет осуществлять прыжки.
- Создать новый объект-пустышку, и поместить его внутрь тех объектов, которые представляют собой землю. А сам объект разместить чуть выше объекта-земли для того, чтобы наш персонаж мог в этот объект войти.
- Добавить в объект-пустышку компонент Box Collider 2D, и поставить галочку в поле isTrigger.
В целом, этот способ очень хорош, но есть два небольшим минуса. Во-первых, Вам придётся каждой земле добавлять дополнительный вложенный объект(триггер). А во-вторых, он более ресурсозатратный, чем все остальные способы.
Physics2D.OverlapCircle
Метод Physics2D.OverlapCircle() довольно часто используется по сравнению с другими способами. Суть данного способа заключается в том, что вокруг персонажа создаётся круговая область. И если в эту область попадает объект типа Ground, то мы это записываем в нашу переменную isGround.
Сейчас мы объявим несколько дополнительных переменных, которые нам понадобятся:
private float groundRadius = 0.3f;
public Transform groundCheck;
public LayerMask groundMask;
А теперь добавим код, который будет определять наличие персонажа на земле, и записывать в переменную isGround результат:
void Update()
{
isGround = Physics2D.OverlapCircle(groundCheck.position, groundRadius, groundMask);
}
Метод Physics2D.OverlapCircle() принимает 3 параметра. Все эти 3 параметра были объявлены нами чуть выше, в предыдущем коде:
- groundCheck.position – это координата точки, которая будет являться центром создаваемой окружности. Обычно для неё создаётся новый игровой объект, и помещается под ноги персонажа.
- groundRadius – радиус окружности.
- groundMask – название слоя, с которым будет взаимодействовать ваш персонаж, например, слой Ground.
Не забудьте в окне Inspector присвоить игровой объект персонажа полю Transform, и новый слой Ground для LayerMask.
Данный способ очень распространён, но всё же он не идеален. И при некоторых условиях данный способ будет работать не совсем правильно.
Physics2D.Raycast
Суть данного способа в том, что наш персонаж с помощью метода Physics2D.Raycast выпускает луч себе под ноги, который ищет землю под ногами.
Для начала укажите название слоя нашей земле как Ground. Далее объявим дополнительное поле, которое будет отвечать за длину выпускаемого вниз луча:
public float rayDistance = 0.03f;
Далее выпустим луч от нашего объекта вниз, который будет искать объект на своём пути, имеющий слой Ground.
RaycastHit2D hit = Physics2D.Raycast(rb.position, Vector2.down, rayDistance, LayerMask.GetMask("Ground"));
В зависимости от ситуации, в переменную hit попадёт определённое значение, если луч встретит под собой землю. Если же луч земли под собой не обнаружит, то переменная hit получит значение null.
Сейчас мы определить, есть ли значение в переменной hit, или его нет. После чего в переменную isGround занесём true или false.
if (hit.collider != null)
{
isGrounded = true;
}
else
{
isGrounded = false;
}
Данный способ обнаружения земли так же как и предыдущий вариант имеет недостаток в том, что при определённых условиях, прыжок персонажа будет работать некоректно.
На этом всё. Мы рассмотрели 4 способа обнаружения земли под ногами персонажа.
А какой способ используете Вы? И почему? Напишите об этом в комментариях, думаю эта информация будет очень полезна.