■
ScriptableObjectを使ってBuildProfileを簡単に作って、保存して、ビルド時に使い分けられるようにしたかったときのこと
- ScriptableObjectでPlayerSettingsに入れる値を保存する
- ただの箱
- これを継承した各プラットフォーム用のProfileClassを作成
- androidのKeyStoreName等
public class BuildProfile : ScriptableObject { public string artifactName;//生成ファイルの名前 public string bundleIdentifier; public string bundleVersion; public string productName; public string companyName; public bool release; public List<string> defineSymbols; public string iconPath; public int accelerometerFrequency; public List<string> ignorePaths;//どけときたいフォルダ }
- EditorWindowで簡単に扱えるようにしたい
- BuildProfileのリストを持ち、Build実行や、中身の確認をするEditorWindowを開くためのWindow
public class ProfileWindow : EditorWindow { [MenuItem("File/BuildProfiles")] static void Init() { GetWindow<ProfileWindow>("BuildProfiles"); } void OnGUI() { //例にアンドロイド. isAndroidFoldOut = EditorGUILayout.Foldout(isAndroidFoldOut, "Android"); if(isAndroidFoldOut) { EditorGUI.indentLevel++; foreach(var androidProfile in androidProfiles) { if(androidProfile == null) { RefreshBuildProfiles(); return; } ButtonLayout(androidProfile, BuildTarget.Android); } AddNewBuildProfileLayout(BuildTarget.Android); EditorGUI.indentLevel--; } GUILayout.EndVertical(); } void ButtonLayout(BuildProfile buildProfile, BuildTarget buildTarget) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(buildProfile.name); if(GUILayout.Button("Select")) { EditorGUIUtility.PingObject(buildProfile); Selection.objects = new[] { buildProfile }; } if(GUILayout.Button("Build")) { Build(buildProfile, buildTarget); } EditorGUILayout.EndHorizontal(); } }
- BuildProfileの中身を見るEditorWindowも欲しさ
- PlayerSettingsの値と見比べて、違うなら強調表示するやつがほしかった
- いわゆるPlaceHolder
- それぞれのプラットフォームに合わせて継承したクラスも作る
- PlayerSettingsの値と見比べて、違うなら強調表示するやつがほしかった
public class ProfileEditor : EditorWindow { public override void OnInspectorGUI() { EditorGUI.BeginChangeCheck(); PropertyLayouter(); ButtonLayouter(); if(EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(buildProfile); } } protected virtual void PropertyLayouter() { buildProfile.artifactName = PlaceHolderTextField("artifactName",buildProfile.artifactName,buildProfile.name); //以下それぞれのプロパティ書いていく } //このWindowでもビルドしたり、Profile選択Window開きたい的な protected virtual void ButtonLayouter() { if(GUILayout.Button("Open Window")) { EditorWindow.GetWindow<ProfileWindow>("BuildProfiles"); } if(GUILayout.Button("Build " + buildTargetGroup.ToString())) { Build(); GUIUtility.ExitGUI(); } } protected string PlaceHolderTextField(string propertyName, string input, string placeHolder) { GUI.SetNextControlName(propertyName); if(!string.IsNullOrEmpty(input) || GUI.GetNameOfFocusedControl() == propertyName) { return EditorGUILayout.TextField(propertyName, input); } EditorGUILayout.TextField(propertyName, placeHolder, defaultStyle); return input; } }
- BuildPipeline.BuildPlayer()
ビルド中にScriptableObjectのインスタンスが破棄されるのでScriptableObjectにバックアップをとっておくとかはできない。
でもPlayerSettingsはバックアップを取りたい
- ので、全部コピー。
using System.IO; public class Builder { const string PlayerSettingsPath = "ProjectSettings/ProjectSettings.asset"; const string BackupPlayerSettingsPath = "Temp/BackupProjectSettings.asset"; public void BuildWithProfile(BuildProfile profile) { //他にもapk等の保存先を作るとかする BackupProjectSettings();//バックアップ SetProfile();//BuildProfile適用 Build();//実行 RestorePlayerSetting();//もとに戻す //バージョニングとかもする } void BackupCurrentPlayerSetting() { if(!File.Exists(PlayerSettingsPath)) { Debug.Log("not Exist"); return; } File.Copy(PlayerSettingsPath, BackupPlayerSettingsPath, true); } void SetProfile() { //PlayerSettingsにBuildProfileを入れる処理 } void Build() { //BuildPipeline.BuildPlayer() } void RestorePlayerSetting() { File.Copy(BackupPlayerSettingsPath, PlayerSettingsPath, true); File.Delete(BackupPlayerSettingsPath); AssetDatabase.Refresh(); } }
そういった次第だった