Построение отряда по шаблону

Подобное можно увидеть в таких играх как Original Sin или, например, Total War. У нас есть группа юнитов или персонажей, которым мы задаем построение на основе определенного шаблона. При этом, само построение отряда должно сохраниться, когда юниты сменят свою позицию. Направление «лица» для каждого юнита, так же определяется шаблоном, то есть, мы можем создавать какие угодно формы построения. Разворот шаблона и соответственно юнитов, будет осуществляется после указания точки назначения отряда мышкой, например, если отряд развернут в правую сторону, а затем кликнуть с левой стороны отряда, то шаблон будет развернут в эту сторону.


Для начала нам нужно создать шаблоны.

Первое, добавляем на сцену спрайт в виде стрелки:

Построение отряда по шаблону

Обратите внимание, что стрелка должна быть развернута по оси Z.

После этого, мы объедением все спрайты в группу (делаем их дочками):


При этом родительский объект, так же, должен быть развернут в нужную сторону, в данном случаи "лицо" отряда смотрит по оси Z.

Когда дочерние объекты отряда будут настроены, их можно выключить.

Теперь, на родительский объект отряда вешаем простенький скрипт:

using System.Collections;
using UnityEngine;

public class SampleComponent : MonoBehaviour {

	public Transform[] point;

}

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

На юнитов вешаем скрипт:

using System.Collections;
using UnityEngine.AI;
using UnityEngine;

[RequireComponent(typeof(NavMeshAgent))]

public class UnitComponent : MonoBehaviour {

	private NavMeshAgent agent;

	void Awake()
	{
		agent = GetComponent<NavMeshAgent>();
	}

	public void Destination(Vector3 position)
	{
		agent.SetDestination(position);
	}

	public void MyUpdate(Vector3 forward)
	{
		if(!agent.hasPath) // разворот юнита
		{
			transform.forward = Vector3.Lerp(transform.forward, forward, 0.05f);
		}
	}
}

Данный класс отвечает за движение и разворот юнита в отряде.

Далее, для управления всем этим, добавим на сцену еще один скрипт:

using System.Collections;
using UnityEngine;

public class SquadManager : MonoBehaviour {

	[SerializeField] private UnitComponent[] unit;
	[SerializeField] private SampleComponent[] sample;
	[SerializeField] private LayerMask layerMask;
	private int index;
	private Transform last;

	void Start()
	{
		Destination();
	}

	void LateUpdate()
	{
		if(Input.GetMouseButtonDown(1))
		{
			RaycastHit hit;
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
			if(Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
			{
				last = sample[index].transform;
				last.forward = (hit.point - last.position).normalized;
				last.position = hit.point;
				Destination();
			}
		}

		for(int i = 0; i < unit.Length; i++)
		{
			unit[i].MyUpdate(sample[index].point[i].forward);
		}
	}

	void Destination()
	{
		for(int i = 0; i < unit.Length; i++)
		{
			unit[i].Destination(sample[index].point[i].position);
		}
	}

	public void SetSample(int i) // функция переключения шаблона
	{
		if(i < 0) index = 0; else if(i > unit.Length-1) index = unit.Length-1; else index = i;
		sample[index].transform.forward = last.forward;
		sample[index].transform.position = last.position;
		Destination();
	}
}

Тут мы определяем массив юнитов и шаблонов. Так как мы заранее знаем сколько юнитов в будет в отряде, то чисто юнитов в массиве и число точек в шаблоне должны совпадать.

Скачать демо проект:

Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.
Тестировалось на: Unity 5.6.0

Комментариев 4

Офлайн
sherck 1 апреля 2017
/offTop/Простите за оффтоп, я новичок, я сделал TD игру, где есть грид на него наложена NavMesh, есть EnemySpawnPint- от куда враги движутся к HomeTarget, есть Tower - вставляеш его и враги видят его как препятствие и обходят его. Все работает, но мне нужно чтобы всегда было бы путь от EnemySpawnPint до HomeTarget, то есть если вставляемый Tower в ячейку закроет путь, то вывести сообщение/красный бекграунд ячейки что нельзя вставить Tower в эту ячейку. Можно ли это сделать стандартными средствами Unity(NavMesh, NavMeshAgent etc.) или все же нужно написать самому? Просто не хочется строит костыли если все уже есть. Спасибо заранее.
Офлайн
Alex2D 1 апреля 2017
Спасибо Вам за новый урок! :)
Как раз пригодится, можно сказать, прямо сейчас :)
Добавил несколько построений -всё прекрасно работает, единственное, что "не по плану" - исключение - переменная "last" не инициализирована, если попытаться поменять шаблон до первого перемещения отряда.

С Уважением, Алексей!

P.S. А не могли бы Вы предложить вариант кода, который позволил бы сначала развернуть построение, так чтобы оно всё целиком было повёрнуто в направлении Цели, а уже потом двигаться к ней в боевом строю? Мне кажется был бы очень интересный и востребованный алгоритм. :)
Офлайн
Louren325 6 апреля 2017
Исправьте, пожалуйста, название.
отрЯда
Офлайн
Golden50k 27 октября 2017
Спасибо, то что нужно!
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика