動作環境
- Windows10
- Unity2018.4.22f1
記事の作成にあたり使用したアセット(無料)
Asset StoreからSunny Landという2Dのプレイヤー画像を使用させていただきました。
こちらのかわいい複数枚のキツネをUnityの標準機能だけでテクスチャアトラスにします。
処理を始める前に…
画像をパックする前に対象となるテクスチャアセットのRead/Write Enabled
にチェックを入れておく必要があります。
この項目にチェックが入っていないとTexture2D 関数からテクスチャデータにアクセスができないので画像をパックできません。
実装内容
private static void Pack(string filename, Texture2D[] resources, int maxsize)
{
// 1.複数枚の画像を1つにパックする
var texture = new Texture2D(maxsize, maxsize, TextureFormat.RGBA32, false);
var rect = texture.PackTextures(resources, 4, maxsize, false);
File.WriteAllBytes(Application.dataPath + filename, texture.EncodeToPNG());
AssetDatabase.ImportAsset("Assets" + filename);
// 2.SpriteのMultiple設定をパックした画像から作成
var spritesheets = new List<SpriteMetaData>();
for (var index = 0; index < resources.Length; index++)
{
var data = new SpriteMetaData();
data.name = resources[index].name;
var x = rect[index].x * texture.width;
var y = rect[index].y * texture.height;
var w = rect[index].width * texture.width;
var h = rect[index].height * texture.height;
data.rect = new Rect(x, y, w, h);
spritesheets.Add(data);
}
// 3.作成した情報をもとに画像をAtlas化
var importer = AssetImporter.GetAtPath("Assets" + filename) as TextureImporter;
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Multiple;
importer.spritesheet = spritesheets.ToArray();
AssetDatabase.ImportAsset("Assets" + filename);
}
解説
1. 複数枚の画像を1つにパックする
動的に画像を生成してPackTextures関数にTexture2D 配列を渡すことで自動的にパックしてくれます。
ただ、ここまでだと1枚の画像を作っただけです。テクスチャアトラスとして使うためには戻り値のRect型が必要になります。
2. SpriteのMultiple設定をパックした画像から作成
画像をMultipleに設定することでパックした画像の配置とサイズを設定できます。
そのためにSpriteMetaDataクラスへPackTextures関数から返ってきたRect型の情報を割り当てて配列を用意しておきます。
3. 作成した情報をもとに画像をアトラス化
ここからがパックした画像をアトラス化する方法です。
まずTextureImporterクラスで生成したパック画像をエディターで読み込みます。
※画像を読み込むためにAssetDatabase.ImportAsset関数で画像を生成した後にインポートしておく必要があります。
読み込むことができたらTexture Type
をSpriteに、Sprite Mode
をMultipleにします。
最後に、用意しておいたSpriteMetaData型の配列をspritesheetに設定したら完成です。
おわりに
Unityの標準機能だけでテクスチャアトラスを用意することができました。
ここまでならTexturePackerを使わなくてもいいのでは?とも思われそうですが、Unityで画像を作成するからこそ発生するデメリットがあります。
そのデメリットとはTexture2Dで指定できる最大サイズが限定的なので、必ず画像に余白ができることです。
PackingTexture関数が画像をパッキングするタイミングで自動的に32のべき乗のサイズが設定されます。
その点、TexturePackerを使うと画像サイズは最適化されて余白が生まれません。
Unityを使用しないプロジェクトであればTexturePackerだけでいいのかもしれないですね。