Апгрейд проекта «Миникарта UI»

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

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

Теперь, основные изменения. Иерархия UI:

Апгрейд проекта «Миникарта UI»

Sample - шаблон для всех объектов, которые автоматически добавляются на миникарту.

Настройки шаблона:


MAP_IMAGE - как и в старом варианте это, спрайт самой карты.

Настройки карты почти такие же, только скрипт для нее теперь специальный:


Layer 0 и Layer 1, это для создания групп, может быть полезно, если нужно чтобы некоторые иконки, отображались поверх других.

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

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

Далее, изменения скриптов.

Главный скрипт миникарты:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Minimap : MonoBehaviour {
	
	public Transform player; // модель персонажа
	public RectTransform playerImage; // иконка персонажа на миникарте
	public enum GameMode {RotatePlayerImage, RotateMapImage}; // режимы, вращать иконку персонажа или самой карты
	public GameMode mode = GameMode.RotateMapImage;
	public float zoom = 10; // зум миникаты и всех иконок на ней
	public RectTransform[] layers; // слои миникаты, для разделения иконок на группы
	public Sprite[] icons; // иконки для объектов
	public MinimapBlip sample; // шаблон объекта для миникарты
	public RectTransform inBoundsRect; // рамка для объектов, которые должны быть внутри окна карты

	private Vector2 XRot = Vector2.right;
	private Vector2 YRot = Vector2.up;
	private float rotateValue;
	private Rect rect;
	private static Minimap _instance;

	void Awake()
	{
		rect = GetComponent<RectTransform>().rect;
		_instance = this;
	}

	public static Minimap Instance
	{
		get{ return _instance; }
	}
	
	public Vector2 TransformPosition(Vector3 position)
	{
		Vector3 offset = position - player.position;
		Vector2 pos = offset.x * XRot;
		pos += offset.z * YRot;
		pos *= zoom;
		return pos;
	}

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

	public Vector2 MoveInside(Vector2 point)
	{
		point = Vector2.Max(point, rect.min);
		point = Vector2.Min(point, rect.max);
		return point;
	}

	Sprite GetIcon(string name)
	{
		foreach(Sprite i in icons)
		{
			if(i.name.CompareTo(name) == 0)
			{
				return i;
			}
		}

		return null;
	}

	public GameObject AddObject(Transform target, bool inBounds, int layer, string iconName, Color iconColor, float iconSize)
	{
		MinimapBlip b = Instantiate(sample) as MinimapBlip;
		b.gameObject.SetActive(true);

		if(inBounds)
		{
			b.GetComponent<RectTransform>().SetParent(inBoundsRect);
		}
		else
		{
			b.GetComponent<RectTransform>().SetParent(layers[layer]);
		}

		b.inBounds = inBounds;
		b.target = target;
		b.iconSize = iconSize;
		b.GetComponent<Image>().sprite = GetIcon(iconName);
		b.GetComponent<Image>().color = iconColor;
		return b.gameObject;
	}

	void LateUpdate()
	{
		if(mode == GameMode.RotateMapImage)
		{
			XRot = new Vector2(player.right.x, -player.right.z);
			YRot = new Vector2(-player.forward.x, player.forward.z);
			rotateValue = player.eulerAngles.y;
			playerImage.localEulerAngles = Vector3.zero;
		}
		else
		{
			XRot = Vector2.right;
			YRot = Vector2.up;
			rotateValue = 0;
			playerImage.localEulerAngles = new Vector3(0, 0, player.eulerAngles.y);
		}
	}
}

Скрипт шаблона:

using UnityEngine;
using System.Collections;

public class MinimapBlip : MonoBehaviour {

	public Transform target;
	public bool inBounds;
	public float iconSize;

	private RectTransform rect;

	void Start()
	{
		rect = GetComponent<RectTransform>();
		rect.sizeDelta = new Vector2(iconSize, iconSize);
	}

	void LateUpdate()
	{
		Vector2 pos = Minimap.Instance.TransformPosition(target.position);
		if(inBounds) pos = Minimap.Instance.MoveInside(pos);
		rect.localScale = new Vector3(Minimap.Instance.zoom, Minimap.Instance.zoom, 1);
		rect.localEulerAngles = Minimap.Instance.TransformRotation(target.eulerAngles);
		rect.localPosition = pos;
	}
}

Специальный скрипт для изображения миникарты:

using UnityEngine;
using System.Collections;

public class MinimapImage : MonoBehaviour {

	public Transform targetPlane;
	private RectTransform rect;

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

	void LateUpdate()
	{
		Vector2 pos = Minimap.Instance.TransformPosition(targetPlane.position);
		rect.localScale = new Vector3(Minimap.Instance.zoom, Minimap.Instance.zoom, 1);
		rect.localEulerAngles = Minimap.Instance.TransformRotation(targetPlane.eulerAngles);
		rect.localPosition = pos;
	}
}

Компонент для объектов:

using UnityEngine;
using System.Collections;

public class MinimapComponent : MonoBehaviour {

	public int minimapLayer;
	public bool inBounds;
	public float iconSize = 1;
	public string iconName = "enemy 1";
	public Color iconColor = Color.red;
	private GameObject blip;

	void Start()
	{
		// создание новой иконки данного объекта на миникарте
		blip = Minimap.Instance.AddObject(this.transform, inBounds, minimapLayer, iconName, iconColor, iconSize);
	}

	void OnDisable() // если объект не активен (выключен в инспекторе), отключаем иконку на миникарты
	{
		if(blip) blip.SetActive(false);
	}

	void OnEnable() // если объект активирован (включен в инспекторе), активируем иконку на миникарты
	{
		if(blip) blip.SetActive(true);
	}

	void OnDestroy() // если объект уничтожен, то и уничтожаем иконку
	{
		Destroy(blip);
	}
}

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

Чтобы добавить и настроить объект, теперь просто цепляем MinimapComponent:


Указываем слой, в пределах окна или нет, размер иконки, имя (соответствующие спрайты, должны быть добавлены в массив миникарты), и указываем цвет для иконки.

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

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