Pull to refresh

Comments 10

Читал, что спрайты из Resources не попадают в автоматически генерируемые текстурные атласы — что вызывает создание нескольких текстур, а каждая новая текстура — это дополнительный Draw Call. Просветите, кто в курсе, так ли это?
Протестировал у себя в игре. После загрузки спрайтов из Resources количество Draw Calls не меняется.
Вот статистика с 2х(hd) текстурами, которые не загружаются из Resources:



А вот 4х(ultra-hd) которые подгружались из Resources



Разное количество сохраненных тестур батчингом показывает, потому что некоторые текстуры и объекты work in progress.
Вопрос?
А если таких атласов будет ну скажем 5, учитывая HD SD MD все это хранить в билде немного увеличит размер.(загрузку с интернета откинем)
Как вариант хранить одни лист HD, потом его при первом запуске ужимать, пересчитывать текстуры и использовать (ну и сохранить, что бы не повторять)
(в unityне профессионал но интересно ваше мнение ?)
Спасибо за статью. Я некоторое время назад делал ассет для Unity, который грузит разные сцены в зависимости от разрешения экрана.

Для этого тоже используются суффиксы (у файлов сцены), но вида ".1024x768", плюс еще генерируется xml со списком сцен (так как в рантайме список получить проблематично). Алгоритм выбора у меня посложнее, если интересно, то можно посмотреть на github (много кода).

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

В общем, Вы меня заставили задуматься о добавлении нового функционала к моему проекту :-)
Интересный подход, я бы о таком даже и не подумал. К сожалению, приходится делать много ненужной механической работы.
Но вот я думал, что замена спрайтов в рантайме это довольно таки дорогая для производительности операция, оказылось, что она проходит без заметных глазу фризов даже на маломощных устройствах, если конечно количество объектов в сцене в пределах разумного.

Мне интересно как реализуется данная фича в 2d Toolkit.
А если брать простые 2д фреймфорки типо CoronaSDK или Cocos, то там спрайты же для разных разрешений грузятся сразу, без поиска и замены, потому что у них все пишется с кода. Такой подход тоже можно реализовать в unity, и я видел решения где-то на форуме официальном, но это не очень удобно для привычного рабочего процесса, т.к. нужно будет все спрайты удалять с объектов перед запуском или вообще создавать объекты с кода в рантайме. Вообщем мне от этого становится страшно:)
Просто до того, как писать этот ассет, я работал на проекте (довольно успешная мобильная игра, но не на Unity), где было пять версий сцен для разных разрешений. Именно версий, так как сцены различались кардинально: для телефонов это был портрет, для планшетов — ландшафт, разные элементы UI, + сам игровой процесс отличался, даже количество сцен было разным и т.п. Отсюда и растут уши.

К сожалению, приходится делать много ненужной механической работы.
А вот тут есть вариант перенести Ваш подход в скрипт редактора и совместить с моим. То есть, в редакторе по нажатию одной кнопочки будут заменяться текстуры в конкретной сцене (а то и сразу во всех, если их можно грузить из скриптов редактора), что ускорит создание версий. Можно было бы это сделать вообще автоматически, но, к сожалению, Unity не позволяет вызвать скрипт перед началом сборки (в Pro, вроде бы, можно).

… если конечно количество объектов в сцене в пределах разумного.
Если делать только для себя, то, я согласен, что такой подход более чем оправдан. Если же делать ассет, которым будут пользоваться другие люди, которые, предположительно, могут вообще быть не программистами, то уже нехорошо. Правда, можно оставлять в сцене всегда минимальные текстуры, а в рантайме менять их на нужные в корутине. Например, по десятку за кадр. Тогда и для больших сцен все может быть вполне окей.

Мне интересно как реализуется данная фича в 2d Toolkit.
С 2d toolkit я не работал, но, насколько я понимаю, у них сделан собственный компонент спрайта. Атласы текстур хранятся в ресурсах, также как у Вас, но при этом грузится всегда только нужный, как в кокосе. Правда, я могу и ошибаться. Подобная идея мне не очень нравится, так как в Unity уже есть вполне приличный спрайт, которым люди пользуются, в том числе и я.
… где было пять версий сцен для разных разрешений...

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

Unity не позволяет вызвать скрипт перед началом сборки (в Pro, вроде бы, можно).

Насколько я знаю, в Unity API ограниченные возможности по пре/после-процессингу билда. Не очень компетентен я в этой сфере, но что-то можно сделать через BuildPipeline, где можно управлять процессом упаковки.

А еще можно запускать скрипты прямо в редакторе Running Editor Script Code on Launch, ExecuteInEditMode

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

Неплохое решение.

Кстати, есть еще решение для свапинга атласа спрайтов с помощью NGUI, нашел я его на lynda.com, но я думаю в интернете это где-то гуляет.
Насколько я знаю, в Unity API ограниченные возможности по пре/после-процессингу билда.
Я разбирался как раз для этого ассета, там ситуация такая: пост-процессинг есть и работает во free версии. Есть два его варианта, один (PostProcessSceneAttribute) срабатывает при запуске сцены в редакторе (почему-то после Awake), и я его использую в своем ассете, чтобы пересобирать xml со списком сцен. А второй вариант — после билда (PostProcessBuildAttribute). И его у меня использовать не получается, так как собранный билд уже проблематично переделывать, особенно, если это apk или ipa. Поэтому пришлось добавить пункт меню, чтобы вручную пересоздавать xml.

В BuildPipeline метод BuildPlayer, к сожалению, pro-only. Кроме того, как я понимаю, это обходной путь, чтобы создавать собственную последовательность сборки и для нее нужно делать отдельную кнопку или пункт меню. А стандартный билд по-прежнему будет собираться, как и раньше. Думал, может у них что-то поприличнее сделано, но вроде нет.

Выполнение скриптов в редакторе тоже не спасет, так как они выполняются иначе, чем в рантайме (например, Update вызывается только при изменении сцены).

А вот зато можно написать скрипт редактора для SpriteRenderer. Например, вот такой скрипт не дает изменить спрайт:
Код
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(SpriteRenderer))]
public class SpriteRendererEditor : Editor
{
	Sprite _oldSprite;

	void OnEnable()
	{
		var sr = (SpriteRenderer)target;
		_oldSprite = sr.sprite;
	}

	public override void OnInspectorGUI ()
	{
		var sr = (SpriteRenderer)target;
		DrawDefaultInspector ();
		if (_oldSprite != null && sr.sprite != _oldSprite)
			sr.sprite = _oldSprite;
	}
}

Таким макаром мы можем отлавливать момент установки пользователем текстуры. А зная, в каком разрешении сцена, можно сразу текстуру поменять. К сожалению, это не покрывает use case'ы, когда пользователь изменяет разрешение сцены или когда он сначала сделал сцену, а потом добавил текстуры для других разрешений. То есть, все равно придется делать кнопку, которую нужно нажать перед билдом.

А еще, кстати, есть префабы, и это вообще отдельный разговор…

Кстати, есть еще решение для свапинга атласа спрайтов с помощью NGUI, нашел я его на lynda.com, но я думаю в интернете это где-то гуляет.
Я так думаю, Вы об этом. Идея вроде бы та же, что и у Вас, меняются атласы в рантайме, но только средствами NGUI.
Спасибо, недавно только начал осваиваться с Unity и думал, что все это Unity делает автоматически. Думал, что просто кидаешь в самом большом разрешение а Unity сам подготавливает в зависимости от размера сцены
Sign up to leave a comment.

Articles