Всем привет. Глубоко извиняюсь, что забросил свой блог. Руки дошли все же написать что-нибудь полезное за эти пару свободных часов, поэтому минимум воды и перейдем сразу к сути заметки. Поехали!
Все кто щупал Unity 4.3 или выше, наверняка, заметили мощнейшие возможности работы как с одиночными спрайтами, так и с атласами спрайтов. Unity позволяет атлас разбивать на спрайты как вручную, так и в автоматическом режиме, а еще разбивать по сетке с различными настройками разбиения. Казалось бы этого вполне достаточно для работы с набором спрайтов записанных в одну текстуру, но на этом не все! Есть и более тонкие возможности работы с этим делом, правда без кода тут не обойтись. Я говорю об автоматическом разбиении атласа, согласно вашему упаковщику атласов, дабы сохранились его настройки координат и именования спрайтов. Тонкости парсинга того или иного упаковщика атласов я рассматривать не буду, это реализовать сможет каждый желающий. А так же нюансы разворота текстур в атласе даже не берусь затрагивать ибо в Unity это не сработает со стандартными спрайтами(есть много других решений).
Создадим класс, хранящий информацию о расположении спрайта в атласе. Что-то подобное этому. Только не стоит упираться в сию реализацию, каждый должен его делать по своему усмотрению. В моем примере класс хранит координаты прямоугольника спрайта и его имя, а так же имеет ужасный конструктор и две функции возвращающие этот прямоугольник и имя.

Все вопросы, замечания, комментарии и предложения направлять в комментарии или лично в соц.сети или скайп.
Все кто щупал Unity 4.3 или выше, наверняка, заметили мощнейшие возможности работы как с одиночными спрайтами, так и с атласами спрайтов. Unity позволяет атлас разбивать на спрайты как вручную, так и в автоматическом режиме, а еще разбивать по сетке с различными настройками разбиения. Казалось бы этого вполне достаточно для работы с набором спрайтов записанных в одну текстуру, но на этом не все! Есть и более тонкие возможности работы с этим делом, правда без кода тут не обойтись. Я говорю об автоматическом разбиении атласа, согласно вашему упаковщику атласов, дабы сохранились его настройки координат и именования спрайтов. Тонкости парсинга того или иного упаковщика атласов я рассматривать не буду, это реализовать сможет каждый желающий. А так же нюансы разворота текстур в атласе даже не берусь затрагивать ибо в Unity это не сработает со стандартными спрайтами(есть много других решений).
Создадим класс, хранящий информацию о расположении спрайта в атласе. Что-то подобное этому. Только не стоит упираться в сию реализацию, каждый должен его делать по своему усмотрению. В моем примере класс хранит координаты прямоугольника спрайта и его имя, а так же имеет ужасный конструктор и две функции возвращающие этот прямоугольник и имя.
public class SpriteData
{
private string name_;
private int x_, y_, w_, h_;
public SpriteData(string name, int x, int y, int w, int h)
{
name_ = name;
x_ = x;
y_ = y;
w_ = w;
h_ = h;
}
public Rect GetRect()
{
return new Rect(x_, y_, w_, h_);
}
public string GetName()
{
return name_;
}
}
Идем дальше! Ниже представлен рабочий код, нюансы, которого описаны в коментариях к коду.
using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
// я использую кастомное окошко, можно реализовать, как команду контекстного меню
public class SpritePacker : EditorWindow
{
// наш атлас со спрайтами
private Texture2D texture_;
// текстовый файл информации о расположении спрайтов
// обычно упаковщики их генерируют в том или ином виде
private TextAsset atlas_;
// массивчик данных спрайтов в который будем парсить координаты и прочее
private static List<SpriteData> data_ = new List<SpriteData>();
[MenuItem("Unity2D/Sprite packer")]
static void GenerateAtlas()
{
var window = ScriptableObject.CreateInstance<SpritePacker>();
window.Show ();
}
private void OnGUI()
{
texture_ = (Texture2D)EditorGUILayout.ObjectField(
"Atlas texture:", texture_, typeof(Texture2D), true);
atlas_ = (TextAsset)EditorGUILayout.ObjectField(
"Atlas info:", atlas_, typeof(TextAsset), true);
if(GUILayout.Button("Generate atlas"))
{
string path = AssetDatabase.GetAssetPath(texture_);
List<SpriteMetaData> sprites = Parse(atlas_, texture_.height);
// Ранее я рассказывал, что такое TextureImporter и как это дело юзать
TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
textureImporter.spritesheet = sprites.ToArray();
textureImporter.textureType = TextureImporterType.Sprite;
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
}
}
private static List<SpriteMetaData> Parse(TextAsset text, int height)
{
using (StringReader reader = new StringReader(text.text))
{
ParseAtlasInfo(text);
List<SpriteMetaData> spriteAtlas = new List<SpriteMetaData>();
foreach(SpriteData spr in data_)
{
SpriteMetaData smd = new SpriteMetaData();
smd.name = spr.GetName();
Rect r = spr.GetRect();
smd.rect = new Rect(r.x, height - r.y - r.height, r.width, r.height);
smd.pivot = Vector2.zero;
// выбор пивота спрайта в данном случае по центу
smd.alignment = 1;
spriteAtlas.Add(smd);
}
data_.Clear();
return spriteAtlas;
}
}
// мой парсер недописанный читает атласы сгенерированные программой
// Cheetah Texture Packer - http://www.gamedev.ru/projects/forum/?id=161714
private static void ParseAtlasInfo(TextAsset text)
{
using (StringReader reader = new StringReader(text.text))
{
reader.ReadLine();
while (true)
{
string line = reader.ReadLine();
if (line != null)
{
string[] sprData = line.Split(new char[]{' ', '\t'});
string[] name = sprData[0].Split ('.');
SpriteData sprite = new SpriteData(
name[0],
int.Parse(sprData[1]),
int.Parse(sprData[2]),
int.Parse(sprData[3]),
int.Parse(sprData[4])
);
data_.Add(sprite);
}
else
break;
}
}
}
}
Ну вот и все! В итоге получаем небольшую утилиту подобную этой:
Все вопросы, замечания, комментарии и предложения направлять в комментарии или лично в соц.сети или скайп.
Комментариев нет:
Отправить комментарий