Menu
CoddyTech

Прицеливание платформой

Урок 4 из 16 курса Игра в Unity: арканоид на Coddy.

При идеальном отскоке игрок не может целиться: мяч отскакивает от платформы под тем же углом, под которым прилетел. В играх типа Brick Breaker направление мяча определяет сама платформа. Удар ближе к левому краю отправляет мяч вверх и влево, удар по центру — прямо вверх, а чем дальше от центра, тем шире угол.

Преобразуй точку удара в число от -1 у левого края до 1 у правого: смещение мяча по x относительно центра платформы, делённое на половину ширины платформы. Допустим, ширина платформы — 4 единицы, а её центр находится в точке x = 2, и мяч попадает в точку x = 3. Смещение равно 1, половина ширины равна 2, поэтому число равно 0.5, а новое направление — 0.5 по горизонтали и 1 вверх, (0.5, 1, 0), нормализованное. Удар точно по краю даёт 1 или -1, что соответствует углу в 45 градусов от направления строго вверх. Ограничь число этим диапазоном, так как мяч может коснуться угла платформы чуть дальше её края.

Метод OnCollisionEnter мяча выполняется после того, как физика рассчитает отскок, поэтому заданная в нём скорость заменит его. Стены отправляют то же сообщение, и их обычный отскок должен сохраниться, поэтому сначала проверь, по чему был удар. collision.collider.bounds — это ограничивающий параллелепипед коллайдера в мировом пространстве, с учётом масштаба:

void OnCollisionEnter(Collision collision)
{
    Bounds box = collision.collider.bounds;
    Debug.Log(collision.gameObject.name + " is " + box.size.x + " wide, centered at x = " + box.center.x);
}
challenge icon

Задание

Легко

Добавь OnCollisionEnter(Collision collision) в Ball:

  1. Ничего не делай, если у объекта, с которым произошло столкновение, нет тега Paddle.
  2. Вычисли x: координата x мяча минус координата x платформы, делённое на половину ширины платформы (collision.collider.bounds.size.x); результат должен быть в диапазоне от -1 до 1.
  3. Задай Rigidbody скорость new Vector3(x, 1f, 0f), нормализованную и умноженную на speed.

Нажми Play, отбей мяч возле каждого края платформы, затем нажми Check.

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

using UnityEngine;
using UnityEngine.InputSystem;

public class Ball : MonoBehaviour
{
    public Transform paddle;
    public float speed = 9f;

    Rigidbody rb;
    bool launched;

    void Awake()
    {
        rb = GetComponent<Rigidbody>();
        PhysicsMaterial bouncy = new PhysicsMaterial("Bouncy");
        bouncy.bounciness = 1f;
        bouncy.dynamicFriction = 0f;
        bouncy.staticFriction = 0f;
        bouncy.bounceCombine = PhysicsMaterialCombine.Maximum;
        bouncy.frictionCombine = PhysicsMaterialCombine.Minimum;
        GetComponent<Collider>().material = bouncy;
    }

    void Update()
    {
        if (launched) return;
        transform.position = paddle.position + Vector3.up * 0.5f;
        if (Keyboard.current.spaceKey.wasPressedThisFrame) Launch(new Vector3(0.3f, 1f, 0f));
    }

    public void Launch(Vector3 direction)
    {
        launched = true;
        rb.linearVelocity = direction.normalized * speed;
    }

    void FixedUpdate()
    {
        if (!launched) return;
        rb.linearVelocity = rb.linearVelocity.normalized * speed;
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Игра в Unity: арканоид