Unityの標準機能だけでTexturePackerを作ってテクスチャアトラスを用意する


# 動作環境
- Windows10
- Unity2018.4.22f1

### 記事の作成にあたり使用したアセット（無料）
Asset Storeから[Sunny Land](https://assetstore.unity.com/packages/2d/characters/sunny-land-103349)という2Dのプレイヤー画像を使用させていただきました。
![0.PackingTargets.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96676/8d88659f-0471-fa10-d5e9-83866b828ad2.jpeg)
こちらのかわいい複数枚のキツネをUnityの標準機能だけで**テクスチャアトラス**にします。

### 処理を始める前に…
画像をパックする前に対象となるテクスチャアセットの`Read/Write Enabled`にチェックを入れておく必要があります。
この項目にチェックが入っていないとTexture2D 関数からテクスチャデータにアクセスができないので画像をパックできません。
![2.Checkit.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96676/3c834674-3959-5b2d-c611-fad6d442c205.jpeg)



# 実装内容
```` TexturePacker.cs
    private static void Pack(string filename, Texture2D[] resources, int maxsize)
    {
        // 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. 複数枚の画像を１つにパックする
動的に画像を生成して**PackTextures**関数にTexture2D 配列を渡すことで自動的にパックしてくれます。
ただ、ここまでだと１枚の画像を作っただけです。テクスチャアトラスとして使うためには戻り値のRect型が必要になります。
![1.PackingTexture.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96676/69df7baa-97b5-bd03-9d13-c08c36314d3e.jpeg)


### 2. SpriteのMultiple設定をパックした画像から作成
画像をMultipleに設定することでパックした画像の配置とサイズを設定できます。
そのために**SpriteMetaData**クラスへPackTextures関数から返ってきたRect型の情報を割り当てて配列を用意しておきます。


### 3. 作成した情報をもとに画像をアトラス化
ここからがパックした画像をアトラス化する方法です。
まず**TextureImporter**クラスで生成したパック画像をエディターで読み込みます。
※画像を読み込むために**AssetDatabase.ImportAsset**関数で画像を生成した後にインポートしておく必要があります。
読み込むことができたら`Texture Type`をSpriteに、`Sprite Mode`をMultipleにします。
最後に、用意しておいたSpriteMetaData型の配列をspritesheetに設定したら完成です。
![3.TextureAtlas.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96676/6993b036-cb25-3420-0631-52c2596551dc.jpeg)

# おわりに
Unityの標準機能だけでテクスチャアトラスを用意することができました。
ここまでならTexturePackerを使わなくてもいいのでは？とも思われそうですが、Unityで画像を作成するからこそ発生するデメリットがあります。
そのデメリットとは**Texture2Dで指定できる最大サイズが限定的なので、必ず画像に余白ができる**ことです。
![x32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96676/73a298bf-819d-53e7-cc51-fc56714f9b69.jpeg)
PackingTexture関数が画像をパッキングするタイミングで自動的に**32のべき乗**のサイズが設定されます。
その点、TexturePackerを使うと画像サイズは最適化されて余白が生まれません。
Unityを使用しないプロジェクトであればTexturePackerだけでいいのかもしれないですね。