ゴイサギ日記

東京でエンジニアとして頑張って何とか生きてます。。ゆる~く更新していきます

【Unity】新機能の Presets について

Unity 2018.1 から導入された Presets を試してみました。

Presets とは

Unityでアセットを管理する際にInspector上からパラメータを設定する事があると思います。例えば、テクスチャであれば Texture Type は Default か Sprite なのか、メモリ消費を抑えるために Read/Write Enabled のチェックを外すなど、アセットの種類(画像、モデル、アニメーション、サウンド)と制作するゲームに応じて様々な設定が必要になってきます。

そうした全ての設定を手動で行ったら物凄い時間掛かりますね。。。Presets は Inspector上で設定したパラメータを設定ファイル(以下preset)として保存後、それを他のアセットにも適用出来る機能です。

使ってみる

まずはpresetを作ります。Inspector上で対象アセットの設定が完了したら右上のスライダーアイコンをクリックして Select Preset ウインドウから「Save current to ...」をクリックすればpresetが作成されます。
f:id:aki517:20180525011541g:plain

次に別アセットを選択して同様に Inspector上のスライダーアイコンをクリックして Select Preset ウインドウから先ほど作成したpresetを選択するとパラメータが適用されます。
f:id:aki517:20180525011617g:plain

PresetManager

更にPresetManagerを使う事によってアセットインポート時の初期パラメータをpresetの値で設定できます。使い方はメニューの Edit > Project Settings > Preset Manager の Default Presets から「+」をクリックして任意の preset を登録するだけです。

f:id:aki517:20180525011629g:plain

また、preset は png, ogg, fbx だけでなく、Component にも設定できます。なので ParticleSystem の Max Particles を 1000 -> 100にした preset を用意してPresetManager に登録すれば、エフェクトのアセット作成時に制限値や必要な初期設定を手動で行う必要が無くなり、設定ミスによる不具合なども減りそうです。
f:id:aki517:20180526105712p:plain

気になった点
①presetがアセットの種類単位でしか設定できない

同じ種類のアセットだけど用途ごとに専用の設定をしたい場合はどうするんだろと思いました。例えば wav ファイルで Load Type を SE は Compressed In Memory、BGM は Streaming 、Voiceは、、といった場合です。

対処法として思いついたのは専用の設定をしたいアセットを置くフォルダと同階層に専用presetを用意して AssetPostprocessor からその preset を適用するというものです。これなら専用presetが無い場合は PresetManager で設定した preset が適用されます。

f:id:aki517:20180527193433p:plain

スクリプトはこんな感じです。

using UnityEditor;
using UnityEditor.Presets;
using System.IO;

public class PresetPostProcessor : AssetPostprocessor
{
    public const string PRESET_EXT = ".preset";

    public override int GetPostprocessOrder(){ return 1; }

    public void OnPreprocessAsset()
    {
        if( Directory.Exists( assetPath )){
            // フォルダなら何もしない.
            return;
        }
    
        string ext = Path.GetExtension( assetPath );
        if( ext == PRESET_EXT ){
            // .presetなら何もしない.
            return;
        }

        // 対象アセットの保存ディレクトリから専用presetパスを作る.
        string dirName = Path.GetDirectoryName( assetPath );
        string presetPath = (dirName + PRESET_EXT);

        if( !File.Exists( presetPath )){
            // 専用.presetが無いなら何もしない.
            return;
        }

        if( assetImporter.importSettingsMissing )
        {
            // 専用.presetを適用する.
            var preset = AssetDatabase.LoadAssetAtPath<Preset>( presetPath );
            if( preset != null ){
                preset.ApplyTo( assetImporter );
            }
        }
    }
}
②presetの変更が適用されない

preset の値を変更してもインポート済みアセットには変更が適用されないです。難しいところとして、もし preset が変更される度に該当する全アセットに適用処理が実行される場合、アセットが増えれば増えるほど、処理が完了するのに時間が掛かってしまいます。

①のような専用preset であれば値を変更後に Reimport を実行する事によって AssetPostprocessor のコールバックでインポート済みアセットに変更を適用することが出来そうです。かなり強引ですが・・ (^_^;)

まとめ

幾つか気になる点はありましたが、個人的には便利な機能だと思います。Presets の APIも提供されているのでプロジェクトに応じたカスタマイズも色々と出来そうです。

参考

https://forum.unity.com/threads/presets-feature.491263/
Preset - Unity スクリプトリファレンス