【LT】Unity5.2で作ったAndroidアプリをUnity2019.4に更新した話

LTのYouTube動画 (クリックで再生)
[<img width=480 src="http://img.youtube.com/vi/5cKQ_w8Op0U/hqdefault.jpg">](https://www.youtube.com/watch?v=5cKQ_w8Op0U)

※以下は動画の内容を書き起こして一部編集したものです。

# はじめに

2016年にUnity5.2で開発したAndroidアプリが今年の夏にGoogle PlayでBANしまいました。Unity製Androidアプリを最新バージョンのUnity2019.4に対応して気づいたことを共有します。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/d4b1e031-ae85-cc3b-414d-c39e880740cd.png" width=320 /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/eca88f60-fbbe-5e5d-0e14-bacf2dda4d39.png" width=320 />

変更前と変更後の環境や使用アセットは以下となります。
動画の通り、縦画面の2Dパズルゲームとなります。

|バージョン|1.0.0|1.1.0|
|:--|:--|:--|
|更新日|2016年4月|2020年10月|
|Unity Version|Unity5.2.3|Unity2019.4.1 LTS|
|Android targetSdkVersion|18|29|
|Assets/Animation|iTween|DOTween|
|Assets/Social|Ultimate Mobile Pro|-|
|Assets/Ads|i-mobile, Admob|i-mobile, Admob|

# やったこと

### Unityのバージョンの特性を知る

現在の年号バージョンが始まったのは2017で、最新は2020.1になります。
.4はLTSという長期サポートバージョンになります。
実際にどれを使えばよいのかもろもろ試したところ、破壊的変更が多く入ったのは「Unity2019.3」でした。このバージョンからUIやパッケージが変更になっています。

||.1|.2|.3|.4 LTS|
|:--|:--|:--|:--|:--|
|2017|||||
|2018||||✅|
|2019|||💀|✅|
|2020||-|-|-|

そのため、Unity2018.4, Unity2019.4で動作確認をするのがおすすめです。
Unity5からUnity2019.4に一気に更新するとエラー箇所が多いので一度2018.4に更新してから2019.4に更新を行いました。

### ライブラリ更新(しやすい作りにする)

上記の通り、Unity4, Unity5時代はメジャーだったiTweenは2019.3を境に動作しなくなっていました。このためアニメーションライブラリはDOTweenに差し替えました。

iTween サンプル

```C#
iTween.MoveTo(target.gameObject,
  iTween.Hash(
    "position", new Vector3(0.0f, 0.0f, 0.0f),
    "time", 0.2f,
    "islocal", true,
    "easeType", iTween.EaseType.easeOutExpo)
);
```

DOTween サンプル

```C#
Tween tween;
tween = target.gameObject.transform
  .DOLocalMove(new Vector3(0f, 0f, 0f), 0.2f);
tween.SetEase(Ease.OutExpo);
tween.Play();
```

アニメーションに限らず、ライブラリを使用する場合は直で使用するのではなくinterfaceなどで機能と実装を分けるとライブラリを差し替えやすくなります。

```C#
// ライブラリを差し替えてもinterfaceには影響しない
interface IUIAnimation {
  void showWindow(GameObject go);
}

public class UIAnimationBridge: IUIAnimation {
  public void showWindow(GameObject go) {
    //ライブラリを使用した処理
  }
}

```

AndroidのネイティブアプリではDIの方法が確立されていますがUnityだとSingletonにできればクラスの差し替えが充分にできると思います。直打ちやstatic methodなどにまとめている方はSIngletonを試すと便利だと思います。

```C#
//一度Instanceを差し替えればモックで動作する
UIAnimationBridge.SetInstance(mockAnimationBridge)
:
UIAnimationBridge.Instance.showWindow(go)
```

### 最新の端末に対応(18:9画面対応)

Unity5時代はアスペクト比が大きくても16:9くらいが最大でした。(iPhone8相当)
2020年現在は18:9や19:9の端末が主流となっています。

対応方法はいくつかありますが、自分の場合は
「16:9画面を基準に、縦長であればwidthにmatch、横長であればheightにmatchさせる」
というCanvasScalerのカスタムスクリプトを追加しました。

```C#
[RequireComponent(typeof(CanvasScaler))]
public class CanvasController : MonoBehaviour
{
    void Awake()
    {
        float matchWidthOrHeight = (Screen.height / Screen.width > 16 / 9) ? 0.0f : 1.0f;
        GetComponent<CanvasScaler>().matchWidthOrHeight = matchWidthOrHeight;
    }
}

```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/94c55ff9-1d3a-0b22-64e0-9a80d41d64bc.png" width=320 /> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/f7358e4b-beb9-f4a8-570a-1f883a2aca61.png" width=320 />

### Android 64bit対応
2019年8月1日以降、Androidは64bitのアーキテクチャサポートが必須となりました。
Monoだと64bit対応ができないためIL2CPP対応が必須でした。

MonoとIL2CPPの大きな違いとして、プラグイン呼び出しがある場合に、
コンパイル時にエラー検出することがあります。

以下のようなエラー文言となりますが、エラーメッセージを下階層まで読むと
プラグイン呼び出し時にエラーになっていることが多いです。

```
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) (at /Users/builduser/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:197)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/ac4b5e01-dbcb-5220-1348-68e8bef5603b.png" width=320 />

### Android 9, 10 対応

##### https通信対応

Android 9以降はhttp通信が禁止されています。
自分の場合はi-mobileのSDKがhttp通信だったため広告が一切でない不具合になりました。
メインのAndroidManifest.xmlのapplicationタグにnetworkSecurityConfigを記述することで解決しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/502346fd-8d7d-2fd0-bc35-b3a06df7a51d.png" width=320 />

##### targetSdkVersion:29対応

Androidでは2020年11月1日以降(この記事投稿の3日後！)にtargetSdkVersion:29が必須になります。動作の変更点は以下公式サイトにまとめられています。

> 動作の変更点: API 29 以降をターゲットとするアプリ
> https://developer.android.com/about/versions/10/behavior-changes-10?hl=ja

targetSdkVersionの指定は、publishing settingのtarget API Levelで行うことができます。ここで29が表示されない場合は「Unityのバージョン確認」「Android SDKの確認」を行う必要があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/d74c874c-0f2d-0d70-7c49-e4eb44ed1ee7.png" width=320 />

自分はtargetSdkVersionを確実に指定する方法を使用しました。
Android StudioなどでAndroid SDKを自分でインストールし、それを指定する方法です。
Preference > External ToolsでAndroid SDKを指定する項目があります。
デフォルトはUnityフォルダ内にUnity用のAndroid SDKが指定されているのですが、チェックを外してパスを指定することで行うことができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19692/9c58ee1d-deda-16b8-9333-85ead8dd6d58.png" width=320 />

# まとめ

簡単な2Dゲームですが以下を行うことでUnity5.2からUnity2019.4に更新し、Google Playに再度アプリを公開することができました。Input ManagerやShader周りも変更点があるので追加で必要な方もいるかも知れませんが参考になれば。

- Unityのバージョンの特性を知る
- ライブラリ更新(しやすい作りにする)
- 最新の端末に対応(18:9)
- Android 64bit対応
- Android 9, 10 対応