Unityでスマホアプリを開発する

Unityでスマホアプリを開発するために必要なものを全てドキュメントに残します。
また、自分自身Unityを使ってのアプリ開発は初めてなので少しでも疑問に思ったことは全てメモしていこうと思います。
完成するまでに随時アップデートします。

## プロジェクト作成までにするべきこと
### Unityのインストール
Unity Hubをインストールするのが良いでしょう。
そこからUnityをインストールします。
※ここでiOSとandroidのモジュールを追加すること
※後からでも追加できます。
（自分は後からモジュールを追加しました）
※日本語化したい人は日本語化のモジュールもインストール

![スクリーンショット 2021-08-18 9.21.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615043/d9c21920-81ed-f69c-1524-0fe5dae42418.png)

こうなっていればOK！

### 2Dと3D両方のスクリーンが出てくる場合はどうすればいい？？
→一旦2Dで作成。

## プロジェクト作成後
### レイアウトを整える
ここは完全に個人の自由
個人的に今回は2×3のレイアウトで開発を進める

### 日本語化出来ない？
【Unity】→【Preferences】→【Languages】→【English選択】→【Japaneseを選択】
本来ならこの流れで日本化が可能です。
しかし日本語のモジュールをインストールしていないと【Languages】が出てこないので気をつけましょう。

### プラットフォームの変更
【ファイル】→【ビルド設定】→【android】→【Switch Build】
これでandroidの開発環境が整いました。

### 画面サイズの設定
1920×1080 Portaitに設定
↓
画面サイズによって表示を合わせたい
UIコンポーネントの親要素である
【Canavs】をクリックし
【Canvas Scaler】
→【UIスケールモード】→【画面サイズに拡大】
→【参照解像度】xyを初期に設定していた1920×1080をそれぞれxとyに設定
→【マッチ】→【高さ】（縦画面ゲームのため）
これで基本的にはOK！

## 広告関係
### 広告の種類
#### バナー広告
プレイしていると画面下や画面の中に横長で出てくる広告

* 標準バナー広告
* スマートバナー広告
* アダプティブバナー


#### インタースティシャル広告
全画面で強制的に広告を表示させる。
ゲームの終了後など表示タイミングに制限がある。

#### リワード広告
アイテム付与などを得点としてつけれる

### 広告準備（Unity外設定）

