パープルハット

※当サイトではGoogleアドセンス広告を利用しています

【Unity】SpriteEditorによる画像分割(手動&自動)



手動でのやり方

1. 画像ファイルの準備

手順1

  • 画像を用意します。

画像1

手順2

  • 使用する画像をプロジェクトにインポートしたら、インスペクター上でSpriteModeを「Multiple」に変更します。
  • 設定したら「Apply」ボタンを押して設定を適用させます。

SpriteModeをMultipleに変更


2. SpriteEditor上の設定

手順1

先ほどのインスペクターの画面から「Sprite Editor」をクリックしてSprite Editorを開きます。

手順2

SpriteEditor上で、「Slice」をクリックしたら「Type」を「Grid By Cell Count」に変更します。「Type」による分割方法の違いは下の表に示します。

Automatic 画像から判断して自動で分割をします
Grid By Cell Size 分割後の1枚ごとの画像のサイズをピクセル単位で指定します
Grid By Cell Count 縦と横にそれぞれ何分割するか設定して分割


手順3

「Column & Row」の「C」と「R」をそれぞれ2にして、「Slice」をクリックします。設定が完了したら、SpriteEditorの右上にある「Apply」ボタンを押して設定を適用。
CとRを2にしてSlick

確認

正しく処理されていればインポートした画像がアセット内でこのように表示されます。
分割結果






自動化

0. 概要

  • SpriteEditorは確かに便利ですが、画像ファイルのインポート設定(Sprite Modeの変更など)・分割方法の指定など地味にやることが多いです。
  • そこで、スクリプトを使って「Grid By Cell Size」と「Grid By Cell Count」による分割をある程度自動化してみました。
  • ↓↓参考サイト

Unity公式フォーラム「Editor script to slice sprites」
Unity公式ドキュメント「EditorGUILayout.EnumPopup」


1. 画像を用意

sample1.png sample2.png
自動画像1 自動画像2



2. スクリプトの準備

  • 今回はEditorWindowを使います。

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);
        }
    }
}



3. 実行

設定

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

自動化設定

確認

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

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


4. 補足(分割数を指定する場合)

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