Menu
CoddyTech

Толкаем предметы

Часть раздела Создание настоящих игр путешествия по Unity на Coddy. Урок 41 из 60.

CharacterController никогда ничего не толкает: направьте его на ящик с компонентом Rigidbody, и он остановится, словно перед стеной. Вместо этого Unity вызывает OnControllerColliderHit(ControllerColliderHit hit) в собственных скриптах контроллера для каждого коллайдера, которого касается Move, включая пол, а скрипт решает, что произойдёт. hit.collider — это то, чего коснулись, hit.moveDirection — направление Move, который коснулся этого объекта, а hit.normal — направление, в котором обращена поверхность в точке контакта. Вот скрипт толкания от Unity:

public float pushPower = 2f;

void OnControllerColliderHit(ControllerColliderHit hit)
{
    Rigidbody body = hit.collider.attachedRigidbody;
    if (body == null || body.isKinematic) return;   // нечего толкать
    if (hit.moveDirection.y < -0.3f) return;        // он у нас под ногами

    Vector3 pushDir = new Vector3(hit.moveDirection.x, 0f, hit.moveDirection.z);
    body.linearVelocity = pushDir * pushPower;
}

У каждого return есть своя причина. У пола и стен нет Rigidbody, поэтому для них body равен null, и с ними происходит столкновение почти при каждом Move. Кинематическое тело перемещается только тогда, когда его перемещает собственный скрипт, поэтому изменение скорости на него не влияет. Если Move направлен круто вниз, значит, он коснулся чего-то под ногами, и ящик, на котором стоит игрок, не следует толкать.

В направлении толчка сохраняются только x и z, поэтому ящик скользит по земле, а не прижимается к ней. Установка linearVelocity вместо приложения силы перемещает лёгкий и тяжёлый ящик с одинаковой скоростью; body.AddForce(pushDir * pushPower, ForceMode.Impulse) толкнул бы тяжёлый ящик слабее.

challenge icon

Задание

Средне

Позволь игроку пинать мячи, в которые он врезается.

  1. В Kicker.cs напиши void OnControllerColliderHit(ControllerColliderHit hit) и получи Rigidbody body = hit.collider.attachedRigidbody;.
  2. Выполни return, если body равен null или является кинематическим, либо если hit.moveDirection.y < -0.3f (мяч находится под ногами).
  3. Задай для body.linearVelocity скорость в направлении движения с компонентой y, равной 0, умноженную на kickPower, плюс Vector3.up * lift.

Нажми «Играть» и врежься в красный мяч: он полетит вперёд и вверх. Затем нажми «Проверить».

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

using UnityEngine;

public class Kicker : MonoBehaviour
{
    public float kickPower = 6f;
    public float lift = 4f;

    // Отталкивать мячи, на которые натыкается игрок
}

Все уроки раздела Создание настоящих игр

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