SpriteAtlas作成時に圧縮設定を自動で適用する
SpriteAtlas作成時の圧縮設定を自動化します。
特にAndroid、iOSなどのモバイル向け設定を変更します。
背景
Unityではアセット作成時やインポート時にAssetPostprocessorを利用することでアセットの設定を自動で変えることができます。
TextureにはTextureImporter、3DモデルにはModelImporterといったAssetImporterが存在しており、簡単にインポート設定を変更することができます。
しかしSpriteAtlasにはImporterが存在しないため、一旦SerializeObjectとして読み込み、直接値を書き換えることで設定を反映させます。
今回は各プラットフォームの圧縮設定を変更します。
導入
下準備で圧縮設定やPacking設定などを適用済みのPreset用SpriteAtlasを Assets/Editor/DefaultSpriteAtlas.spriteatlas に作成しておきます。
次に以下のコードをEditorフォルダ以下に作成すればSpriteAtlas作成時に自動で設定が適用されます。
using System.Linq; using UnityEditor; using UnityEngine.U2D; /// <summary> /// SpriteAtlasのプラットフォーム圧縮設定を自動適用する /// </summary> public class SpriteAtlasPostprocessor : AssetPostprocessor { private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath) { // SpriteAtlasの変更のみ検知 var list = importedAssets.Where(c => c.EndsWith(".spriteatlas")).ToArray(); if (list.Length <= 0) return; // 設定をインポートするPreset用のSpriteAtlas var originAtlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>("Assets/Editor/DefaultSpriteAtlas.spriteatlas"); var originSetting = new SerializedObject(originAtlas).FindProperty("m_EditorData").FindPropertyRelative("platformSettings"); var originAndroid = originSetting.GetArrayElementAtIndex(0); var originiPhone = originSetting.GetArrayElementAtIndex(1); // 設定を適用 foreach (var path in list) { var atlas = AssetDatabase.LoadAssetAtPath<SpriteAtlas>(path); var serializedObject = new SerializedObject(atlas); var editorData = serializedObject.FindProperty("m_EditorData"); // platform設定 var platFormSettings = editorData.FindPropertyRelative("platformSettings"); // Android、iOSのみ設定を変えるのでarraySizeは2 platFormSettings.arraySize = 2; var targetAndroid = platFormSettings.GetArrayElementAtIndex(0); var targetiPhone = platFormSettings.GetArrayElementAtIndex(1); CopyProperty(targetAndroid, originAndroid); CopyProperty(targetiPhone, originiPhone); // ついでにpacking設定も適用 var packingSetting = editorData.FindPropertyRelative("packingSettings"); packingSetting.FindPropertyRelative("enableRotation").boolValue = false; packingSetting.FindPropertyRelative("enableTightPacking").boolValue = false; // 上記の変更を適用 serializedObject.ApplyModifiedProperties(); } } /// <summary> /// プロパティの書き換え /// フォーマットは以下のようになっている /// - serializedVersion: 2 /// m_BuildTarget: Android /// m_MaxTextureSize: 2048 /// m_ResizeAlgorithm: 0 /// m_TextureFormat: 65 /// m_TextureCompression: 1 /// m_CompressionQuality: 50 /// m_CrunchedCompression: 0 /// m_AllowsAlphaSplitting: 0 /// m_Overridden: 1 /// m_AndroidETC2FallbackOverride: 0 /// </summary> /// <param name="_target">適用先</param> /// <param name="_origin">適用元</param> private static void CopyProperty(SerializedProperty _target, SerializedProperty _origin) { _target.FindPropertyRelative("m_BuildTarget").stringValue = _origin.FindPropertyRelative("m_BuildTarget").stringValue; _target.FindPropertyRelative("m_MaxTextureSize").intValue = _origin.FindPropertyRelative("m_MaxTextureSize").intValue; _target.FindPropertyRelative("m_TextureFormat").intValue = _origin.FindPropertyRelative("m_TextureFormat").intValue; _target.FindPropertyRelative("m_TextureCompression").intValue = _origin.FindPropertyRelative("m_TextureCompression").intValue; _target.FindPropertyRelative("m_CompressionQuality").intValue = _origin.FindPropertyRelative("m_CompressionQuality").intValue; _target.FindPropertyRelative("m_CrunchedCompression").boolValue = _origin.FindPropertyRelative("m_CrunchedCompression").boolValue; _target.FindPropertyRelative("m_AllowsAlphaSplitting").boolValue = _origin.FindPropertyRelative("m_AllowsAlphaSplitting").boolValue; _target.FindPropertyRelative("m_Overridden").boolValue = _origin.FindPropertyRelative("m_Overridden").boolValue; _target.FindPropertyRelative("m_AndroidETC2FallbackOverride").intValue = _origin.FindPropertyRelative("m_AndroidETC2FallbackOverride").intValue; } }
解説
AssetPostprocessorとOnPostprocessAllAssets
アセットの変更を検知します。
OnPostprocessAllAssetsには特定のファイル形式のみを検知する方法はないため、下記でspriteatlasのみをフィルタリングします。
var list = importedAssets.Where(c => c.EndsWith(".spriteatlas")).ToArray();
importedAssetsのpathには拡張子も含まれます。
SpriteAtlasのシリアライズ形式
デフォルトの.spriteAtlasファイルは以下のようになっています。
%YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!687078895 &4343727234628468602 SpriteAtlas: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: New Sprite Atlas m_EditorData: serializedVersion: 2 textureSettings: serializedVersion: 2 anisoLevel: 1 compressionQuality: 50 maxTextureSize: 2048 textureCompression: 0 filterMode: 1 generateMipMaps: 0 readable: 0 crunchedCompression: 0 sRGB: 1 platformSettings: [] packingSettings: serializedVersion: 2 padding: 4 blockOffset: 1 allowAlphaSplitting: 0 enableRotation: 1 enableTightPacking: 1 variantMultiplier: 1 packables: [] totalSpriteSurfaceArea: 0 bindAsDefault: 1 m_MasterAtlas: {fileID: 0} m_PackedSprites: [] m_PackedSpriteNamesToIndex: [] m_Tag: New Sprite Atlas m_IsVariant: 0
プラットフォームの圧縮設定をoverrideし圧縮設定を変更してみるとplatformSettingsが以下になります。
圧縮設定はAndroidで RGBA Crunched ETC2 、iOSで RGBA Compressed ASTC 6×6 Block です。
platformSettings: - serializedVersion: 2 m_BuildTarget: Android m_MaxTextureSize: 2048 m_ResizeAlgorithm: 0 m_TextureFormat: 65 m_TextureCompression: 1 m_CompressionQuality: 50 m_CrunchedCompression: 0 m_AllowsAlphaSplitting: 0 m_Overridden: 1 m_AndroidETC2FallbackOverride: 0 - serializedVersion: 2 m_BuildTarget: iPhone m_MaxTextureSize: 2048 m_ResizeAlgorithm: 0 m_TextureFormat: 50 m_TextureCompression: 1 m_CompressionQuality: 50 m_CrunchedCompression: 0 m_AllowsAlphaSplitting: 0 m_Overridden: 1 m_AndroidETC2FallbackOverride: 0
上記からm_EditorData->platformSettings->各値でたどって変更すれば良いことがわかります。
SerializeObjectからの値取得
元のSpriteAtlasの設定値を取得する流れです。
①SpriteAtlas形式のファイルをSerializedObjectに変換
new SerializedObject(originAtlas)
②FindPropertyで目的のプロパティを取得
.FindProperty("m_EditorData")
③FindPropertyRelativeでプロパティ内のプロパティを取得
.FindPropertyRelative("platformSettings")
④配列の場合はGetArrayElementAtIndex(番号)で取得
var originAndroid = originSetting.GetArrayElementAtIndex(0);
反映先も同様にして取得しますが、SpriteAtlasのPlatformSettingsは空だったのでサイズを拡張する必要があります。
platFormSettings.arraySize = 2
反映には各プロパティの実値を取得する必要があるため、stringValue/intValue/boolValueなどと型を指定します。
型はインスペクタでどのように見えているかを参考に。
(数値入力ならintValue、チェックボックスならboolValue)
最後に適用を保存すれば完了です。
serializedObject.ApplyModifiedProperties();
検証環境
- Unity2018.3
- Unity2019.1
参考