Menu
CoddyTech

Проверка земли с помощью луча

Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 37 из 71.

Прыжок должен начинаться только с земли. В примере «Стояние на земле» это определялось по нормалям контакта, которые обновлялись сообщениями о столкновениях. Луч сразу отвечает на вопрос «стою ли я на чём-нибудь?» в любой момент: направь его строго вниз от центра, сделав немного длиннее расстояния от центра до нижней точки. Этот игрок — капсула высотой 2 единицы, поэтому нижняя точка находится на 1 единицу ниже центра, а длина луча равна 1.1:

public float jumpForce = 5f;
private Rigidbody rb;

void Start()
{
    rb = GetComponent<Rigidbody>();
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
    {
        rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
    }
}

bool IsGrounded()
{
    return Physics.Raycast(transform.position, Vector3.down, 1.1f);
}

Дополнительные 0.1 — это запас. Тело, покоящееся на полу, может оказаться чуть выше него или немного погрузиться в него, поэтому луч длиной ровно 1 в некоторые кадры не попадёт в пол. Слишком большая длина приводит к обратной проблеме: при длине 3 игрок сможет снова прыгнуть, находясь в воздухе на высоте 2 единиц, а при нулевой длине луч всегда будет находить пол, поэтому каждое нажатие будет приводить к прыжку.

Луч начинается внутри собственного коллайдера игрока, который лучи игнорируют, поэтому он никогда не сообщает об игроке. Клавиша считывается в Update(), потому что GetKeyDown имеет значение true только в течение одного кадра, а одиночный импульс можно добавить прямо там, как в примере «Прыжок с импульсом».

challenge icon

Задание

Средне

Пусть лягушка прыгает только с земли.

  1. Добавь bool IsGrounded(), которая возвращает Physics.Raycast(transform.position, Vector3.down, 0.85f): радиус лягушки, 0.75, плюс 0.1.
  2. В Update() добавь && IsGrounded() к if для клавиши пробела.

Нажми «Играть» и дважды нажми пробел: лягушка прыгнет один раз. Затем нажми «Проверить».

Попробуйте сами

using UnityEngine;

public class Hopper : MonoBehaviour
{
    public float jumpForce = 6f;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }
}

Все уроки раздела Физика и игровой процесс

Потренируйтесь самостоятельно: Песочница Unity