Строительство базы / расстановка объектов [RTS]

Итак, строительство базы в стратегии. Параметры, которые участвуют в этом процессе могут самые разные. Возможно золото или минералы, доступность энергии и прочее. В каждом проекте может быть что-то индивидуальное, однако, общее для всех это само строительство, то есть, расстановка объектов в определенной области. Что нам нужно сделать? Во-первых, у нас есть набор иконок, каждый обозначает некую постройку. При клике по иконке, получаем заготовку постройки, которую можно двигать по плоскости XZ. Во-вторых, нужно сделать так, чтобы новые здания нельзя было создать там где уже есть постройка и там, где запрещено строить что-либо.


Данный вариант подходит только для 3D, для двухмерного проекта надо переделывать рэйкаст и плоскость движения объектов.

Подготовка. Создание самих строений, модельки зданий. Как они будут анимированы и прочее - не важно, главное моделька должны быть под коллайдером, это необходимо не только для строительства, но и для создания карты навигации ботов. Например:

Строительство базы / расстановка объектов [RTS]

Коллайдер должен закрывать весь объект.

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


Точно также, объект должен закрываться коллайдером, но в режиме Is Trigger. При этом коллайдер макета можно сделать чуть-чуть больше чем у оригинала, на +0.1 допустим, это повысит чувствительность и гарантирует, чтобы невозможно было создать один объект поверх другого. У всех макетов должен быть установлен слой Ignore Raycast! Дополнительно на модельку вешаем Rigidbody и выключаем гравитацию. Плюс, вешаем небольшой скрипт MaskControl:

using UnityEngine;
using System.Collections;

public class MaskControl : MonoBehaviour {

	public string respawnTag = "Respawn";

	void Start()
	{
		DragAndDrop.isOn = true;
	}

	void OnTriggerStay(Collider coll)
	{
		if(coll.tag != respawnTag)
		{
			DragAndDrop.isOn = false;
		}
	}

	void OnTriggerExit(Collider coll)
	{
		if(coll.tag != respawnTag)
		{
			DragAndDrop.isOn = true;
		}
	}
}

Задача этого скрипта в том, чтобы определять где можно установить объект, а где нет. В переменной respawnTag мы указываем тег, который разрешает установку. Допустим если сделать плоскость с тегом, то здание можно строить только в этой области, а если объект наткнется на другие строения то автоматически заблокируется. В общем всё как и обычной стратегии.

Далее, имена строений. Оригинальные префабы зданий именуются вот так id_xxx, то бишь - номер, нижние подчеркивание, имя. Префабы макетов, именуются точно также, номера оригинала и макета - должны совпадать, а имена могут различаться.

Теперь вешаем на пустой объект скрипт DragAndDrop:

using UnityEngine;
using System.Collections;
using System;

public class DragAndDrop : MonoBehaviour {

	public Transform[] original;
	public Transform[] mask;
	public float shift = 0.01f;
	public string respawnTag = "Respawn";

	public static bool isOn;
	private Transform original_tmp;
	private Transform mask_tmp;
	private Vector3 curPos;

	void Start()
	{
		isOn = false;
	}

	public void SetMask(int id)
	{
		foreach(Transform obj in original)
		{
			string name = obj.name.Split(new char[] {'_'}, StringSplitOptions.RemoveEmptyEntries)[0];
			if(id.ToString() == name)
			{
				original_tmp = Instantiate(obj);
				original_tmp.gameObject.SetActive(false);
			}
		}

		foreach(Transform obj in mask)
		{
			string name = obj.name.Split(new char[] {'_'}, StringSplitOptions.RemoveEmptyEntries)[0];
			if(id.ToString() == name)
			{
				mask_tmp = Instantiate(obj);
			}
		}
	}

	void Update() 
	{
		RaycastHit hit;
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		if (Physics.Raycast(ray, out hit))
		{
			curPos = hit.point + hit.normal * shift;
		}

		if(mask_tmp)
		{
			mask_tmp.position = curPos;

			if(Input.GetAxis("Mouse ScrollWheel") > 0)
			{
				mask_tmp.localEulerAngles += new Vector3(0, 45, 0);
			}
			if(Input.GetAxis("Mouse ScrollWheel") < 0)
			{
				mask_tmp.localEulerAngles -= new Vector3(0, 45, 0);
			}

			if(Input.GetMouseButtonDown(0) && isOn)
			{
				original_tmp.gameObject.SetActive(true);
				original_tmp.position = mask_tmp.position;
				original_tmp.localEulerAngles = mask_tmp.localEulerAngles;
				original_tmp = null;
				isOn = false;
				Destroy(mask_tmp.gameObject);
			}
			else if(Input.GetMouseButtonDown(1))
			{
				Destroy(original_tmp.gameObject);
				Destroy(mask_tmp.gameObject);
			}
		}
	}
}

