Unity 2D: робота зі спрайтами в різних дозволах дисплея


Починаючи з версії 4.3 Unity з'явилася можливість роботи з 2D графікою, велика частина нових стандартних рішень мені припали до душі, тому що я якраз незадовго до цього оновлення перейшов з Corona SDK.
Але що мене не порадувало, так це відсутність стандартних інструментів для оптимізації спрайтів під різні дозволи екранів, що має досить таки істотний вплив на продуктивність на малопотужних пристроях.

Звичайно можна використовувати щось схоже на 2D Toolkit для вирішення цієї проблеми, але навіщо платити 75$, якщо можна зробити все самому?

Зі слів користувачів офіційного форуму Unity, розробники незабаром не планують розширювати 2D функціонал, принаймні до релізу 5 версії Unity і поки що користувачі повинні самостійно вирішувати цю проблему. Борознячи простори інтернету в надії знайти відповідь, я натрапив на цікавий доповідь одного з розробників Unity на літній Nordic Game Conference 2014, назва говорить сама за себе «2D issues and how to solve them». Користуючись матеріалами цієї доповіді, я зробив своє рішення проблеми підтримки дисплеїв різного дозволу.

Для того, щоб почати нам потрібна тільки версія атласу спрайтів з найвищим дозволом, інші маніпуляції з зменшенням якості атласів відбуваються всередині Unity.

Підготовка спрайтів

Отже, на першому етапі ми повинні організувати атласи спрайтів для різних дозволів: SD, HD, ultra-HD, у нас же будуть використані суфікси 1x, 2x, 4x.

Беремо атлас спрайтів, в нашому випадку це 'spritesheet1@4x.png', в інспекторі вибираємо потрібні параметри, ріжемо атлас в Sprite Editor, якщо потрібно. Створюємо ще дві копії атласу Project Browser (cmd+D, ctrl+D) і перейменуємо їх так, щоб суфікси в назві були '@2x', '@1x', міняємо властивість Max Size значення в 2 і в 4 рази менше відповідно.

Спрайт повинні знаходиться в папці Resources, якщо такий не є, створіть. Це дозволяє завантажувати файли з цієї папки під час виконання програми.





Зверну Вашу увагу на поля Pixels Per Unit і Format перше допоможе підібрати розмір спрайтів під розміри сцени без зміни scale, а друге є дуже важливим для правильної передачі кольору, розміру білду і використання ресурсів графічного процесора. На цю тему є чудовий мануал

Підготовка префаба

Тут все просто, ми збираємо ігровий об'єкт на основі атласу спрайтів з суфіксом '@2x', додаємо анімацію і будь-які інші фішки, які можуть вам знадобиться. Зберігаємо об'єкт як префаб.
Суфікс '@2x' був обраний, тому що більша частина пристроїв мають hd дозвіл, нам не доведеться робити зайву роботу в більшості випадків.

Скрипт

Скрипт буде працювати з будь-якою кількістю компонентів SpriteRenderer. Він не буде впливати ні на анімацію, ні на що інше, головне щоб імена спрайтів в атласі і SpriteRenderer'е були однаковими. Дану особливість можна застосовувати не тільки для зміни дозволу спрайтів, але і для заміни їх на цілком інші, наприклад при створенні іншого скіна персонажа.

Основний принцип роботи скрипта такий: у нас є публічна мінлива spriteSheet, в якій ми передаємо ім'я атласу в якому знаходяться спрайт нашого об'єкта.



За допомогою методу GetQuality дізнаємося з яким дисплеєм ми маємо справу (для моїх цілей було досить орієнтуватися на висоту екрана).

Потім у методі ManageQuality, маючи дані про дозвіл екрана, завантажуємо в масив sprites всі спрайт потрібного нам атласу з правильним суфіксом. В масив renderers завантажуємо всі компоненти SpriteRenderer які знаходяться в об'єкті. Шукаємо в масиві sprites спрайт по імені і присвоюємо його спрайту компонента SpriteRenderer, якщо такий існує. Завершує все Resources.UnloadUnusedAssets (), цей метод вивантажує з пам'яті невживані ассеты.

Тут знаходиться скрипт
using UnityEngine;
using System.Collections;
using System;

public class ConstObjectsQuality : MonoBehaviour {

public string spriteSheet;

private string qSuffix;

void Awake(){
qSuffix = GetQuality ();
ManageQuality ();
}

private string GetQuality(){
int screenH = Screen.height;
print (screenH);
if (screenH > 1440)
return "4x";
else if (screenH < 720)
return "1x";
else
return "2x";
}


private void ManageQuality(){

if (qSuffix == "1x" || qSuffix == "4x") {

Sprite[] sprites = Resources.LoadAll<Sprite>(spriteSheet + "@" + qSuffix);

if (sprites != null) {
SpriteRenderer[] renderers = GetComponentsInChildren<SpriteRenderer>(true);

if (renderers.Length > 0) {

foreach (SpriteRenderer r in renderers)
{
if (r.name != null){
string spriteName = r.sprite.name;
Sprite newSprite = Array.Find(sprites, item => item.name == spriteName);

if (newSprite)
r.sprite = newSprite;
}
}
}
}
}

Resources.UnloadUnusedAssets ();

}

}


Також цей скрипт можна використовувати для зміни всіх спрайтів в сцені. Для цього створюємо новий об'єкт, наприклад SpriteManager, і додаємо до нього даний скрипт, але із зміненим визначенням масиву renderers:

SpriteRenderer[] renderers = GameObject.FindObjectsOfType<SpriteRenderer>();

Спасибі за увагу, сподіваюся стаття була вам корисна.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.