Стояние на земле
Часть раздела Физика и игровой процесс путешествия по Unity на Coddy. Урок 11 из 63.
У каждого контакта есть нормаль: направление длиной 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.
Задание
ЛегкоИгрок может ходить и прыгать, но клавиша Space работает и в воздухе, поэтому он может взбираться в небо прыжок за прыжком и прыгать со стены в сторону. (У его коллайдера материал без трения, поэтому он скользит вниз по стенам, а не прилипает к ним.) Сделай так, чтобы он прыгал, только когда стоит на чём-нибудь.
- Используй
bool grounded: значение true, пока игрок касается чего-либо, нормаль контакта с чем направлена вверх (y больше 0.5), и false, как только он перестаёт касаться. - Прыгай, только когда была нажата клавиша Space и значение
groundedравно true. Нажатие в воздухе игнорируется, а не сохраняется до приземления.
Нажми Играть, попробуй прыгнуть дважды и забраться на стену, затем нажми Проверить.
Попробуйте сами
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 для физикиСкоростьКинематические телаПовторение: пусковая площадка2Столкновения
OnCollisionEnterВо что я попал?Разрушение при столкновенииСтояние на землеОтскок и трениеФормы коллайдеровПовторение: разрушаемая стена5Проект: Погоня за монетами
Катящийся мячМонеты для сбора