original - массив всех префабов с оригинальными моделями построек.

mask - массив всех префабов макетов.

shift - сдвиг по оси Y для модельки.

respawnTag - тег плоскости на которой разрешено строительство.

На сцену нужно добавить несколько UI элементов, точнее иконки, GameObject > UI > Image. Создаем нужное количество иконок, размещаем как нужно. Затем, на каждую иконку надо добавить компонент Event Trigger, выбрать в нем функцию Pointer Click а потом перетащить в активное поле объект со скриптом DragAndDrop и меню выбрать функцию скрипта - SetMask и указываем номер макета. Например:


То есть, суть в том, что каждая иконка соответствует конкретной модели, поэтому мы назначаем номера. В игре, кликаем на иконку - отправляем номер в скрипт - он находит соответствующую модель. Так это работает.

ЛКМ по иконке - получить макет здания. Повторный ЛКМ - установить здание. ПКМ - отмена. Колесико мыши - вращать.

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

У вас нет доступа!

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

Офлайн
Andrejus 11 августа 2015
Замечательный урок. Большое спасибо
Офлайн
Prog-Maker 7 марта 2017
У вас в статье скрипт MaskControl не такой как в проекте, вернее не полный.
Офлайн
ArturST 21 апреля 2017
как адаптировать под точскрин управление макетом здания (вращать, отмена) https://docs.unity3d.com/ru/530/Manual/MobileInput.html что использовать вместо Input думаю данный вопрос будет интерес много кому
Офлайн
ArturST 21 апреля 2017
предварительно по поводу вращения думаю на макете можно сделать кнопки вращения
Офлайн
Light 21 апреля 2017
ArturST, для тачскрина используется такой код:

void Update()
{
	if(Input.touchCount > 0)
	{
		Controls();
	}
}

void Controls()
{
	if(Input.GetTouch(0).phase == TouchPhase.Began)
	{
		// касание экрана пальцем
	}

	if(Input.GetTouch(0).phase == TouchPhase.Moved)
	{
		// палец движется по экрану
	}

	if(Input.GetTouch(0).phase == TouchPhase.Ended)
	{
		// палец убран
	}

	if(Input.GetTouch(0).phase == TouchPhase.Stationary)
	{
		// палец на экране, но не движется
	}
}
Офлайн
Light,
Можете сделать, пожалуйста в 2D проекте ?
Офлайн
Crysis001 10 июля 2017
Подскажите пожалуйста какие есть подходы к созданию к 2d стратегиям координатной сетки на Unity. Хочется чтобы как в фермах выбираешь объект для размещения на поле, а поле уже поделено сеткой для возможного размещения. Как такое возможно реализовать??
Офлайн
Light 10 июля 2017
Crysis001, ну, если в игре можно ставить конкретный объект, только в определенном месте, то изначально всё игровое поле нужно накрывать спрайтом сетки, который запрещает ставить объект, а в зеленых зонах, поверх показывать другую сетку.

В планах строительство для 2д проектов, возможно там будет реализовано нечто такое...
Офлайн
Crysis001 20 июля 2017
Цитата: Light
Crysis001, ну, если в игре можно ставить конкретный объект, только в определенном месте, то изначально всё игровое поле нужно накрывать спрайтом сетки, который запрещает ставить объект, а в зеленых зонах, поверх показывать другую сетку.

В планах строительство для 2д проектов, возможно там будет реализовано нечто такое...

А как реализовать сетку, допустим для 3d? Строить здания по сетке что бы то же с подсвечиваниями где можно строить и где нельзя. Есть ли такие уроки или примеры? Очень хотелось об этом узнать.
Офлайн
Light 20 июля 2017
Crysis001, есть ли именно такие уроки, мне неизвестно. Но как уже говорил ранее, в планах улучшение данного проекта, и возможно там будет такая фишка.
Офлайн
Помогите пожалуйста, поставил свои модельки вместо ваших . Все сделал по инструкции но как только я выбираю нужную модельку по кнопке то она начинает лететь в центр экран. Что мне делать ?
Офлайн
Андрей Сандаков,
разобрался
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика