UnityでAndroid拡張を行うベストプラクティス

Android拡張の開発を行う際に、いちいちAndroid Studioでビルドした結果をUnityに移動してビルドするという手順を踏むのは煩雑であると感じたので、Unityに移動する手順を極力省いて、Android Studioだけで高速にデバッグ開発を行う手段を検討した。

# 注意点
本エントリは現行の`Unity5.4`に対応した情報です。
次期バージョンの`Unity5.5`からはGradleに正式対応するので手順が変わることが想定されます。
[ 追記 ]
Gradleに対応させた記事を書きました。 → [こちらへ](http://qiita.com/seachicken/items/d882c780d880f70e58e1)
また、この記事の内容は、Unityからエクスポートしたデータをバージョン管理対象にしている為、チーム開発ではすぐにコンフリクトしてしまい効率が良くないです。`Unity5.4`の方も上記の新しい記事を参考にした方が良いと思います。

# 動作確認環境
- Unity 5.4.3f1
- Android Studio 2.2.2

# サンプルプロジェクト置き場
[GitHub: UnityAndroidPluginSample](https://github.com/seachicken/UnityAndroidPluginSample/tree/unity5_4_3f1)

# プロジェクト全体の構成
```
├── UnityAndroidPluginSample
│   └── UnityProject           // Unityプロジェクト
│   └── AndroidPluginFactory   // プラグイン開発用プロジェクト
│   │   └── app                // プラグインの実行モジュール
│   │   └── androidplugin      // プラグイン生成モジュール
│   │
│   └── merge_unity_export.bat // Unity変更データのマージツール
│   └── exclude.list           // マージ除外リスト
│
├── UnityExport // ※バージョン管理外
```

# Android拡張プラグインの開発手順
1. Unityでプロジェクトを作成
-  `UnityProject/Assets/Plugins/Android`の下に`AndroidManifest.xml`を配置  
   Activity名は`UnityPlayerActivity`の拡張クラスを想定している。
   尚、このXMLはUnityがビルド時に必要な情報とマージ処理を行う為、拡張したい箇所だけ記載しておけば良い

    ```xml:AndroidManifest.xml
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
      <application>
        <activity android:name="com.sample.androidplugin.SampleActivity" android:label="@string/app_name">
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
        </activity>
      </application>
    </manifest>
    ```
-  Androidのプロジェクトとしてエクスポート  
   `Development Build`: これにチェックを入れないとAndroid Studioでステップ実行できないので注意
   ![build_settings.png](https://qiita-image-store.s3.amazonaws.com/0/116939/cfb5c050-5f6e-62a2-58a5-7ac939d3f333.png)
-  出力されるプロジェクトはAndroid Studioの形式ではないので、バージョン管理外の`UnityExport`ディレクトリに一旦書き出す
-  Android Studioを開いて、エクスポートしたプロジェクトをインポートする
   ![androidstudio_import.png](https://qiita-image-store.s3.amazonaws.com/0/116939/e25e4137-cf24-d899-a7ec-a15464bf4d0a.png)
-  インポート先に`AndroidPluginFactory`を選択する、これがプラグイン開発用のプロジェクトとなる
   ![androidstudio_import2.png](https://qiita-image-store.s3.amazonaws.com/0/116939/93e4e1b9-c612-70b2-4754-d949af109e66.png)
   ![androidstudio_import3.png](https://qiita-image-store.s3.amazonaws.com/0/116939/50106c97-6090-bfc3-0332-5f749e585b6c.png)
-  プラグイン開発用の新規モジュールを追加する
   ![androidstudio_new_module.png](https://qiita-image-store.s3.amazonaws.com/0/116939/4eb1aa7f-69a7-a0f8-d715-a6a3ea594d96.png)
   ![androidstudio_new_module2.png](https://qiita-image-store.s3.amazonaws.com/0/116939/88c87e82-8f7c-a75d-10a5-0fb9a5081343.png)
-  `UnityPlayerActivity`を拡張したクラスを作成する（`AndroidManifest.xml`に記載したクラス名にする）

    ```java:SampleActivity.java
    public class SampleActivity extends UnityPlayerActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // 拡張に成功したら"Android拡張成功！"とToast表示
            Toast.makeText(this, R.string.complete_message, Toast.LENGTH_LONG).show();
        }
    }
    ```
-  参照エラーになるので、`app`と`androidplugin`のお互いの依存関係を解決する
   ![androidstudio_new_module4.png](https://qiita-image-store.s3.amazonaws.com/0/116939/07ce392a-9f65-7f62-f264-8c37a4779078.png)
   ![androidstudio_new_module3.png](https://qiita-image-store.s3.amazonaws.com/0/116939/9f283adb-917a-5a8f-2a39-b2f272e391ac.png)
-  これで`app`モジュールを実行することでデバッグ開発が行えるようになる、拡張に関しては`androidplugin`モジュールに対してのみ行う運用にする

# 作成したプラグインをUnityへ適用する手順
1. `androidplugin/build.gradle`にAARの作成と転送のタスクを追加（JARだとstrings.xml等のリソースを含めることができない為AARにする）

    ```groovy:androidplugin/build.gradle
    // Unityビルド時のunity-classes.jarと重複しないように除外する
    android.libraryVariants.all { variant ->
        variant.outputs.each { output ->
            output.packageLibrary.exclude('libs/unity-classes.jar')
        }
    }

    def AAR_NAME='androidplugin.aar'
    task makeAndExportAar(type: Copy) {
        from('build/outputs/aar/')
        into('../../UnityProject/Assets/Plugins/Android/')
        include('androidplugin-release.aar')
        rename('androidplugin-release.aar', AAR_NAME)
    }
    makeAndExportAar.dependsOn(build)
    ```
-  右ペインから`makeAndExportAar`を実行することで、`UnityProject/Assets/Plugins/Android`の下に`androidplugin.aar`が転送される
   ![androidstudio_new_module5.png](https://qiita-image-store.s3.amazonaws.com/0/116939/1e052d40-87a4-9c5d-ba16-9160496914be.png)
-  Unityでビルド実行を行うと、Android拡張済みの状態で実行される

# Unityの変更をプラグイン開発環境に反映したい場合
1. Unityにて`File > BuildSettings`を選択
-  `Google Android Project`及び`Development Build`にチェック
-  Exportを選択
-  `UnityExport`配下のデータを全て削除し、`UnityExport`のディレクトリを選択
-  `merge_unity_export.bat`を実行することで、Unityで変更した内容のみを自動でコピーする
-  `AndroidPluginFactory`で通常通りプラグイン開発を行う