UnityでGoogle Play Game Servicesとmobile backendを導入してハマった話


UnityでGoogle Play Game Servicesを導入済みのプロジェクトにmobile backendを導入した際、Androidビルドでハマったので解決に至るまでをメモとして残します。

##環境

-	Unity 5.3.4f1

##序章

###Google Play Game Services

Google Play Game Services（以下GPGS）のプラグインは、以下のリポジトリから現時点での最新版0.9.32をプロジェクトに導入済みでした。

[playgameservices/play-games-plugin-for-unity: Google Play Games plugin for Unity](https://github.com/playgameservices/play-games-plugin-for-unity)

###mobile backendのインポート

プッシュ通知に対応するため、NIFTY Cloudのmobile backendのUnity SDK（2.1.1）を導入しました。

[NIFTYCloud-mbaas/ncmb_unity: ニフティクラウド mobile backend Unity SDK](https://github.com/NIFTYCloud-mbaas/ncmb_unity)

このとき、android-support-v4.jarとgoogle-play-services.jar（と、res/values/version.xmlも）はGPGSのプラグインによりプロジェクトにインポート済みだったので、外しました。

![](https://qiita-image-store.s3.amazonaws.com/0/9836/c07fff7a-14e1-1335-85c6-d43094d4e58f.png)


###起動、そしてクラッシュ

この時点でビルドしてAndroidの実機上で起動してみると、クラッシュします。OMG!

![](https://qiita-image-store.s3.amazonaws.com/0/9836/73908aaa-e9ad-d780-78b1-90e065ac6dc6.png)


Android Studioのlogcatを見ると、以下のようなログが出ています。

```
04-10 00:48:34.984 24899-24988/? E/AndroidRuntime: FATAL EXCEPTION: IntentService[RegIntentService]
                                                   Process: com.mybdesign.mobilebackendexample, PID: 24899
                                                   java.lang.Error: FATAL EXCEPTION [IntentService[RegIntentService]]
                                                   Unity version     : 5.3.4f1
                                                   Device model      : LGE Nexus 4
                                                   Device fingerprint: google/occam/mako:5.1.1/LMY48T/2237560:user/release-keys
04-10 00:48:34.989 567-1033/? W/ActivityManager:   Force finishing activity 1 com.mybdesign.mobilebackendexample/com.nifty.cloud.mb.ncmbgcmplugin.UnityPlayerNativeActivity
```

どうやらmobile backendのプッシュ通知のデバイス登録をおこなうタイミングでクラッシュしているようでした。

##GPGSのダウングレード

経験上、GPGSのインポート、セットアップで追加されるandroid-support-v4とgoogle-play-servicesがほかの広告SDKと競合を起こすことがよくあったので、まずこれを疑ってGPGSのダウングレードを試みました。

プロジェクトにインポート済みのGPGSを一旦削除して（GooglePlayGamesフォルダ、PlayServicesResolverフォルダ、Plugins/Androidのlibsフォルダ、MainLibProjフォルダをまず削除、Unityを再起動してからplay-services-*.aarとsupport-*.aarを削除）、old-builds/GooglePlayGamesPlugin-0.9.21.unitypackageをインポート、Windowメニュー→「Google Play Games」→「Setup」→「Android setup...」から再度セットアップをしました。

するとConsoleに大量のエラーが出力されます。

```
Assets/GooglePlayGames/ISocialPlatform/PlayGamesPlatform.cs(94,21): error CS0104: `Logger' is an ambiguous reference between `UnityEngine.Logger' and `GooglePlayGames.OurUtils.Logger'
```

Unity 5.3以降でUnityEngine.Loggerが定義されたので、こいつが曖昧だということですね。
ここは面倒ですが、GPGSでGooglePlayGames.OurUtils.Loggerクラスを使っているファイル全部に以下を追加して解決してやります。

```
using Logger = GooglePlayGames.OurUtils.Logger;
```

これで再度ビルドして実機で実行してみます。

```
04-10 01:29:21.040 28391-28411/? I/Unity: OnRegistrationSucceeded
                                           
                                          (Filename: ./artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
```

今度はmobile backendのデバイス登録に成功しているようですが…。

##今度はGPGSが…

logcatをよく見ると、以下のようなログが出ています。

```
04-10 01:29:16.432 28391-28411/? D/GamesUnitySDK: Performing Android initialization of the GPG SDK
04-10 01:29:16.447 28391-28411/? E/GamesNativeSDK: Can't register class com/google/android/gms/appstate/AppStateManager: an exception occurred.
04-10 01:29:16.515 28391-28411/? E/GamesNativeSDK: Could not register one or more required Java classes.
04-10 01:29:16.688 28391-28411/? I/Unity: InvalidOperationException: There was an error creating a GameServices object. Check for log errors from GamesNativeSDK
                                            at GooglePlayGames.Native.PInvoke.GameServicesBuilder.Build (GooglePlayGames.Native.PInvoke.PlatformConfiguration configRef) [0x00000] in <filename unknown>:0 
                                            at GooglePlayGames.Native.NativeClient.InitializeGameServices () [0x00000] in <filename unknown>:0 
                                            at GooglePlayGames.Native.NativeClient.Authenticate (System.Action`1 callback, Boolean silent) [0x00000] in <filename unknown>:0 
                                            at GooglePlayGames.PlayGamesPlatform.Authenticate (System.Action`1 callback, Boolean silent) [0x00000] in <filename unknown>:0 
                                            at GooglePlayGames.PlayGamesPlatform.Authenticate (System.Action`1 callback) [0x00000] in <filename unknown>:0 
                                            at GooglePlayGames.PlayGamesLocalUser.Authenticate (System.Action`1 callback) [0x00000] in <filename unknown>:0 
                                            at MobileBackendExample.Start () [0x00000] in <filename unknown>:0 
                                           
                                          (Filename:  Line: -1)
```

どうやらGPGSが機能していないようです。そういえばGPGSのログイン画面が出なかったような…。

エラーの内容を見てみると、AppStateManagerクラスが登録できない様子。ググってみると、あるバージョンのgoogle-play-servicesからAppStateManagerクラスがなくなっているらしいことがわかりました。

[Error Creating a GameServices object. · Issue #884 · playgameservices/play-games-plugin-for-unity](https://github.com/playgameservices/play-games-plugin-for-unity/issues/884)

とりあえず旧バージョンのgoogle-play-servicesが入手できないか探してみます。するとStack Overflowにまんま直球の質問が。

[java - How to download older google play services? - Stack Overflow](http://stackoverflow.com/questions/20982533/how-to-download-older-google-play-services)

ここからひとつずつダウンロードしてAppStateManagerクラスが含まれているバージョンのgoogle-play-servicesを探します。
jarの中身を確認するのには[Java Decompiler](http://jd.benow.ca/)を使いました。GUIもあって便利です。

![](https://qiita-image-store.s3.amazonaws.com/0/9836/7e4cb5c9-f4f6-591c-66fe-d090a50e2271.png)

r26のgoogle-play-servicesにはAppStateManagerクラスがあったので、これをプロジェクトにインポート済みのものと差し替えます[^1]。

[^1]: ここで再度GPGSのセットアップをおこなうと、google-play-servicesを元に戻されてしまうので注意。

##Finally it works!

再度ビルドして動作を確認すると、GPGSのログイン画面も表示され実績やリーダーボードも機能していました。mobile backendの方も、正常にプッシュ通知が機能していました。

ライブラリのソースコードを書き換えたり、古いバージョンを使ったりしているので正直おすすめはできませんが、同様にハマった人の参考になればと思います。

##オマケ

実はあと2つほどハマったポイントがあります。

-	Player SettingsのStripping LevelをDisabledにしておかないとmobile backendのデバイス登録が機能しなかった。
-	使っているAndroidプラグインが多すぎて、ビルド時にToo many method referencesが発生→不要なjarを削除。