UnityでGoogle Play Game Services導入する際、あらゆる罠にハマった話

UnityプロジェクトにGoogle Play Game Servicesを導入した際、いろいろ罠にはまって24時間くらい無駄にしたので、ここに何が発生してどうやって解決したかメモしておきます。

# 私の開発環境

* Unity 2018.4.10f1
* Google Play Game plugin for Unity v 0.10.09
* Android SDK level 28

macで作業しています。

# 動かしたいコード

[Google Play Game Servicesプラグイン](https://github.com/playgameservices/play-games-plugin-for-unity)を使って、プロジェクトにクラウドセーブ機能を導入しようとしています。
動かしたいコードは、サービスの初期化とプレイヤの認証です。

```C#
var conf = new PlayGamesClientConfiguration.Builder()
    .EnableSavedGame()
    .Build();
PlayGamesPlatform.InitializeInstance(conf);
PlayGamesPlatform.Activate();

Social.localPlayer.Authenticate( (res, msg) => {
    Debug.Log($"Result {res} : {msg}");
});
```

# ハマった罠たち

## ■ビルド時、ネームスペースGoogleが見つからない

**●現象**
Googleというネームスペースが見つからずにエラーになる。
```Assets/GooglePlayGames/Editor/GPGSAndroidSetupUI.cs(118,17): error CS0103: The name 'Google' does not exist in the current context```

**●原因**

バッチビルドのオプションでパッケージマネージャを使わないようにしてるのが原因です。

**●解決方法**

-noUpmオプションを外して、パッケージマネージャを使うようにします。

```sh
$UNITY -quit -noUpm -batchmode -logfile ./build.log -username $USERNAME -password $PASSWORD -executeMethod AndroidBuildRelease
```
　　　　　　↓

```sh
$UNITY -quit -batchmode -logfile ./build.log -username $USERNAME -password $PASSWORD -executeMethod AndroidBuildRelease
```

## ■ビルド時、Proguard (R8)でエラーが発生する

**●現象**

設定ファイルは正しいはずなのに、Proguardが文法エラーで止まる。

```sh
/path/to/src/proguard-user.txt:2:2: D8: Expected char '-' at /path/to/src/proguard-user.txt:1:1
-keep class com.google.android.gms.games.multiplayer.** { *; }
```

**●原因**

progurad-user.txt にBOMがついているためエラーになります。

**●解決方法**

proguard-user.txtのBOMを取ります。また、AssetImporterでテキストを全てBOM付きに変更しているプロジェクトでは、このファイルを対象外にするように修正を加えます。

## ■ビルド時、support-v4周りでコンパイルエラーがでる

**●現象**

ビルドすると``Program type already present: android.support.v4.なんとか``というエラーが発生する。

**●原因**

GPGSではandroidxで提供されているv4サポートを使っているためです。その他のプラグインでandroid.support.v4系のパッケージを利用しているとこのエラーが発生します。

**●解決方法**

android.support.v4 はバージョン28で終了なので androidxを使うようにします。でも、自分で書いたコードだったら直せますが、外部のライブラリがこの辺を要求しているとなかなか対応が面倒ですね。

## ■ClassNotFoundExceptionが発生する

**●現象**
APKを実行するとClassNotFoundExceptionを吐いて止まる。
``Exception class not found com.google.android.gms.games.Games``

**●原因**

これには以下の要因があります。

1. Assets/Plugins/Android以下にサービス関連のaarファイルが配置されていないと発生します。
2. ProguardによってGPGS関連のクラス名が変更されると発生します。

**●解決方法**

 **＊ 1. GPGS関連のaarを配置する**
プラグインを導入すると、パッケージマネージャにレジストリを加えてGPGS関連のaarがインストールされるようになっています。
ここで問題がでるのは主に開発環境のjava関連が理由かと思われます。

* javaがインストールされていなければインストールする
* パスを通すか、パスの通ったディレクトリにjavaを置く。 /usr/bin/java があれば問題ないはず
* gradleがインストールされていなければインストールする (未確認)
* Unityエディタで``Assets > External Dependency Manager > Android Resolver > Force Resolve``を実行する

**＊ 2. Proguard関連でリネームされないようにする**

クラス名が変更されないように、[ここ](https://github.com/playgameservices/play-games-plugin-for-unity#play-games-services-proguard-configuration)らへんに書いてある内容を設定するか、難読しないようにします。
前述しましたが、Proguardの設定を追加する場合はファイルにBOMがつかないようにします。


## ■おかえりポップアップが表示されない

**●現象**

正式名称を何と言うのか分かりませんが、アプリを実行した際に表示されるはずのおかえりなさいポップアップが表示されない。

**●原因**

これには以下のような要因があります。

1. バンドルIDを間違えている
2. app idを間違えている
3. ゲームサービス側にテストユーザを設定していない

**●解決方法**

**＊ 1. バンドルIDを正しいものにする**

Google Play Consoleでゲームサービスに登録しているバンドルIDと、APKのものとを合わせるようにします。

**＊ 2. app idを正しいものにする**

Unityエディタの``Window > Google Play Games > Android setup``でダイアログを開き、Resource Definitionで登録するXMLを確認します。

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_id" translatable="false">ここにapp idを記述する</string>
  <string name="package_name" translatable="false">ここにバンドルIDを記述する</string>
</resources>
```
app id はGoogle Play Consoleの``ゲームサービス > ゲームの詳細``に書いてある11桁の数値です。

**＊ 3. ゲームサービス側のテストユーザに設定する**

テストユーザの設定はゲームサービス側にもあり、そちらの設定をしていないとこの現象が発生します。
Google Play Consoleで、テストプレイヤーを登録します。


## ■プレイヤー認証に失敗する

**●現象**

device errorやcancel authentication といったエラーで、Social.localPlayer.Authenticate が常に失敗する。

**●原因**

これには以下のような要因があります。

1. SHA1フィンガープリントが間違っている
2. SavedGame の設定がオフになっている

**●解決方法**

**＊ 1. SHA1フィンガープリントを修正する**

アプリのSHA1フィンガープリントを確認します。署名の方法によって2パターンあります。

A) Google Play App Signingを使っている場合
　Google Play Consoleのアプリの詳細画面から ``リリース管理＞アプリの署名`` で確認します。

B) ビルド時にキーストアで署名している場合
　下記コマンドで表示されるSHA1フィンガープリントを確認します。

```sh
keytool -list -keystore キーストアのパス -v
```

つぎに https://console.developers.google.com でゲームサービス側に登録されているフィンガープリントを確認します。
上記サイトからサービスを選び、``認証情報＞Oauth2.0 クライアント ID``のなかから、アプリを選んで編集画面に入ると確認できます。
アプリとサービスのSHA1フィンガープリントを合わせるように、どちらかもしくは両方を修正します。

**＊ 2. SavedGameの設定をオンにする**

Google Play Consoleのゲームサービスでアプリを選び、ゲームの詳細を表示します。SavedGameの設定項目があるのでONにします。

<img width="437" alt="スクリーンショット 2020-05-30 20.29.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646468/abb87be0-0c92-efcc-2490-a2b6d3af3762.png">

保存済みゲームというのはSavedGameの翻訳ですが、これ紛らわしいですね。「SavedGameを有効にする」という感じの表記にしてほしいです。


# 最後に

iOSのGameCenterは簡単だったのでGPGSも楽勝だろうと思って舐めていたら、これらの罠を全部踏むと言う有様でした。UnityにGoogle Play Game Serviceを導入するための日本語情報は多少ありますが、トラブルシュートのようなものがないんですよね。
ここに書いたのは自分のための備忘録なのですが、もしだれかが同様につまづくことがあったとき、これが参考になればいいなと思います。