#### 広告サービス登録
AdModの登録
こちらから　登録できます。(https://admob.google.com/intl/ja/home/get-started/)

#### 税務情報入力
これをやらないと24%の税金がかかってしまいます。
登録はこちらの記事がとても参考になります(https://marumaro7.hatenablog.com/entry/zeimujouhou)


#### テストデバイス登録
実機確認する端末で本番広告が出ないようにする設定。
本番広告をタップするとアカウントが停止されて1ヶ月ほど収益が入らなくなってしまう。
→実機端末のみでテスト広告が表示できる。
[](
こちらの記事を参考にテストデバイスを登録しましょう。（https://qiita.com/Maru60014236/private/987c7b59ea621736826d）
)
##### AdModにログイン
「設定」→「テストデバイス」→「テストデバイスを追加」
各情報を入力!!
おそらく広告IDまたはIDFAの入力で詰まると思います。
androidとiOSそれぞれのIDの取得方法を下記に示します。
※各端末でIDの確認
* android
「設定」→「Google」→「広告」→「広告ID」

* iOS
「設定」→「プライバシー」→「トラッキング」→「ON」。
appStoreで「IDFA」と検索しアプリをインストール→インストールしたアプリを起動し表示されたIDがIDFA！

### アプリ登録

リリース後に連携。
連携のための箱を用意する感覚です。
AdModから1分で可能です。

* リリース後にアプリ連携必要
* アプリID生成される（アプリ内実装に使用）
* androidとiOSでそれぞれ登録必要

#### 広告ユニット作成（広告ID実装に使用）
こちらもAdModから簡単に作成が可能でした。
今回は下記3つ×2(iOS,android)で合計6つ作成します。

* バナー
* インタースティシャル
* リワード


### 広告実装(Unity内)

####　初期設定

* プラグインインポート
[](
こちらの記事を参照（https://qiita.com/Maru60014236/private/005638881967aadc55c0）
)
公式サイト
https://developers.google.com/admob/unity/quick-start?hl=ja

1.　公式サイトの「プラグインをダウンロード」を押す
1.　2.「GoogleMobileAds-v（バージョンNo）unitypackage」を押す 
1.　広告を実装するUnityプロジェクトを開き、ダウンロードした「GoogleMobileAds-v5.4.0.unitypackage」をAssetsにドラッグアンドドロップ
1.　インポートを押して取り込みます。

* android設定
ビルド設定からプラットフォームをandroidに変更する。
【アセット】→【External Dependency Manager】→【androiad reolver】→【Resolve】
これでsuccessが表示されればOK

* iOS設定
ビルド設定からプラットフォームをiOSに変更する。
【アセット】→【External Dependency Manager】→【iOS reolver】→【設定】→プルダウンからXcodeProjectを選択する。
【アセット】→【External Dependency Manager】→【iOS reolver】→【install cocoapods】を選択する。
これでiOSの初期設定は完了です。

* アプリIDの設定

アセット→Google mobile Ads → AdMobのアプリ設定からからアプリIDを確認しiOSとandroidそれぞれ記入する。
※記事にはenableにcheckを入れると書いてあるがそのような項目は見つからないためIDだけ入力することにする。

####　バナー広告実装

[](
こちらの記事よりバナー広告の実装をします.(https://qiita.com/Maru60014236/private/cb54133567529cca8d4b)
)

1. 広告用のオブジェクトを作成（小さなアプリなら広告関係をまとめて一つのオブジェクトで管理！）（今回はAdMobManager）
1. スクリプト作成（IDだけ変更して下記コードをコピペ）(AdMobBanner という名前で作成します。)
1. オブジェクトにスクリプトを割り当てる

``` C#
using UnityEngine;
using System;
using GoogleMobileAds.Api;

public class AdMobBanner : MonoBehaviour
{
    //やること
    //1.バナー広告IDを入力
    //2.バナーの表示位置　(現状表示位置は下になっています。)
    //3.バナー表示のタイミング (現状 起動直後になっています。)

    private BannerView bannerView;//BannerView型の変数bannerViewを宣言　この中にバナー広告の情報が入る


    //シーン読み込み時からバナーを表示する
    //最初からバナーを表示したくない場合はこの関数を消してください。
    private void Start()
    {
        RequestBanner();//アダプティブバナーを表示する関数 呼び出し
    }


    //ボタン等に割り付けて使用
    //バナーを表示する関数
    public void BannerStart()
    {
        RequestBanner();//アダプティブバナーを表示する関数 呼び出し       
    }

    //ボタン等に割り付けて使用
    //バナーを削除する関数
    public void BannerDestroy()
    {
        bannerView.Destroy();//バナー削除
    }

    //アダプティブバナーを表示する関数
    private void RequestBanner()
    {
        //AndroidとiOSで広告IDが違うのでプラットフォームで処理を分けます。
        // 参考
        //【Unity】AndroidとiOSで処理を分ける方法
        // https://marumaro7.hatenablog.com/entry/platformsyoriwakeru

#if UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/6300978111";//ここにAndroidのバナーIDを入力

#elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/2934735716";//ここにiOSのバナーIDを入力

#else
        string adUnitId = "unexpected_platform";
#endif

        // 新しい広告を表示する前にバナーを削除
        if (bannerView != null)//もし変数bannerViewの中にバナーの情報が入っていたら
        {
            bannerView.Destroy();//バナー削除
        }

        //現在の画面の向き横幅を取得しバナーサイズを決定
        AdSize adaptiveSize =
                AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth);


        //バナーを生成 new BannerView(バナーID,バナーサイズ,バナー表示位置)
        bannerView = new BannerView(adUnitId, adaptiveSize, AdPosition.Bottom);//バナー表示位置は
                                                                               //画面上に表示する場合：AdPosition.Top
                                                                               //画面下に表示する場合：AdPosition.Bottom


        //BannerView型の変数 bannerViewの各種状態 に関数を登録
        bannerView.OnAdLoaded += HandleAdLoaded;//bannerViewの状態が バナー表示完了 となった時に起動する関数(関数名HandleAdLoaded)を登録
        bannerView.OnAdFailedToLoad += HandleAdFailedToLoad;//bannerViewの状態が バナー読み込み失敗 となった時に起動する関数(関数名HandleAdFailedToLoad)を登録


        //リクエストを生成
        AdRequest adRequest = new AdRequest.Builder().Build();

        //広告表示
        bannerView.LoadAd(adRequest);
    }


    #region Banner callback handlers

    //バナー表示完了 となった時に起動する関数
    public void HandleAdLoaded(object sender, EventArgs args)
    {
        Debug.Log("バナー表示完了");
    }

    //バナー読み込み失敗 となった時に起動する関数
    public void HandleAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
    {        
        Debug.Log("バナー読み込み失敗" + args.LoadAdError);//args.LoadAdError:エラー内容 
    }

    #endregion

}
```

####　インタースティシャル広告実装
[](
こちらの記事よりインタースティシャル広告を実装します。（https://qiita.com/Maru60014236/private/cea412526723db40775e）
)

1. 広告用のオブジェクトを作成（小さなアプリなら広告関係をまとめて一つのオブジェクトで管理！）（今回はAdMobManager）
1. スクリプト作成（IDだけ変更して下記コードをコピペ）(AdMobInterstitial という名前で作成します。)
1. オブジェクトにスクリプトを割り当てる

``` C#
using UnityEngine;
using GoogleMobileAds.Api;
using System;

public class AdMobInterstitial : MonoBehaviour
{
    //やること
    //1.インタースティシャル広告IDの入力
    //2.インタースティシャル起動設定　ShowAdMobInterstitial()を使う

    private InterstitialAd interstitial;//InterstitialAd型の変数interstitialを宣言　この中にインタースティシャル広告の情報が入る

    private void Start()
    {
        RequestInterstitial();
        Debug.Log("読み込み開始");
    }

    //インタースティシャル広告を表示する関数
    //ボタンなどに割付けして使用
    public void ShowAdMobInterstitial()
    {
        //広告の読み込みが完了していたら広告表示
        if (interstitial.IsLoaded() == true)
        {
            interstitial.Show();
            Debug.Log("広告表示");
        }
        else
        {
            Debug.Log("広告読み込み未完了");
        }
    }


    //インタースティシャル広告を読み込む関数
    private void RequestInterstitial()
    {
        //AndroidとiOSで広告IDが違うのでプラットフォームで処理を分けます。
        // 参考
        //【Unity】AndroidとiOSで処理を分ける方法
        // https://marumaro7.hatenablog.com/entry/platformsyoriwakeru

#if UNITY_ANDROID
        string adUnitId = "ca-app-pub-3940256099942544/1033173712";//ここにAndroidのインタースティシャル広告IDを入力

#elif UNITY_IPHONE
        string adUnitId = "ca-app-pub-3940256099942544/4411468910";//ここにiOSのインタースティシャル広告IDを入力

#else
        string adUnitId = "unexpected_platform";
#endif

        //インタースティシャル広告初期化
        interstitial = new InterstitialAd(adUnitId);


        //InterstitialAd型の変数 interstitialの各種状態 に関数を登録
        interstitial.OnAdLoaded += HandleOnAdLoaded;//interstitialの状態が　インタースティシャル読み込み完了　となった時に起動する関数(関数名HandleOnAdLoaded)を登録
        interstitial.OnAdFailedToLoad += HandleOnAdFailedToLoad;//interstitialの状態が　インタースティシャル読み込み失敗 　となった時に起動する関数(関数名HandleOnAdFailedToLoad)を登録
        interstitial.OnAdClosed += HandleOnAdClosed;//interstitialの状態が  インタースティシャル表示終了　となった時に起動する関数(HandleOnAdClosed)を登録


        //リクエストを生成
        AdRequest request = new AdRequest.Builder().Build();
        //インタースティシャルにリクエストをロード
        interstitial.LoadAd(request);
    }

    //インタースティシャル読み込み完了 となった時に起動する関数
    public void HandleOnAdLoaded(object sender, EventArgs args)
    {        
        Debug.Log("インタースティシャル読み込み完了");
    }

    //インタースティシャル読み込み失敗 となった時に起動する関数
    public void HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args)
    {
        Debug.Log("インタースティシャル読み込み失敗" + args.LoadAdError);//args.LoadAdError:エラー内容 
    }


    //インタースティシャル表示終了 となった時に起動する関数
    public void HandleOnAdClosed(object sender, EventArgs args)
    {
        Debug.Log("インタースティシャル広告終了");

        //インタースティシャル広告は使い捨てなので一旦破棄
        interstitial.Destroy();

        //インタースティシャル再読み込み開始
        RequestInterstitial();
        Debug.Log("インタースティシャル広告再読み込み");
    }

}
```

####　リワード広告実装
[](
こちらの記事よりインタースティシャル広告を実装します。（https://qiita.com/Maru60014236/private/e86d88581526b037d895）
)

1. 広告用のオブジェクトを作成（小さなアプリなら広告関係をまとめて一つのオブジェクトで管理！）（今回はAdMobManager）
1. スクリプト作成（IDだけ変更して下記コードをコピペ）(AdMobReward という名前で作成します。)
1. オブジェクトにスクリプトを割り当てる

``` C# 
using UnityEngine;
using GoogleMobileAds.Api;
using System;

public class AdMobReward : MonoBehaviour
{
    //やること
    //1.リワード広告IDの入力
    //2.Update関数のif文内に報酬内容を入力
    //3.リワード起動設定　ShowAdMobReward()を使う


    private bool rewardeFlag=false;//リワード広告の報酬付与用　初期値はfalse

    private RewardedAd rewardedAd;//RewardedAd型の変数 rewardedAdを宣言 この中にリワード広告の情報が入る

    private string adUnitId;

    //リワード広告を表示する関数
    //ボタンに割付けして使用
    public void ShowAdMobReward()
    {
        //広告の読み込みが完了していたら広告表示
        if (rewardedAd.IsLoaded())
        {
            rewardedAd.Show();
            Debug.Log("リワード広告表示");
        }
        else
        {
            Debug.Log("リワード広告読み込み未完了");
        }
    }


    private void Update()
    {
        //広告を見た後にrewardeFlagをtrueにしている
        //広告を見たらこの中の処理が実行される
        if (rewardeFlag == true)
        {
            rewardeFlag = false;//報酬付与用のフラグをfalseへ戻す

            //ここに報酬の処理を書く
        }

    }


    private void Start()
    {      
        //AndroidとiOSで広告IDが違うのでプラットフォームで処理を分けます。
        // 参考
        //【Unity】AndroidとiOSで処理を分ける方法
        // https://marumaro7.hatenablog.com/entry/platformsyoriwakeru

#if UNITY_ANDROID
        adUnitId = "ca-app-pub-3940256099942544/5224354917";//ここにAndroidのリワード広告IDを入力
#elif UNITY_IPHONE
        adUnitId = "ca-app-pub-3940256099942544/1712485313";//ここにiOSのリワード広告IDを入力
#else
        adUnitId = "unexpected_platform";
#endif

        CreateAndLoadRewardedAd();//リワード広告読み込み
    }

    //リワード広告読み込む関数
    public void CreateAndLoadRewardedAd()
    {
        //リワード広告初期化
        rewardedAd = new RewardedAd(adUnitId);

        //RewardedAd型の変数 rewardedAdの各種状態 に関数を登録
        rewardedAd.OnAdLoaded += HandleRewardedAdLoaded;//rewardedAdの状態が リワード広告読み込み完了 となった時に起動する関数(関数名HandleRewardedAdLoaded)を登録
        rewardedAd.OnAdFailedToLoad += HandleRewardedAdFailedToLoad;//rewardedAdの状態が　リワード広告読み込み失敗 　となった時に起動する関数(関数名HandleRewardedAdFailedToLoad)を登録
        rewardedAd.OnAdClosed += HandleRewardedAdClosed;//rewardedAdの状態が  リワード広告閉じられた　となった時に起動する関数(関数名HandleRewardedAdFailedToLoad)を登録
        rewardedAd.OnUserEarnedReward += HandleUserEarnedReward;//rewardedAdの状態が ユーザーの報酬処理　となった時に起動する関数(関数名HandleUserEarnedReward)を登録


        //リクエストを生成
        AdRequest request = new AdRequest.Builder().Build();
        //リクエストと共にリワード広告をロード
        rewardedAd.LoadAd(request);
    }


    //リワード読み込み完了 となった時に起動する関数
    public void HandleRewardedAdLoaded(object sender, EventArgs args)
    {
        Debug.Log("リワード広告読み込み完了");
    }

    //リワード読み込み失敗 となった時に起動する関数
    public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args)
    {
        Debug.Log("リワード広告読み込み失敗" + args.Message);//args.Message:エラー内容 
    }

    //リワード広告閉じられた時に起動する関数
    public void HandleRewardedAdClosed(object sender, EventArgs args)
    {
        Debug.Log("リワード広告閉じられる");

        //広告再読み込み
        CreateAndLoadRewardedAd();
    }

    //ユーザーの報酬処理 となった時に起動する関数
    public void HandleUserEarnedReward(object sender, Reward args)
    {
        Debug.Log("報酬受け取り");

        //この関数内ではゲームオブジェクトの操作ができない
        //そのため、ここでは報酬受け取りのフラグをtrueにするだけにする
        //具体的な処理はUpdate関数内で行う。
        rewardeFlag = true;
    }


}
```


####　実機確認

* android

[](
android の実機確認はこちらの記事を参考に実装します。（https://qiita.com/Maru60014236/private/a34234a9ac7f19297034）
)

##### 端末の準備
1. 開発者向けオプションを有効にする

「設定」→「システム」→「端末情報」→「ビルド番号を`7回`タップ」
「開発者向けオプション」→「USBデバッッグをON」
PCと端末をコードで　接続→あらわれるメニューをタップ→MIDIモードを選択
※macの場合androidに認識されないのでアプリを入れてあげましょう。
Android File Transfer（https://www.android.com/filetransfer/）
※現在macでの接続確認ができていないため随時更新

-- 追記

現在2代のadndroidテスト環境があるのですがそれぞれ問題点がありました。

1代目　富士通 Arrows M03
こちらは2016年発売の少し古い機種だからかPCと接続してもmac側でandroidを検知でできずにビルドに失敗しました。

2代目「Redmi 9T」（Xiaomi Communications製)
こちらは2021年発売の最新の機種です。（実機確認用に新しく購入）
こちらはmac側が読み取ることに成功したのですが、Xiaomiの製品はUSBでデバックをしようとすると何故かSIMカードが挿入されていることが求められたので現在格安SIMの契約申請中です。


#### Unity側の設定
1. プラットフォームをandroidに変更
1. プレイヤー設定よりパッケージ名を変更企業名は好きな開発者のハンドルネームを好きな形で入力
1. 画面自動回転設定（任意）
1. ビルド！

* iOS
[](
iosの実機確認はこちらの記事を参考に実装します（https://qiita.com/Maru60014236/private/0efa7d9dd0397027de18）
)
1. Apple Developer 登録
1. Xcodeインストール

##### Unity側の設定

1. プラットフォームをiOSに変更
1. パッケージ名を変更
1. 署名チームID設定(appDeveloperのTeamID)
1. ビルド！（フォルダ名_iOSとファイル名をしておくとわかりやすい！）

##### Xcode側の設定

1. Xcodeファイル起動
1. アカウントサインイン確認
1. ビルド先決定
1. 実行ボタン押す

##### Xcodeでビルドはサクセスになるのに動かない。
[The Google Mobile Ads SDK was initialized incorrectly.]
といったエラーが出ている場合。
XcodeよりInfo.plistを修正してあげましょう。

![スクリーンショット 2021-08-19 19.53.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615043/361eb1f5-cea2-3169-c0c5-10d7a0756b43.png)

+ボタンをクリックして

keyのところに`GADApplicationIdentifier`をvalueのところに`アプリID`を追加すれば解決します！
※同じところに`Privacy - Tracking Usage Description`をvalueのところに`あなたの好みに合わせた広告を表示するために使用されます`を追加する作業もテンプレのように必要です。
※アーカイブが表示されないときは「ウィンドウ」→「オーガナイザー」で表示可能。
ついでにトラッキングの設定も追加しておきましょう。
参考（https://marumaro7.hatenablog.com/entry/idfa_att）

## ストアへのリリース

### 共通設定
#### アイコンの設定
ビルド設定→プレイヤーの設定よりアイコンの設定
#### スクリーンショットの準備
ios,androidともに3種×2枚は必要です。
* 1334×750 portrait
* Xs Max 2688×  portrait
* iPadPro 2732× portrait

###android
* Googleデベロッパーの登録
* GooflePlayConsoleの入力
* 
[](
https://qiita.com/Maru60014236/private/ae4de47dbc25f042d6b1
)

#### アプリのファイル作成
[](
https://qiita.com/Maru60014236/private/983f1a79a573890ec26e
)

1. プラットフォームをAndroidに変更
1. (任意)AppBundleをビルドにチェック
1. ターゲットAPIレベル変更を最上のものに変更
1. 64ビット版への変更
・プレイヤー設定＞その他の設定＞スクリプティングバックエンド＞IL2CPPへ変更
・プレイヤー設定＞その他の設定＞ターゲットアーキテクチャ
　●ARMv7のチェック外す
　(入れてても問題無いと思いますが、ビルドエラーが出ることがあったので私は外しています。)
　●ARMv64のチェック入れる

5. 公開鍵の設定
プレイヤー設定＞公開設定＞キーストアマネージャー
＞新規作成
＞任意の場所
＞「user.keystore」と入力する。（拡張子をkeystoreにしたい）
＞ファイルの場所をなくさない場所に保存(重要)

キーストアマネージャー入力(Passwodord, Confirmpassword, alias, Passwodord, Confirmpassword, First and Last Name, Organization(空白でもOK))

6. ビルド！！

### iOS
#### apple developre登録
#### 証明書の作成
https://marumaro7.hatenablog.com/entry/2020/06/23/224837?_ga=2.117378114.572655050.1619616748-61554812.1592315812

#### app IDの作成
https://marumaro7.hatenablog.com/entry/2020/06/23/234655

#### profileの作成
https://marumaro7.hatenablog.com/entry/2020/06/24/001020

#### Xcodeファイルの作成＆　AppStoreConnectへのアップロード
https://marumaro7.hatenablog.com/entry/2020/06/24/005439?_ga=2.75456854.572655050.1619616748-61554812.1592315812

appleの管理画面で間違えてBundleIDを設定してしまいアーカイブを作成することはできるのにバリデーションできない、、
→こちらの記事を参照し解決（ https://qiita.com/BMJr/items/ff51f9fa4d8eab957222 ）

## リリース後広告設定
 

## 開発編
### ボタンを丸に変更
#### パターン1
個人的には汎用的だからこっちで実装するのがおすすめ。

https://note.com/hikohiro/n/n9100eae28208
#### パターン2
https://note.com/hikohiro/n/n4dfce7380e42

#### 一定時間後に処理を実装

https://qiita.com/toRisouP/items/e402b15b36a8f9097ee9#invoke%E3%82%92%E4%BD%BF%E3%81%86

#### ユーザーに値を紐づける

https://www.sejuku.net/blog/69991

#### アニメーションを任意のタイミングで開始、終了する


## 参照

https://www.udemy.com/course/unity_app_increase_profit/