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

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

MAP_IMAGE - как и в старом варианте это, спрайт самой карты.
Настройки карты почти такие же, только скрипт для нее теперь специальный:

Layer 0 и Layer 1, это для создания групп, может быть полезно, если нужно чтобы некоторые иконки, отображались поверх других.
Player - собственно иконка персонажа, которую мы настраиваем вручную. Так как в процессе игры, она не будет уничтожаться в отличии от временных иконок, кроме того, изображение персонажа всегда должно быть поверх остальных групп иконок.
InBounds - это отдельный RectTransform, который делается поверх самой миникарты, с точно такими же настройками Transform как у нее. Это своего рода окно, куда будут помещаться иконки, которые всегда должны быть видимыми, например, это иконка точки назначения или задания.
Далее, изменения скриптов.
Главный скрипт миникарты:
Скрипт шаблона:
Специальный скрипт для изображения миникарты:
Компонент для объектов:
Стоит отметить что этот компонент, не влияет на объект, а только реагирует на некоторые действия с ним. Например, это касается оптимизации, если игрок отходит на некоторое расстояние от объекта, то его можно деактивировать, в этом случаи иконка на миникарте тоже будет дезактивирована.
Чтобы добавить и настроить объект, теперь просто цепляем MinimapComponent:

Указываем слой, в пределах окна или нет, размер иконки, имя (соответствующие спрайты, должны быть добавлены в массив миникарты), и указываем цвет для иконки.
Скачать проект:
Итак, прежде чем рассматривать изменения, нам нужно сделать всё, что было в предыдущем проекте.
Теперь, основные изменения. Иерархия 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:

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