UnityでAndroidビルドエラーUnityEditor.BuildPlayerWindow+BuildMethodExceptionが出た時のライブラリ競合解決が辛過ぎて泣いた

# 概要
Unityでスマホゲーム作っててiOS向けのリリースがひと段落したのでAndroid向けビルドしたらめっちゃエラー出て泣いた。
<img width="172" alt="2020-01-18_20h49_42.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/fe3e6050-afda-dc50-b83f-40b250df077d.jpeg">
つら…
# 環境
- OS:Windows 10
- Unity:2019.1.0f2

Macでも同様のエラー出たので、OS依存のエラーではないことは検証済み。

# エラー内容を確認する
ビルド失敗時に表示されるUnity Editorのダイアログには、何もメッセージが表示されず無事死亡。
<img width="192" alt="2020-01-18_20h47_54.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/f1d0a808-823d-6e75-839f-038ce4d60e0e.jpeg">

Consoleを確認すると`UnityEditor.BuildPlayerWindow+BuildMethodException: 145 errors`という素敵なログが出ていた。

```
UnityEditor.BuildPlayerWindow+BuildMethodException: 145 errors

  at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (UnityEditor.BuildPlayerOptions options) [0x00242] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:194 

  at UnityEditor.BuildPlayerWindow.CallBuildMethods (System.Boolean askForBuildLocation, UnityEditor.BuildOptions defaultBuildOptions) [0x0007f] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:97 
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
```

エラー145個て。初代のポケモン図鑑ならもう少しでコンプやぞ。

`UnityEditor.BuildPlayerWindow+BuildMethodException`でググると結構情報出てくるけど、`PlayServicesResolver`だけで解決するパターンばかり。どれも今回のエラーとはちょっと違いそうな雰囲気だ。

もう少し手前のログを見ると、Gradle buildでコケていることがわかった。 

```
CommandInvokationFailure: Gradle build failed. 
C:\Program Files\Unity\Hub\Editor\2019.1.0f2\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\OpenJDK\Windows\bin\java.exe -classpath "C:\Program Files\Unity\Hub\Editor\2019.1.0f2\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle\lib\gradle-launcher-4.6.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"

stderr[
D8: Program type already present: com.facebook.unity.FBDialogUtils

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':transformDexArchiveWithExternalLibsDexMergerForRelease'.
> com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
...
```

以下、つらつらと導入ライブラリの一覧が羅列されていた。
stderrにはFacebookの`FBDialogUtils`がすでに存在しているとのメッセージが。

`D8: Program type already present: com.facebook.unity.FBDialogUtils`

Facebook SDKで何か引っかかっているのかな？
正直これだけでは具体的な原因が特定できない。

とりあえず現状得られたエラーメッセージでググってみると、SDKの重複に起因して発生するエラーっぽい情報がでてきた。
[D8: Program type already present: com.facebook.unity.Constants - Unity Answers](https://answers.unity.com/questions/1635048/d8-program-type-already-present-comfacebookunityco.html)
[Program type already present error when gradle build - Unity Forum](https://forum.unity.com/threads/program-type-already-present-error-when-gradle-build.699428/)

そういえばAndroidアプリのビルドでいろんなSDK入れると、バージョン違いの重複ライブラリが存在してしまい「どっち見ればええねん」的なエラーが出るのを何度も経験していた…

# ライブラリの依存関係を調査する

おおよその目星がついたので深掘ってみる。Androidプロジェクト吐いて`gradlew dependencies`コマンド叩くと、ライブラリの依存関係を確認できるらしい。
[【Android】ライブラリの依存関係を調査する方法（gradle） - テクノモンキーのアプリ開発日記](https://develop.hateblo.jp/entry/android-library-gradle-izon)


知らなかった。

Build Settingsで [Export Project] にチェックを付けてAndroidプロジェクトを出力。
<img width="465" alt="2020-01-18_21h39_22.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/4fee2aa4-5c0a-8e75-3cf1-1396886509db.jpeg">
Android Studioでプロジェクト開いてgradlew sync実行。エラー出てたら解消させとく。


コマンドプロンプト（Macの場合はターミナル）でAndroidプロジェクトのフォルダに移動して`gradlew dependencies`コマンドを叩く。ライブラリ一覧や依存関係がズラリと表示される。

<img width="420" alt="2020-01-18_21h51_00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/a88e7f44-a9a2-1b66-2feb-42d0b04bf81f.jpeg">
<img width="357" alt="2020-01-18_21h52_01.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6380/3f699768-bb6c-d608-a09c-bdead5f70601.jpeg">

細かい部分はスルーするが、同名のバージョン違いが存在したり`play-services`系で被っているものがいくつかあった。

# ライブラリの競合を解決する
おそらく以下3つのライブラリが重複対象として該当。

- play-services-ads-identifier
- play-services-basement
- facebook-android-wrapper

対応方法としては

- バージョンを合わせる
- 依存関係を無効化する
- 重複ライブラリを除外する

といった案が考えられるようだ。

## 重複ライブラリを除外する

Androidプロジェクト上では`build.gradle`の`dependencies`から対象のimplementationを削除することで、ビルドエラーが解消されapkの生成ができた。

```build.gradle
dependencies {
...
    implementation(name: 'play-services-ads-identifier-16.0.0', ext:'aar')
    implementation(name: 'play-services-basement-16.0.1', ext:'aar')
    implementation(name: 'facebook-android-wrapper-7.16.1', ext:'aar')
...
}
```

とはいえ毎回UnityからAndroidプロジェクト吐いてAndroid Studioでビルドするのはダル過ぎる。そんなのはiOSだけで十分です。

軽く調べてみると、Unityプロジェクト上では`mainTemplate.gradle`を自前で用意して依存関係を書かなければならないらしい。

ちょっと時間も無くて「なるほどわからん」って感じだったので、重複してるaarファイルのバージョン低い方を削除するという力技でUnity上でもビルドエラーを解決（＾ω＾）

その後、対象ライブラリが関係している広告まわりを実装。ひと通りの動作確認でも問題なさそうだったのでクローズとした。

# Androidのビルドエラー解消しんどい
Androidのライブラリ競合問題、5年くらい前から悩まされてた気がするけど、未だにサクッと解消できなくてつらい。はやくAIに仕事奪われたい。