Стояние на земле
Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 11 из 71.
У каждого контакта есть нормаль: направление длиной 1, перпендикулярное поверхности, которой вы коснулись и направленное от неё к вашему объекту. collision.GetContact(0) — это первая точка контакта, а её normal показывает, какой стороны вы коснулись. На ровной поверхности нормаль равна (0, 1, 0); если справа от вас стена — (-1, 0, 0); если вы ударились головой о потолок — (0, -1, 0).
Этот фрагмент кода отличает приземление от бокового столкновения:
void OnCollisionEnter(Collision collision)
{
Vector3 normal = collision.GetContact(0).normal;
if (normal.y > 0.5f)
{
Debug.Log("Landed on " + collision.gameObject.name);
}
else
{
Debug.Log("Bumped the side of " + collision.gameObject.name);
}
}Проверка использует normal.y > 0.5f, а не точное значение 1, чтобы наклонные поверхности тоже считались землёй: на склоне с углом 60 градусов значение y равно 0.5, а по таким крутым склонам никто не ходит. Ещё два сообщения пригодятся для всего, что длится какое-то время: OnCollisionStay выполняется на каждом шаге физики, пока длится контакт, а OnCollisionExit — один раз, когда контакт заканчивается. У события выхода нет точек контакта, поскольку больше ничего не соприкасается, поэтому не вызывайте там GetContact.
Задание
ЛегкоРазрешите игроку прыгать, только когда он стоит на чём-либо.
- Добавьте
private bool grounded;. ВOnCollisionStayзадайте ему значение true, когдаcollision.GetContact(0).normal.y > 0.5f; вOnCollisionExitзадайте значение false. - В
FixedUpdate()выполняйте прыжок, только еслиif (jumpPressed && grounded), а после этогоifустановитеjumpPressed = false;, чтобы нажатие в воздухе пропускалось.
Нажмите «Играть» и попробуйте выполнить двойной прыжок: второе нажатие ничего не делает. Затем нажмите «Проверить».
Попробуйте сами
using UnityEngine;
public class Hopper : MonoBehaviour
{
public float speed = 4f;
public float jump = 6f;
private Rigidbody rb;
private bool jumpPressed;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
jumpPressed = true;
}
}
void FixedUpdate()
{
float h = Input.GetAxisRaw("Horizontal");
rb.linearVelocity = new Vector3(h * speed, rb.linearVelocity.y, 0);
if (jumpPressed)
{
rb.AddForce(Vector3.up * jump, ForceMode.Impulse);
jumpPressed = false;
}
}
}
Все уроки раздела Физика и игровой процесс
1Твёрдое тело
Гравитация и массаТолкаем с помощью AddForceПрыжок с импульсомFixedUpdate для физикиСкоростьКинематические телаПовторение: пусковая площадка4Корутины
InvokeInvokeRepeating, CancelInvokeВаша первая корутинаЦиклы в корутинахОстановка корутинПовторение: обратный отсчёт10Проект: Побег с арены
АренаОхотники2Столкновения
OnCollisionEnterВо что я попал?Разрушение при столкновенииСтояние на землеОтскок и трениеФормы коллайдеровПовторение: разрушаемая стена5Проект: Монетная гонка
Катящийся шарСобираем монетыПотренируйтесь самостоятельно: Песочница Unity