Unityの設定をまとめて切り替えるUnitySettingSwitcherを作ってみている

* これは作成中のUnitySettingSwitcherの使いかたを説明した記事です.
* まだ開発途中につき各種仕様は変更可能性が多々あります,順次アップデート.

# UnitySettingSwitcherとは

JSONで設定情報を定義しておいて、それをもとにUnity設定を切り替えるエディタ拡張です。

GitHub: https://github.com/uisawara/unity-settingswitcher

![Screen Shot 2019-12-13 at 16.06.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189626/13b5e8a3-d924-5dd1-d085-60ca93856d38.png)

## 期待する効果

* UnityのPlayerSettings, BuildSettings等の設定周りの作業が楽になる
  * 設定テンプレートでプロジェクト設定を一括でできるようになる
        * 設定ファイルを置き適用すれば同一設定を再現できる。
        * ファイルベースで設定することで抜け漏れを防げる。
    * 設定の構成管理がやりやすくなる
        * ビルド種類ごとの設定違いを共通部分・個別部分として定義できる(例: PC向け,OculusRift向け,OculusGo向けで設定切替する)
        * 設定を体系立てて構築でき保守性が上がる, 設定作業の手間が減る
* 作った設定ファイルを持っていけば別プロジェクトで同一の設定を再現するのが容易になる
    * 設定のここそこをこうして〜という解説書いていたのが、設定ファイルはコレと置くだけでよくなる,再演する側も設定ファイル持ってくるだけ
    * みんなの手間が減ってhappy

例) こういうJSONファイルを書くと
![Screen Shot 2019-12-13 at 15.58.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189626/21de6112-6bb7-99e9-20fe-1315f35a00ae.png)


こんな感じに設定切替できるようになる
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">実験tweet <a href="https://t.co/xmCieGJbBy">pic.twitter.com/xmCieGJbBy</a></p>&mdash; sa_w_ara△ (@sa_w_ara) <a href="https://twitter.com/sa_w_ara/status/1205293290796400641?ref_src=twsrc%5Etfw">December 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 設定手順1.基本

android向けでdevelop,productionの設定を切り替えられるようにしつつ、
構成 flavors/app, viewerとbuildtype/develop, productionを定義する場合の手順

