四回目の投稿です。よろしくお願いします。
目次
概要
以下のような、指定した圧縮率でテクスチャをCrunch圧縮するEditorWindowの作成方法を解説します :
Crunch圧縮について
Crunch圧縮は圧縮形式のことで、解凍が早く、ロード時間にほとんど影響を与えないため、アプリ容量が削減できるということで、公式が積極的な使用を推奨しています。
使用方法
まずは、外観を把握するという意味でも、使用方法を説明します。作成方法に興味のない方は、ここを読むことで使用できるようになっています。
1. 下記スクリプトを作成し、"Editor"フォルダ内に入れる :
TextureCrunchCompressTool.cs (tap)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TextureCrunchCompressTool : EditorWindow
{
private const int MinCompressionRate = 0;
private const int MaxCompressionRate = 100;
private static readonly string[] TextureExtensions = new string[] { ".png", ".jpg" }; // 対象としたい画像の拡張子
private readonly List<Texture> compressedTextures = new List<Texture>(); // 圧縮した画像たち
private Vector2 scrollValueForDrawCrunchCompressedGUI;
[Range(MinCompressionRate, MaxCompressionRate)]
private int currentCompressionRate = 50;
private bool isCompressed;
private bool isOpenFoldoutForDrawCrunchCompressedGUI;
[MenuItem("Tools/Texture Crunch Compress Tool")]
public static void OpenEditorWindow()
{
GetWindow<TextureCrunchCompressTool>("テクスチャの圧縮ツール");
}
private void OnEnable()
{
Initialize();
}
/// <summary>
/// 初期化処理
/// </summary>
private void Initialize()
{
compressedTextures.Clear();
scrollValueForDrawCrunchCompressedGUI = Vector2.zero;
isCompressed = false;
isOpenFoldoutForDrawCrunchCompressedGUI = false;
}
private void OnGUI()
{
DrawCrunchCompressionSettingGUI();
GUILayout.Space(5);
if (isCompressed) // 圧縮を実行するまで表示しない
{
DrawCrunchCompressedGUI();
}
}
/// <summary>
/// 圧縮に関する設定画面の描画
/// </summary>
private void DrawCrunchCompressionSettingGUI()
{
GUILayout.Label("[概要]\n" +
"テクスチャを指定した圧縮率に圧縮します。");
GUILayout.Space(5);
currentCompressionRate = EditorGUILayout.IntSlider("圧縮率 : ", currentCompressionRate, MinCompressionRate, MaxCompressionRate);
GUILayout.Space(5);
if (GUILayout.Button("Crunch圧縮を実行"))
{
Initialize();
ExecuteCrunchCompress();
isCompressed = true;
}
}
/// <summary>
/// Crunch圧縮を実行
/// </summary>
private void ExecuteCrunchCompress()
{
var paths = GetAllTexturePath("Assets"); // "Assets"下にある画像をすべて取得
foreach (var path in paths)
{
var impoter = (TextureImporter)AssetImporter.GetAtPath(path); // 画像設定を変更するためにAssetImporterを使用
if (impoter.crunchedCompression && impoter.compressionQuality == currentCompressionRate) { continue; } // 未圧縮なら、圧縮する
var texture = (Texture)AssetDatabase.LoadAssetAtPath(path, typeof(Texture)); // テクスチャの取得
compressedTextures.Add(texture);
impoter.crunchedCompression = true; // use crunch compressを有効化
impoter.compressionQuality = currentCompressionRate; // 圧縮率の設定
AssetDatabase.ImportAsset(path); // 変更を適用
}
}
/// <summary>
/// 特定のフォルダ下にあるTextureのパスをすべて取得 (検索 -> guid取得 -> パス取得)
/// </summary>
private static List<string> GetAllTexturePath(string rootFolder)
{
var guids = AssetDatabase.FindAssets("t:Texture", new string[] { rootFolder }); // "rootFolder"フォルダ下の全てのTextureのGUID
var assetPaths = new List<string>();
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid); // guid -> path
var isSubject = false;
foreach (var extension in TextureExtensions)
{
if (!path.Contains(extension)) { continue; } // 画像の拡張子が、対象となるものであるか?
isSubject = true;
}
if (!isSubject) { continue; }
assetPaths.Add(path);
}
return assetPaths;
}
/// <summary>
/// 圧縮した画像の一覧表示画面の描画
/// </summary>
private void DrawCrunchCompressedGUI()
{
if (compressedTextures.Count < 1)
{
GUILayout.Label("圧縮対象は存在しませんでした。");
return;
}
GUILayout.Label($"以下の対象に圧縮処理({currentCompressionRate}%)が適用されました : ");
isOpenFoldoutForDrawCrunchCompressedGUI = EditorGUILayout.Foldout(isOpenFoldoutForDrawCrunchCompressedGUI, $"対象一覧 [{compressedTextures.Count}]");
if (isOpenFoldoutForDrawCrunchCompressedGUI) // 折り畳みが開かれているなら、
{
scrollValueForDrawCrunchCompressedGUI = EditorGUILayout.BeginScrollView(scrollValueForDrawCrunchCompressedGUI);
foreach (var compressedTexture in compressedTextures) // すべての圧縮した画像に対し、
{
EditorGUILayout.ObjectField(compressedTexture, typeof(Texture), false); // 表示
}
EditorGUILayout.EndScrollView();
}
}
}
#endif
Editorフォルダについて
Unityにはフォルダ名によって識別される特殊なフォルダが存在する。その内の一つにEditorフォルダがある。そして、エディタースクリプトを"Editor"と名付けたフォルダ内に配置しなければ、それは動作しないのである。
(エディタースクリプト : UnityEditor名前空間に存在するクラス(EditorやEditorWindow、PropertyDrawerなど)を継承したスクリプト)
追記 : コード全体を"#if UNITY_EDITOR"と"#endif"で囲っている場合は、エディタフォルダに入れていなくても良い。
2. Unityエディタ上で"Tools/Texture Crunch Compress Tool"を選択する :
3. すると、下記EditorWindowが出現するので、圧縮率を指定し、"Crunch圧縮を実行"ボタンを押すと、Assets下にあるすべてのテクスチャに対して圧縮が実行される :
作業手順
1. Unityエディタ上からEditorWindowを開けるように実装
2. 圧縮実行に必要な最低限の描画処理の実装
3. Crunch圧縮処理の実装
4. Crunch圧縮したテクスチャ表示の描画処理の実装
実装方法
1. Unityエディタ上からEditorWindowを開けるように実装
以下のように、TextureCrunchCompressTool.csを作成し、Editorフォルダ内に配置する :
TextureCrunchCompressTool.cs (tap)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TextureCrunchCompressTool : EditorWindow
{
[MenuItem("Tools/Texture Crunch Compress Tool")]
public static void OpenEditorWindow()
{
GetWindow<TextureCrunchCompressTool>("テクスチャの圧縮ツール");
}
private void OnGUI() // 描画処理
{
}
}
#endif
ポイント:
- #if UNITY_EDITOR : Unityエディタ上でしか動作しないようにしている。
- MenuItem属性 : Unityエディタ上のToolsに項目を追加している。
- GetWindow() : EditorWindowを開けるようにしている。
2. 圧縮実行に必要な最低限の描画処理の実装
以下のように、TextureCrunchCompressTool.csに追記する :
TextureCrunchCompressTool.cs (tap)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TextureCrunchCompressTool : EditorWindow
{
+ private const int MinCompressionRate = 0;
+ private const int MaxCompressionRate = 100;
+ [Range(MinCompressionRate, MaxCompressionRate)]
+ private int currentCompressionRate = 50; // 設定中の圧縮率
[MenuItem("Tools/Texture Crunch Compress Tool")]
public static void OpenEditorWindow()
{
GetWindow<TextureCrunchCompressTool>("テクスチャの圧縮ツール");
}
private void OnGUI() // 描画処理
{
+ DrawCrunchCompressionSettingGUI();
}
+ /// <summary>
+ /// 圧縮に関する設定画面の描画
+ /// </summary>
+ private void DrawCrunchCompressionSettingGUI()
+ {
+ GUILayout.Label("[概要]\n" +
+ "テクスチャを指定した圧縮率に圧縮します。");
+
+ GUILayout.Space(5);
+
+ currentCompressionRate = EditorGUILayout.IntSlider("圧縮率 : ", currentCompressionRate, MinCompressionRate, MaxCompressionRate);
+
+ GUILayout.Space(5);
+
+ if (GUILayout.Button("Crunch圧縮を実行"))
+ {
+ // Crunch圧縮を実行
+ }
+ }
}
#endif
ポイント:
- Range属性 : currentCompressionRateの範囲を制限
- EditorGUILayout.IntSlider() : 圧縮率を設定するスライダーを実装
- GUILayout.Button() : 圧縮処理を実行できるようにしている。
3. Crunch圧縮処理の実装
以下のように、TextureCrunchCompressTool.csに追記する :
TextureCrunchCompressTool.cs (tap)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TextureCrunchCompressTool : EditorWindow
{
private const int MinCompressionRate = 0;
private const int MaxCompressionRate = 100;
+ private static readonly string[] TextureExtensions = new string[] { ".png", ".jpg" }; // 対象としたい画像の拡張子
[Range(MinCompressionRate, MaxCompressionRate)]
private int currentCompressionRate = 50; // 設定中の圧縮率
[MenuItem("Tools/Texture Crunch Compress Tool")]
public static void OpenEditorWindow()
{
GetWindow<TextureCrunchCompressTool>("テクスチャの圧縮ツール");
}
private void OnGUI() // 描画処理
{
DrawCrunchCompressionSettingGUI();
}
/// <summary>
/// 圧縮に関する設定画面の描画
/// </summary>
private void DrawCrunchCompressionSettingGUI()
{
GUILayout.Label("[概要]\n" +
"テクスチャを指定した圧縮率に圧縮します。");
GUILayout.Space(5);
currentCompressionRate = EditorGUILayout.IntSlider("圧縮率 : ", currentCompressionRate, MinCompressionRate, MaxCompressionRate);
GUILayout.Space(5);
if (GUILayout.Button("Crunch圧縮を実行"))
{
+ ExecuteCrunchCompress();
}
}
+ /// <summary>
+ /// Crunch圧縮を実行
+ /// </summary>
+ private void ExecuteCrunchCompress()
+ {
+ var paths = GetAllTexturePath("Assets"); // "Assets"下にある画像をすべて取得
+ foreach (var path in paths)
+ {
+ var impoter = (TextureImporter)AssetImporter.GetAtPath(path); // 画像設定を変更するためにAssetImporterを使用
+ if (impoter.crunchedCompression && impoter.compressionQuality == currentCompressionRate) { continue; } // 未圧縮なら、圧縮する
+
+ impoter.crunchedCompression = true; // use crunch compressを有効化
+ impoter.compressionQuality = currentCompressionRate; // 圧縮率の設定
+ AssetDatabase.ImportAsset(path); // 変更を適用
+ }
+ }
+
+ /// <summary>
+ /// 特定のフォルダ下にあるTextureのパスをすべて取得 (検索 -> guid取得 -> パス取得)
+ /// </summary>
+ private static List<string> GetAllTexturePath(string rootFolder)
+ {
+ var guids = AssetDatabase.FindAssets("t:Texture", new string[] { rootFolder }); // "rootFolder"フォルダ下の全てのTextureのGUID
+ var assetPaths = new List<string>();
+ foreach (var guid in guids)
+ {
+ var path = AssetDatabase.GUIDToAssetPath(guid); // guid -> path
+ var isSubject = false;
+ foreach (var extension in TextureExtensions)
+ {
+ if (!path.Contains(extension)) { continue; } // 画像の拡張子が、対象となるものであるか?
+
+ isSubject = true;
+ }
+ if (!isSubject) { continue; }
+
+ assetPaths.Add(path);
+ }
+ return assetPaths;
+ }
}
#endif
ポイント:
- GetAllTexturePath("Assets") : Assets下に存在するすべてのテクスチャのパスを取得している。(例えば、引数を"Assets/Resources/Texture"にすると、そのフォルダより下にあるものにしか適用されなくなる)
- AssetDatabase.FindAssets() : filterを"t:Texture"とすることで、すべてのテスクチャを検索している。(Unityエディタ上のProjectウィンドウの検索欄に"t:Texture"と入力すると、すべてのテクスチャが表示される)
- TextureExtensions変数 : 拡張子を用いて適用範囲を制限している。
- アセットインポーターを用いることで、圧縮の設定を変更できるようにしている。
"Crunch圧縮を実行"ボタンを押し、適当なテクスチャを選択して、インスペクターを確認し、以下のようになっていれば成功 :
この時点で、テクスチャの圧縮の実装は完了しているが、利便性向上のため、圧縮が適用されたテクスチャを表示する描画処理を、以下で実装する。
4. Crunch圧縮したテクスチャ表示の描画処理の実装
以下のように、TextureCrunchCompressTool.csに追記する :
TextureCrunchCompressTool.cs (tap)
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class TextureCrunchCompressTool : EditorWindow
{
private const int MinCompressionRate = 0;
private const int MaxCompressionRate = 100;
private static readonly string[] TextureExtensions = new string[] { ".png", ".jpg" }; // 対象としたい画像の拡張子
+ private readonly List<Texture> compressedTextures = new List<Texture>(); // 圧縮した画像たち
+ private Vector2 scrollValueForDrawCrunchCompressedGUI;
[Range(MinCompressionRate, MaxCompressionRate)]
private int currentCompressionRate = 50; // 設定中の圧縮率
+ private bool isCompressed;
+ private bool isOpenFoldoutForDrawCrunchCompressedGUI;
[MenuItem("Tools/Texture Crunch Compress Tool")]
public static void OpenEditorWindow()
{
GetWindow<TextureCrunchCompressTool>("テクスチャの圧縮ツール");
}
+ private void OnEnable()
+ {
+ Initialize();
+ }
+
+ /// <summary>
+ /// 初期化処理
+ /// </summary>
+ private void Initialize()
+ {
+ compressedTextures.Clear();
+ scrollValueForDrawCrunchCompressedGUI = Vector2.zero;
+ isCompressed = false;
+ isOpenFoldoutForDrawCrunchCompressedGUI = false;
+ }
private void OnGUI() // 描画処理
{
DrawCrunchCompressionSettingGUI();
+
+ GUILayout.Space(5);
+
+ if (isCompressed) // 圧縮を実行するまで表示しない
+ {
+ DrawCrunchCompressedGUI();
+ }
}
/// <summary>
/// 圧縮に関する設定画面の描画
/// </summary>
private void DrawCrunchCompressionSettingGUI()
{
GUILayout.Label("[概要]\n" +
"テクスチャを指定した圧縮率に圧縮します。");
GUILayout.Space(5);
currentCompressionRate = EditorGUILayout.IntSlider("圧縮率 : ", currentCompressionRate, MinCompressionRate, MaxCompressionRate);
GUILayout.Space(5);
if (GUILayout.Button("Crunch圧縮を実行"))
{
+ Initialize();
ExecuteCrunchCompress();
+ isCompressed = true;
}
}
/// <summary>
/// Crunch圧縮を実行
/// </summary>
private void ExecuteCrunchCompress()
{
var paths = GetAllTexturePath("Assets"); // "Assets"下にある画像をすべて取得
foreach (var path in paths)
{
var impoter = (TextureImporter)AssetImporter.GetAtPath(path); // 画像設定を変更するためにAssetImporterを使用
if (impoter.crunchedCompression && impoter.compressionQuality == currentCompressionRate) { continue; } // 未圧縮なら、圧縮する
impoter.crunchedCompression = true; // use crunch compressを有効化
impoter.compressionQuality = currentCompressionRate; // 圧縮率の設定
AssetDatabase.ImportAsset(path); // 変更を適用
}
}
/// <summary>
/// 特定のフォルダ下にあるTextureのパスをすべて取得 (検索 -> guid取得 -> パス取得)
/// </summary>
private static List<string> GetAllTexturePath(string rootFolder)
{
var guids = AssetDatabase.FindAssets("t:Texture", new string[] { rootFolder }); // "rootFolder"フォルダ下の全てのTextureのGUID
var assetPaths = new List<string>();
foreach (var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid); // guid -> path
var isSubject = false;
foreach (var extension in TextureExtensions)
{
if (!path.Contains(extension)) { continue; } // 画像の拡張子が、対象となるものであるか?
isSubject = true;
}
if (!isSubject) { continue; }
assetPaths.Add(path);
}
return assetPaths;
}
+
+ /// <summary>
+ /// 圧縮した画像の一覧表示画面の描画
+ /// </summary>
+ private void DrawCrunchCompressedGUI()
+ {
+ if (compressedTextures.Count < 1)
+ {
+ GUILayout.Label("圧縮対象は存在しませんでした。");
+ return;
+ }
+ GUILayout.Label($"以下の対象に圧縮処理({currentCompressionRate}%)が適用されました : ");
+
+ isOpenFoldoutForDrawCrunchCompressedGUI = EditorGUILayout.Foldout(isOpenFoldoutForDrawCrunchCompressedGUI, $"対象一覧 [{compressedTextures.Count}]");
+ if (isOpenFoldoutForDrawCrunchCompressedGUI) // 折り畳みが開かれているなら、
+ {
+ scrollValueForDrawCrunchCompressedGUI = EditorGUILayout.BeginScrollView(scrollValueForDrawCrunchCompressedGUI);
+ foreach (var compressedTexture in compressedTextures) // すべての圧縮した画像に対し、
+ {
+ EditorGUILayout.ObjectField(compressedTexture, typeof(Texture), false); // 表示
+ }
+ EditorGUILayout.EndScrollView();
+ }
+ }
}
#endif
ポイント:
- isCompressed変数 : 圧縮処理が実行されるまで、結果を表示しないようにしている。
- EditorGUILayout.Foldout() : 対象一覧の表示を折りたためるようにしている。
- EditorGUILayout.BeginScrollView()とEditorGUILayout.EndScrollView() : 対象一覧をスクロールできるようにしている。
- EditorGUILayout.ObjectField() : 対象を表示している。
最後に
どうでしたか、わかりやすかったでしょうか。Crunch圧縮の設定自体は、個々のテクスチャのインスペクター上で設定できるが、個数が多いとかなり面倒なので、こういったエディタ拡張を作成できる能力は有用です。特に、ベイク時に生成されるライトマップは、基本的に個数が多いので、一つずつ適用していくのは骨が折れます。
また気が向いたら何か書きます。それでは。
宣伝 : CUPLEXという時間差アクションパズルゲームを作成しています。私は主にプログラムとプロジェクト管理を担当しています。よかったら、覗いてみてください↓
https://store.steampowered.com/app/2499100/CUPLEX/