パハットノート

主にUnity(C#)を中心としたプログラムの備忘録

Unity SpriteEditorでの画像分割を自動化





はじめに

以前の記事でSpriteEditorを利用した画像の分割方法についてまとめました。
しかし、この処理は

  1. 画像ファイルのインポート設定(Sprite Modeの変更など)
  2. SpriteEditorでの分割方法の指定
  3. 変更を適用

とする必要があり、何度も行うのは面倒です。
そこで、この処理を自動化する方法を考えました。

SpriteEditorの基本的な使い方はこちら
kiironomidori.hatenablog.com




スクリプト

EditorWindowを用いてこれらの処理を実現することにしました。
Grid By Cell Size」と「Grid By Cell Count」による分割を自動で行います。

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class AutoSpriteSlicer : EditorWindow
{
    public enum SliceType
    {
        CellSize,
        CellCount
    }

    [SerializeField] List<Texture2D> srcs;//画像
    [SerializeField] int spritePixelsPerUnit;//unity上での長さ1に対応するピクセル数
    [SerializeField] SliceType sliceType;//スライスの方法
    [SerializeField] int row, column;//行数と列数
    [SerializeField] Vector2Int pixelSize;//ピクセルの幅

    //ウィンドウの生成
    [MenuItem("エディタ拡張/SpriteEditorの処理の自動化")]
    static void Init()
    {
        var window = (AutoSpriteSlicer)GetWindow(typeof(AutoSpriteSlicer));
        window.Show();
    }

    private void OnGUI()
    {
        var so = new SerializedObject(this);
        so.Update();

        //Textureを取得
        EditorGUILayout.PropertyField(so.FindProperty("srcs"), true);
        spritePixelsPerUnit = EditorGUILayout.IntField("1単位に対応するピクセル数", spritePixelsPerUnit);

        //分割
        if (srcs != null)
        {
            //分割の種類
            sliceType = (SliceType)EditorGUILayout.EnumPopup("分割の種類", sliceType);

            //スライスタイプにより設定するパラメータを設定
            switch (sliceType)
            {
                //分割数より指定
                case SliceType.CellCount:
                    row = EditorGUILayout.IntField("行数", row);
                    column = EditorGUILayout.IntField("列数", column);
                    break;
                //セルサイズより指定
                case SliceType.CellSize:
                    pixelSize = EditorGUILayout.Vector2IntField("セルサイズ", pixelSize);
                    break;
            }

            //押したら分割をする
            if (GUILayout.Button("分割"))
            {
                Slice();
            }
        }

        //変更をセーブ
        so.ApplyModifiedProperties();
    }

    //分割のための関数
    void Slice()
    {
        //各画像に対して処理
        foreach (var src in srcs)
        {
            //設定していないもう1つのパラメータを計算
            switch (sliceType)
            {
                //セルサイズで分割
                case SliceType.CellSize:
                    row = src.height / pixelSize.y;
                    column = src.width / pixelSize.x;
                    break;

                //分割数を指定
                case SliceType.CellCount:
                    pixelSize.x = src.width / column;
                    pixelSize.y = src.height / row;
                    break;
            }

            //srcのパスとからインポート設定を取得
            string path = AssetDatabase.GetAssetPath(src);
            TextureImporter tI = AssetImporter.GetAtPath(path) as TextureImporter;

            //テスクチャインポートプロパティを編集
            tI.spritePixelsPerUnit = spritePixelsPerUnit;//16ピクセルで1マス
            tI.spriteImportMode = SpriteImportMode.Multiple;
            tI.filterMode = FilterMode.Point;
            tI.textureCompression = TextureImporterCompression.Uncompressed;

            //ループで分割
            var datas = new SpriteMetaData[row * column];
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < column; j++)
                {
                    int index = i * column + j;
                    int x = j * pixelSize.x;
                    int y = src.height - (i + 1) * pixelSize.y;
                    Rect rect = new Rect(new Vector2(x, y), pixelSize);

                    datas[index] = new SpriteMetaData()
                    {
                        name = $"{src.name}_{index}",
                        rect = rect
                    };
                }

            }
            tI.spritesheet = datas;

            AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
        }
    }
}





使用例

①. pngファイルを用意
sample1.png


sample2.png


②. 設定&実行
今回は100×100ピクセルで分割するので、先ほどの画像をアセットに追加したら次のように設定を行う。
設定が完了したら「分割」ボタンを押す。


③. 確認
実行したら画像のインポート設定が次のように変化している(sample2も同様。また、今回はspritePixelsPerUnitを100としたため一見変化していないがプログラムでの変更している)。


また、分割も次のようにされている。


④. 補足(分割数を指定する場合)
先ほどはピクセル数を指定して分割したが分割数を指定する場合の方法も紹介。
先ほどはsample1は2行3列、sample2は2行2列で分割していたため次のように設定すればsample1を先ほどと同様に分割できる。