【Unity】テクスチャを縦横に切って個別に保存する

DEVELOP, Unity

アセットストアで購入した テクスチャなんかを、一部のデータだけ使いたくてファイル単位で分けたい時があります。Editor のツールを作って実現してみます。

目次

参照

【Unity】テクスチャを分割して個別に保存する – setchi’s blog

今回のツールはこちらで公開されているスクリプトを参照した上で、Editor のツールとして実行できる様にした版です。

スクリプト

Editor フォルダに以下スクリプトを作成、配置してください。

using System.IO;
using UnityEngine;
using UnityEditor;
 
/// <summary>
/// テクスチャを縦横に切って個別に保存する
/// </summary>
public class TextureSlicer : EditorWindow
{
    Texture2D texture;
    int horizontalSlices;
    int verticalSlices;
 
    int partWidth;
    int partHeight;
 
    [MenuItem("Tools/TextureSlicer")]
    static void Open()
    {
        var window = EditorWindow.GetWindow<TextureSlicer>();
        window.Show();
    }
 
    /// <summary>
    ///  GUI更新
    /// </summary>
    void OnGUI()
    {
        EditorGUILayout.LabelField("Textureを分割し個別に保存します。");
 
        texture = EditorGUILayout.ObjectField("target Texture", texture, typeof(Texture2D), true) as Texture2D;
        horizontalSlices = EditorGUILayout.IntField("horizontalSlices", horizontalSlices);
        verticalSlices = EditorGUILayout.IntField("verticalSlices", horizontalSlices);
 
        if (horizontalSlices == 0 || verticalSlices == 0)
        {
            return;
        }
 
        if (GUILayout.Button("Go Slice"))
        {
            var assetPath = AssetDatabase.GetAssetPath(texture);
            var dirPath = System.IO.Path.GetDirectoryName(assetPath);
            var fileNamePath = System.IO.Path.GetFileNameWithoutExtension(assetPath);
 
            partWidth = texture.width / horizontalSlices;
            partHeight = texture.height / verticalSlices;
            var fileNameIndex = 0;
 
            for (var partY = verticalSlices; partY > 0; partY--)
            {
                for (var partX = 0; partX < horizontalSlices; partX++)
                {
                    // 保存
                    var savePath = string.Format("{0}\\{1}{2}.png", dirPath, fileNamePath, fileNameIndex);
 
                    // 分割した一枚分のピクセル取得
                    var partPixels = ReadPartPixels(partX, partY, texture);
 
                    // 描き込み
                    var partTexture = new Texture2D(partWidth, partHeight, TextureFormat.RGBA32, false);
                    partTexture.SetPixels(partPixels);
                    partTexture.Apply();
 
                    SaveBinaryToLocal(savePath, partTexture.EncodeToPNG());
                    AssetDatabase.ImportAsset(savePath);
                    AssetDatabase.SaveAssets();
 
                    fileNameIndex++;
                }
            }
        }
    }
 
    Color[] ReadPartPixels(int partX, int partY, Texture2D texture)
    {
        var pixels = new Color[partWidth * partHeight];
        var offsetX = partX * partWidth;
        var offsetY = partY * partHeight;
 
        for (int y = offsetY, y_ = partHeight - 1; y > offsetY - partHeight; y--, y_--)
        {
            for (int x = offsetX, x_ = 0; x < offsetX + partWidth; x++, x_++)
            {
                pixels[y_ * partWidth + x_] = texture.GetPixel(x, y);
            }
        }
 
        return pixels;
    }
 
    void SaveBinaryToLocal(string path, byte[] binaryData)
    {
        var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
        var binaryWriter = new BinaryWriter(fileStream);
 
        binaryWriter.Write(binaryData);
 
        binaryWriter.Close();
        fileStream.Close();
    }
}

使い方

  • target Texture に分割したいテクスチャをセットする。
    • セットしたテクスチャのReasd/Write Enabled は有効に変更しておく。
  • horizontalSlices に横の分割数を指定
  • verticalSlices に縦の分割数を指定
  • Go Slice で実行

結果

設定したテクスチャと同じディレクトリに個別にテクスチャが作成されます。

Posted by kazupon