Делаем миникарту с помощью Unity UI

Самый простой способ сделать миникарту, это задействовать еще одну камеру, которая будет смотреть сверху вниз, достаточно настроить ее размер и расположить сбоку экрана. Чаще всего предлагается именно такой вариант в различных уроках. Но здесь есть рад серьезных недостатков. Увеличится нагрузка на систему, потому что используется две камеры, оптимизация просядет. При слабом освещении, например, ночью – миникарта тоже будет темной, а это неприемлемо. Поэтому мы будем делать миникарту на основе скриншота основной карты, это будет обычный спрайт, вражеские юниты и игрок, тоже спрайты. Задача в том, чтобы всё это выглядело как уменьшенная копия карты. Такие вот дела.


Итак, прежде чем приступать к созданию миникарты, нужно сделать снимок сцены как карты. Добавим на сцену обычный Plane, растягиваем его так, чтобы он покрыл всю карту, но с сохранением соотношения сторон, должен быть квадрат, в который вмещается вся карта. Теперь добавим новую камеру и отключаем все прочие. Поворачиваем ее по оси Х на 90, чтобы она смотрела под прямым углом - сверху вниз. Поднимаем повыше над объектами. Режим Projection переключаем в Orthographic, так как миникарта нужна в 2D. Добавим разрешение в проект например 1000х1000, то есть, чтобы получить квадрат. А параметр Size настраиваем, чтобы в камеру уместился весь Plane. Кроме того, параметр Rendering Path ставим на Vertex Lit, так изображение будет больше подходить под наши нужды, выпрямятся тени, исчезнут блики, цвета ярче будут.


Не забывайте, что еще нужно отключить все объекты, которые могут двигаться. Персонажи, лифт, какие-нибудь платформы и т.п - всё это выключить на время. Скриншотить надо только статические объекты, это важно, тоже самое что и при создании карты навигации.



А чтобы снять скрин задействуем стандартные функции:

void Start () 
{
	Application.CaptureScreenshot(Application.dataPath + "/map.png");
}

Файл будет создан в папке Assets вашего проекта.

Вот, теперь, у нас есть снимок карты. Дополнительно еще понадобится спрайты для игрока и для вражеского бота. Ну как обычно делают в играх, игрок в виде стрелки, а боты красные кружочки или квадратики, кому как угодно. Добавляем на сцену Canvas а в него Image и сразу переименовываем в MiniMap, это будет окошком для отображения миникарты и активных объектов, настраиваем его размеры и размещаем в нужном месте, плюс, добавляем компонент Mask - маска нужна, чтобы обрезать лишнее за приделами нашего окна.

Двигаемся дальше. Теперь спрайт скриншота карты. Его мы делаем дочерним к MiniMap как обычную картинку и переименуем в MAP.

Важный момент! У MAP нужно настроить ширину и высоту Width / Height, чтобы правильно масштабировать изображение. Делается это на основе того самого Plane квадрата, потому как и скриншот мы делали тоже на его основе, точнее его размеров. Как раз они нам и нужны, смотрим размер квадрата, допустим если его стороны 10х10, то ширина и высота получается 100х100, если 5х5 - тогда 50х50, то есть умножаем на десять.

Делаем миникарту с помощью Unity UI

В дальнейшем масштаб карты будет регулироваться через скрипт.

Кстати цепляем сам скрипт Blip:

using UnityEngine;
using System.Collections;

public class Blip : MonoBehaviour {

	public Transform target;
	public bool inBounds;
	public float minScale = 1;

	private RectTransform rect;
	private MiniMap map;

	void Start()
	{
		map = GetComponentInParent<MiniMap>();
		rect = GetComponent<RectTransform>();
	}

	void LateUpdate()
	{
		Vector2 pos = map.TransformPosition(target.position);
		if(inBounds) pos = map.MoveInside(pos);
		float scale = Mathf.Max(minScale, map.zoom);
		rect.localScale = new Vector3(scale, scale, 1);
		rect.localEulerAngles = map.TransformRotation(target.eulerAngles);
		rect.localPosition = pos;
	}
}

В качестве цели target - указываем опять же Plane. Переменная inBounds обозначает будет-ли объект в приделах рамки окна, даже если игрок ушел далеко от него, для миникарты этот параметр должен быть отключен. Переменная minScale, для регулировки исходного размера, для миникарты этот параметр не должен превышать единицы.

Далее, тут же добавляем спрайты игрока и ботов, так же как и выше приведенный MAP. Но с некоторыми отличиями, во первых ширину и высоту, делаем значительно меньше, зависит от игровых объектов, например для стандартного Cube, значения будут 1.25х1.25. Позже поэкспериментируйте с этими параметрами, выберите как будет лучше. И соответственно в качестве цели target указываем соответствующие объекты, позиции которых будем отображать. Параметр minScale делаем больше, например 10.

В иерархии дочерних UI миникарты, изображение карты должно быть выше всех остальных:



Вешаем скрипт на MiniMap с таким же названием:

using UnityEngine;
using System.Collections;

public class MiniMap : MonoBehaviour {

	public Transform target;
	public float zoom = 10;

	private Vector2 XRot = Vector2.right;
	private Vector2 YRot = Vector2.up;
	
	public Vector2 TransformPosition(Vector3 position)
	{
		Vector3 offset = position - target.position;
		Vector2 pos = offset.x * XRot;
		pos += offset.z * YRot;
		pos *= zoom;
		return pos;
	}

	public Vector3 TransformRotation(Vector3 rotation)
	{
		return new Vector3(0, 0, target.eulerAngles.y - rotation.y);
	}

	public Vector2 MoveInside(Vector2 point)
	{
		Rect rect = GetComponent<RectTransform>().rect;
		point = Vector2.Max(point, rect.min);
		point = Vector2.Min(point, rect.max);
		return point;
	}

	void LateUpdate()
	{
		XRot = new Vector2(target.right.x, -target.right.z);
		YRot = new Vector2(-target.forward.x, target.forward.z);
	}
}

Здесь в target нужно указывать игрока. А с помощью zoom, зумим миникарту.

Последний штрих. Нужно установить приоритет выполнения скриптов. С начало идет MiniMap, потому что здесь просчитывается вращение спрайтов, а уже потом идут запросы Blip. Чтобы назначить очередность, выделите любой скрипт и жмем Execution Order:


А затем настраиваем:


Собственно всё, остается пробовать и смотреть, с какими настройками чего можно добиться.

Разумеется, скачать уже собранный проект можно тут:

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

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

Офлайн
Andrejus 26 июля 2015
Как всегда отличный урок
Офлайн
Cyborg_777 31 июля 2020
Очень нужный урок. Большое спасибо!
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика