Прилипание спрайта к границам экрана

Представим такую ситуацию, например, нам нужно в рамках экрана разместить некие спрайты, которые будут как часть интерфейса пользователя или может это будет элемент фона. Если мы располагаем объекты на сцене, то ориентируемся прежде всего на текущие настройки, соотношения сторон экрана, так как если переключить соотношение, допустим, с 16:9 на 16:10 то мы увидим изменения по ширине экрана и объекты, которые находятся с левой и правой стороны, будут «обрезаны». Так вот, нам нужно сделать так, чтобы объекты «прилипали» к границам экрана, и соответственно меняли свою позицию при изменении разрешения экрана.


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

using System.Collections;
using UnityEngine;
[ExecuteInEditMode] // выполнение в редакторе
public class Responsive2D : MonoBehaviour {

	private enum Anchor
	{
		Center,
		MiddleLeft,
		MiddleRight,
		BottomCenter,
		BottomLeft,
		BottomRight,
		TopLeft,
		TopRight,
		TopCenter
	}

	[SerializeField] private Prefs[] objectPrefs;
	private Vector2 resolution = Vector2.zero;

	[System.Serializable] struct Prefs
	{
		public SpriteRenderer target;
		public Vector2 offset;
		public Anchor anchor;
	}

	Vector2 ScreenAnchor(Anchor value, out Vector2 delta) // определяем координаты по якорю
	{
		Vector2 result = Vector2.zero;
		delta = Vector2.zero;

		switch(value)
		{
		case Anchor.Center:
			delta = new Vector2(.5f, .5f);
			result = new Vector2(Screen.width/2, Screen.height/2);
			break;
		case Anchor.MiddleLeft:
			delta = new Vector2(1f, .5f);
			result = new Vector2(0, Screen.height/2);
			break;
		case Anchor.MiddleRight:
			delta = new Vector2(0, .5f);
			result = new Vector2(Screen.width, Screen.height/2);
			break;
		case Anchor.BottomCenter:
			delta = new Vector2(.5f, 1f);
			result = new Vector2(Screen.width/2, 0);
			break;
		case Anchor.BottomLeft:
			delta = new Vector2(1f, 1f);
			result = new Vector2(0, 0);
			break;
		case Anchor.BottomRight:
			delta = new Vector2(0, 1f);
			result = new Vector2(Screen.width, 0);
			break;
		case Anchor.TopCenter:
			delta = new Vector2(.5f, 0);
			result = new Vector2(Screen.width/2, Screen.height);
			break;
		case Anchor.TopLeft:
			delta = new Vector2(1f, 0);
			result = new Vector2(0, Screen.height);
			break;
		case Anchor.TopRight:
			delta = new Vector2(0, 0);
			result = new Vector2(Screen.width, Screen.height);
			break;
		}

		return result;
	}

	void UpdatePosition() // обновление массива спрайтов
	{
		for(int i = 0; i < objectPrefs.Length; i++)
		{
			if(objectPrefs[i].target != null)
			{
				Vector2 delta;
				Vector2 anchor = ScreenAnchor(objectPrefs[i].anchor, out delta);
				objectPrefs[i].target.transform.position = TargetPosition(objectPrefs[i].target.transform.position, anchor, objectPrefs[i].target.bounds, delta, objectPrefs[i].offset);
			}
		}
	}

	Vector3 TargetPosition(Vector3 worldPoint, Vector2 screenPoint, Bounds bounds, Vector2 delta, Vector2 offset)
	{
		Vector3 worldPosition = Camera.main.ScreenToWorldPoint(screenPoint + offset);
		worldPosition.x += bounds.size.x / 2f * (delta.x - screenPoint.x / Screen.width);
		worldPosition.y += bounds.size.y / 2f * (delta.y - screenPoint.y / Screen.height);
		worldPosition.z = worldPoint.z;
		return worldPosition;
	}

	void LateUpdate()
	{
		if(resolution.x != Screen.width || resolution.y != Screen.height) // только, если было изменено разрешение экрана
		{
			UpdatePosition();
			resolution.x = Screen.width;
			resolution.y = Screen.height;
		}

		#if UNITY_EDITOR
		UpdatePosition(); // постоянное обновление в редакторе
		#endif
	}
}

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

Скачать скрипт:

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

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

Офлайн
Влас 14 февраля 2018
Есть же canvas, или я что-то путаю?
Офлайн
Light 14 февраля 2018
Влас, он работает с RectTransform, а тут для обычного Transform.
Офлайн
igorm 16 февраля 2018
полезный скрипт
Офлайн
igorm 22 февраля 2018
только Camera.main надо бы закешировать, потому что она каждый раз будет искаться
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика