UnityのapplicationIdentifierの小さな落とし穴

#はじめに

UnityEditorを5.5から5.6以降(2017含む)に変更したら、iOSのcodesignに失敗するようになったというお話です。

ご存じのとおり、iOSでは「一つのAppleIDにはiOS端末を最大100台までしか登録できない＆未使用端末の削除が年に1回しかできない」という大胆な仕様になっており、我々の環境では本番用(≒偉い人＆偉い会社用)とは別にデバッグ用(≒下々の者用)のAppleIDを作り、デバッグ用の端末にはこちらを使って生成したProvisioningProfileでコードサインしたアプリをインストールするようにしています。

そうなると面倒なのはBundleIdの切り替え。さすがにEditorのProjectSettingsを手作業で毎度変更するわけにもいかないので、コマンドラインビルド時にオプション指定＆スクリプトで動的に変更＆ビルドしています。(他にも対処法があるとは思いますが都合により…)

が、これが5.6に上げた直後からうまくいかなくなりました。

#bundleIdentifierとapplicationIdentifier 

Unity5.5から5.6に変わったときにビルド環境に関する大きな変更が一つありまして、**BundleIdentifier**(BundleIdだったりAppIDだったり…)がBuildTargetごとに指定できるようになりました。それまでは全機種共通だったわりにはiOSとAndroidでは使える文字が微妙に違っていて、そこらへんで悩んだ方も多いと思います(ハイフンorアンダースコア使えない問題)。それに対するUnityの回答でしょう。

こちらではBuildPipeline.BuildPlayerを呼ぶ前に別途独自の設定ファイルを読み込んでBundleIdを設定していて、これが5.6からの変更を受けてこう書き換わりました。

```Unity5.5
PlayerSettings.bundleIdentifier = bundleId;
```
```Unity5.6以降
PlayerSettings.applicationIdentifier = bundleId;
```

しかし、これではEditorのPlayerSettingsで設定されたBundleIdentifierがそのまま使われてしまい、codesignで「そのBundleIdのProvisioningProfileは持ってないよ！！」と怒られるようになります。

#なぜか？

![platform.png](https://qiita-image-store.s3.amazonaws.com/0/141731/2a240925-3d69-0f2f-9e71-ad615f49119f.png)

最新のスクリプトリファレンスにはわざわざ太文字でこう書いてあります。

> **Changing this only sets the identifier for the currently active platform.**

https://docs.unity3d.com/ScriptReference/PlayerSettings-applicationIdentifier.html

「PlayerSettings.applicationIdentifierは現在アクティブなプラットフォームのBundleIdのみを変更するよ」ということなんですが、そもそも「**現在アクティブなプラットフォーム**」とは何でしょう？

普通に考えるとBuildSettingsでSwitch Platformしたプラットフォームだろうと思うところなんですが(半分正解)、実はUnityにはそれっぽいものが複数あります。

- Application.platform
- EditorUserBuildSettings.selectedBuildTargetGroup
- EditorUserBuildSettings.activeBuildTarget

この中でApplication.platformが一番関係ありそうですが、実行中のプラットフォームを示すものなのでビルドには関係ありません。なのに、関係あるはずの下2つにはPlatformという単語すら入っていません(ターミノロジーの揺れが酷い！)。

で、いきなり結論ですが、

- applicationIdentifierは**selectedBuildTargetGroup**が示している機種のBundleIdを変更する。
- BuildSettingsでSwitch Platformした場合、selectedBuildTargetGroupもactiveBuildTargetも即時に変更される。
- コマンドラインの"-buildTarget"を指定した場合、Editor起動時に**activeBuildTarget**のみが変更される。
- BuildPipeline.BuildPlayerを実行した場合、**activeBuildTarget**のみが変更される。
- Editor終了時(次回起動時？)にselectedBuildTargetGroupがactiveBuildTargetに合わせたものに変更される。

つまり、コマンドラインビルドでBuildTargetを指定した場合と、BuildボタンではなくBuildPipeline.BuildPlayerでビルドした場合は、EditorUserBuildSettings.selectedBuildTargetGroupが更新されないため、PlayerSettings.applicationIdentifierが意図したプラットフォームのBundleIdにならないことがあるんですねー。なんだそれ。

だからこそ PlayerSettings.SetApplicationIdentifier なんていう、一見不要そうなAPIが追加されているわけです。これを使って対応しました。

#おわりに

無事決着はついたのですが、

- なぜapplicationIdentifierはactiveBuildTargetではなくselectedBuildTargetGroupを見るのか？
- なぜ機種ごとに設定するAPIをわざわざ追加したのか？
- なぜEditorUserBuildSettings.SwitchActiveBuildTargetはバッチモードで使えないのか？
- なぜBuildTargetとBuildTargetGroupは微妙に異なるのか？

…と、こういう実装に至った理由を考えるだけでご飯何杯か行けそうですね！！ 単純にバグにも見えるし、Unityのシステムに何らかのしがらみがあるゆえのパッチ対応のようにも見えます。

UnityEditorはウィンドウでもコマンドラインでも起動できてしまうので、こういった不整合は他にもいろいろあるんじゃないかと思います。こういったややこしそうな問題が発生した場合、別PCでUnity環境を作り直したり、コマンドラインビルドしてみたり、各人のPC環境依存になりうる要素を排除していくと、原因が見つかるかもしれません。

#ご参考
PlayerSettings.bundleIdentifier (5.5)
https://docs.unity3d.com/550/Documentation/ScriptReference/PlayerSettings-bundleIdentifier.html
PlayerSettings.applicationIdentifier (最新)
https://docs.unity3d.com/ScriptReference/PlayerSettings-applicationIdentifier.html