Menu
CoddyTech

Патрулирование и погоня

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

Патрульный стражник ходит по маршруту, пока не увидит игрока, преследует его, а когда игрок исчезает, возвращается на маршрут. В обоих случаях он движется одинаково — к заданной точке, поэтому для обоих способов передвижения можно использовать один метод. Этот стражник ходит туда и обратно между двумя постами и преследует игрока, если тот находится в пределах chaseRange:

[SerializeField] private Transform pointA;
[SerializeField] private Transform pointB;
[SerializeField] private Transform player;
[SerializeField] private float speed = 2f;
[SerializeField] private float chaseRange = 5f;
private Rigidbody rb;
private Transform goal;

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

void FixedUpdate()
{
    if (Flat(player.position - rb.position).magnitude < chaseRange)
    {
        WalkTo(player.position);
        return;
    }
    if (Flat(goal.position - rb.position).magnitude < 0.2f)
    {
        goal = goal == pointA ? pointB : pointA;
    }
    WalkTo(goal.position);
}

void WalkTo(Vector3 target)
{
    Vector3 dir = Flat(target - rb.position).normalized;
    rb.linearVelocity = new Vector3(dir.x * speed, rb.linearVelocity.y, dir.z * speed);
}

Vector3 Flat(Vector3 v)
{
    return new Vector3(v.x, 0f, v.z);
}

Сначала выполняется проверка преследования, а return пропускает код патрулирования, поэтому, когда игрок рядом, стражник всегда преследует его. goal — это поле, поэтому стражник помнит его во время преследования: когда игрок исчезает, он продолжает путь к посту, к которому направлялся.

При проверке прибытия измеряется расстояние по земле. Посты — это маркеры на полу, а центр стражника находится на 1 единицу выше них, поэтому расстояние с учетом высоты никогда не станет меньше 1, и стражник никогда не развернется. Проверяется, меньше ли расстояние 0.2, а не равно ли оно точно 0: при скорости 2 единицы в секунду стражник перемещается на 0.04 единицы за шаг и почти никогда не оказывается точно у поста.

challenge icon

Задание

Средне

Заставь робота патрулировать контрольные точки и преследовать игрока, который подходит близко.

  1. Напиши WalkTo(Vector3 target), задавая rb.linearVelocity в направлении цели по земле со скоростью speed и сохраняя скорость по оси y.
  2. В FixedUpdate(), если игрок находится ближе, чем chaseRange, вызови WalkTo(player.position), а затем return.
  3. Иначе, если расстояние до waypoints[next] меньше 0.2, задай next = (next + 1) % waypoints.Length;, а затем иди к waypoints[next].

Нажми «Играть» и пересеките его путь. Затем нажми «Проверить».

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

using UnityEngine;

public class Robot : MonoBehaviour
{
    [SerializeField] private Transform[] waypoints;
    [SerializeField] private Transform player;
    [SerializeField] private float speed = 4f;
    [SerializeField] private float chaseRange = 4f;
    private Rigidbody rb;

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

    void FixedUpdate()
    {
        // Преследовать игрока, когда он близко, иначе следовать по маршруту патрулирования
    }
}

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

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