* [MiniJSON](https://gist.githubusercontent.com/darktable/1411710/raw/513f1c0ceb0cd4728973e109bd0b13911f162ebd/MiniJSON.cs)が必要なので事前にimport
* UnityプロジェクトにUnitySettingSwitcherのunitypackageをインポート (https://github.com/uisawara/unity-settingswitcher/releases)
* メニュー Window/UnitySettingSwitcherでSettingSwitcherウィンドウを開く(CMD+Eでも開く)
* /Assets/UnitySettingSwitcher/TemplatesからSettings.jsonとSettings.android.jsonを/Assets/配下にコピー
* /Assets/settings.jsonを編集して設定を定義

```/Assets/settings.json
{
  "settings": [
    {
      "name": "flavors/app",
      "build_settings": {
        "scene_list": [
          "Assets/Application/Scenes/MainScene.unity"
        ]
      }
    },
    {
      "name": "flavors/viewer",
      "build_settings": {
        "scene_list": [
          "Assets/Core/ARSceneLayout/Scenes/SceneViewerScene.unity"
        ]
      }
    },
    {
      "name": "buildtype/develop",
      "player_settings": {
        "applicationIdentifier": "com.example.sampleappdev",
        "scripting_define_symbols": "ENV_DEVELOP"
      }
    },
    {
      "name": "buildtype/production",
      "player_settings": {
        "applicationIdentifier": "com.example.sampleapp",
        "scripting_define_symbols": "ENV_PRODUCTION"
      }
    }
  ]
}
```

# 設定切替の使いかた

* SettingSwitcherウィンドウを開く(メニュー Window/Unity Setting Switcherを選ぶかCMD+E)
    * Unity Setting Switcherウィンドウが開く
* "reload"ボタンで設定を読込
* 設定を選んでボタンクリックで設定切替

# 設定手順2.android向けkeystore切替を定義する

こんな設定で、開発用keystoreとリリース用keystoreを使い分けできるようになります。

* keystoreファイルを配置する
    * Assets/Cert.local/sample.keystore
* ローカル専用設定を定義する
    * keystoreファイルを配置
    * keystore設定を定義

```/Assets/Settings.local.json
{
  "settings": [
    {
      "name": "android-singing/develop",
      "android": {
        "keystoreName":"",
        "keystorePass":"",
        "keyaliasName":"",
        "keyaliasPass":""
      }
    },
    {
      "name": "android-singing/production",
      "android": {
        "keystoreName":"Assets/Cert.local/sample.keystore",
        "keystorePass":"************",
        "keyaliasName":"************",
        "keyaliasPass":"************"
      }
    }
  ]
}
```

# Git向け設定のすすめ

事前に.gitignoreに以下設定を追記しておくのをオススメします。
ローカル設定ファイルがcommit対象外になり、個人別の設定がリポジトリを汚すのを回避できます。
(選択中のSetting情報、ローカルのみに効かせたい設定等)

```..gitignore
# UnitySettingSwitcher
*.local
*.local.json
*.local.meta
*.local.json.meta
```

# Settingsの仕様

Settingsはこんな仕様です。

* 設定ファイル
    * /Assets/Settings.jsonと/Assets/Settings.*.jsonの全ての設定ファイルが、設定情報の定義ファイルとして読み込まれます。
    * 個別の設定ファイルに定義された設定は相互に参照可能なので、定番設定群とアプリ固有設定群をそれぞれ定義しておいて差分プログラミングするとかできます。
* 設定グループ
    * nameに"/"を入れてパスを区切っておくことで設定のグループ化ができます。
    * グループ内で設定は１つのみ有効となり、どれかが選択されると他の設定が無効になります。
* 非表示設定
    * nameの1文字目が"."だと、設定ウィンドウ上には表示されない設定になります。
* 継承
    * "inherit"宣言を使うことで他の設定を継承した子設定を作れます。
* Settingsの結合
    * 設定は選択されると、選択中のアクティブな設定一式が結合され、それがUnityの各種設定クラス(PlayerSettings,BuildSettings等)へ反映されます。
    * ちなみにこのときUnityEditorのConsoleに実際適用された設定セット名、設定項目がログ出力されます。何かおかしいな？と思ったときはそちら参照するとよいかもです。
* 設定項目の各種名称
    * Unityの各種設定クラスのpublic staticメンバー名をそのままJSON上の項目名として使います。
    * そのためUnityEditorのGUI上のどの項目がどんなメンバー名に適用されるのかは[Unityリファレンス](https://docs.unity3d.com/ja/2018.4/ScriptReference/index.html)等を参考に調べてくだい。
    * enum型の設定項目についてはEnum.Parseによる文字列解釈がなされるので、設定ファイル上の値はEnum要素を使ってください。
        * 例) "ScriptingBackend" : "IL2CPP", "minSdkVersion": "AndroidApiLevel22"
    * enum型で[Flags]属性のついている型については複数の値セットが定義できます。スペース区切りでEnum要素を並べた文字列を使ってください。
        * 例) "targetArchitectures": "ARMv7 ARM64"

# おおまかな仕組み

* 基本的に UnityのPlayerSettingsクラス, BuildSettingsクラス等のclass public static fieldへReflectionを使い値設定してます。
* 値設定で反映できるフィールドはいいのですが、Setterメソッドを使って設定しなければならないフィールド等は個別の対応コードを書いています。そして現状全ての設定項目には対応しきれていません。
    * 未対応項目は個別追記が必要になると思います。

# 最後に補足

* Unityで設定切替のためにチュートリアル記事見ながらいっこいっこ設定していく手間や、Editor拡張書く手間から解放されたかった。。
* 設定ファイル取り込めばボタン１つで設定終えられるくらいまでお手軽にしたい