
Привет разработчикам игр! Решил поделиться гайдом, который довольно часто встречается в различных играх. Речь пойдёт о потрулировании игрового объекта. Не будем долго тянут, а сразу приступим к делу.
Что собой представляет патрулирование персонажа? Это многократное передвижение персонажа между двумя точками. Исходя из данной информации, нам необходимо создать один игровой объект, то-есть персонаж(Player), и два игровых объекта(spot1 и spot2), между которыми этот персонаж будет патрулировать. Так же для удобства можно создать любой игровой объект(AreaPatrolSimple), который будет служить обёрткой. Давайте сделаем это.

Теперь нам необходимо создать скрипт для нашего персонажа Player, в котором и пропишем патрулирование между точками:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class patrolSimple : MonoBehaviour
{
public float speed;
public int spot = 0;
public Transform[] moveSpots;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, moveSpots[spot].position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpots[spot].position) < 0.2f)
{
spot = (spot == 1) ? 0 : 1;
}
}
}
Теперь Этот c# скрипт прикрепляем к игровому объекту Player. А потом объекты spot1 и spot2 перетаскиваем в поля объекта Player, как показано на рисунке.

Готово! Давайте теперь вкратце разберём, как же работает наш C# скрипт:
- В переменной speed мы должны указать скорость передвижения объекта. Скорость указать можете сразу в скрипте, а можете в инспекторе редактора Unity.
- Переменная spot показывает то, какой из двух элементов будет являться первым, к которому будет двигаться игровой объект. Он принимает значения или 0 или 1.
- В массиве moveSpots будут хранится игровые объекты spot1 и spot2, которые мы укажем в инспекторе.
Далее с помощью метода Vector3.MoveTowards, мы плавно перемещаем наш объект Player, с текущей позиции (transform.position) до той позиции, где расположен наш объект с индексом 0 (moveSpots[spot].position) - им является объект spot1. Так же установим скорость перемещения объекта (speed * Time.deltaTime).
Далее с помощью Vector2.Distance мы проверяем расстояние игрового объекта Player(transform.position) с объектом spot1(moveSpots[spot].position), чтобы понять, дошёл ли наш объект до этой точки. И если да, то меняем переменную spot на 1, чтобы объект начал своё движение до spot2.
Как только он дойдёт до объекта spot2, значение переменной spot изменится на 0, и Player будет опять двигаться до spot1.
Как видите, всё очень просто. Но на самом деле, этот код не совсем завершён, ведь что делать, если точек в патрулировании нужно установить не 2, а 5, или 20?
Сложное Патрулирование

Предлагаю немного переписать наш код, чтобы он автоматически подстраивался под необходимое количество точек, хоть 2, хоть 5, хоть 100.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class patrolMultiple : MonoBehaviour
{
public float speed;
public int spot = 0;
public int next = 1;
public Transform[] moveSpots;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, moveSpots[spot].position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpots[spot].position) < 0.2f)
{
if(spot == moveSpots.Length - 1)
{
next = -1;
}
if (spot == 0)
{
next = 1;
}
spot += next;
}
}
}
Как видите, у нас появилась переменная next. При значении "1", движение персонажа Player будет реализовано по точкам 1-2-3-4 и тд. При значении "-1", движение Player будет в обратную сторону, 4-3-2-1.
А в остальном скрипт почти одинаков, за исключением проверки. В 19 строке мы проверяем точку spot, является ли она ПОСЛЕДНЕЙ? Если да, то переменная меняет своё значение на "-1", и движение Player происходит в обратную сторону. А в строке 24 идёт проверка, дашёл ли Player до самой первой точки? Если да, то next меняется на "1", и персонаж снова движется вперёд.
Хаотичное патрулирование (бонус)
На самом деле, патрулирований бывает огромное множество. И в качестве интересного примера, на основе нашего последнего скрипта создадим патрулирование, в котором персонаж будет случайным образом выбирать любую точку, и двигаться к ней. Тоесть, так называемое, хаотичное патрулирование.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class patrolRandom : MonoBehaviour
{
public float speed;
public Transform[] moveSpots;
private int randomSpot;
void Start()
{
randomSpot = Random.Range(0, moveSpots.Length);
}
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, moveSpots[randomSpot].position, speed * Time.deltaTime);
if (Vector2.Distance(transform.position, moveSpots[randomSpot].position) < 0.2f)
{
randomSpot = Random.Range(0, moveSpots.Length);
}
}
}
Как видите, здесь мы создали переменную randomSpot, в которой будет хранится значение той точки, к которой будет двигаться наш персонаж - оно будет постоянно меняться. Это значение впервые присваивается как только запустится данный скрипт (строка 13).
Так же это значение будет меняться случайным образом сразу после того, как персонаж дойдёт до целевой точки(строка 22).
Спасибо всем за внимание, надеюсь максимально понятно обьяснил принцип патрулирования. Не откажусь от лайков :)