【Unity Ads】シーン遷移のあるモバイルゲームで広告実装しようとしたら苦戦したお話

Unity Adsが上手く実装できない!

ある程度のゲームになってくると、「タイトル画面→モード選択画面→プレイ画面→(終了後)モード選択画面」とシーンを複数作成して画面遷移することが多いかと思います。

シーン遷移が発生するプロジェクトにおいて、Unity Adsを適用する際、ちょっとテンプレートに対して改良が必要でした。

Unity側で用意されているサンプルも、検索して出てくる情報もあまりその辺を書かれているものが少なかったので備忘録も兼ねて記事にします。

UnityやC#に慣れている人にとっては当たり前の話かもしれません。これからUnityでマネタイズしたい、けど何か上手くいかなかったという、私のようなUnity初心者の方向けの記事です。

◆Unity2021.3.11f1
◆Unity Hub 3.3.0

Unity Adsって?

Unity Adsが何かわかっている人は本章は読み飛ばしてよいです。
実はUnity Adsは古い呼び名であり、今はUnity Monetizationが正式名称らしいです。

無料アプリを使用した際に上部や下部にバナー広告があったり、プレイしていると急に広告が出てきたり、何かログインボーナスのようなものを得るために広告を見たことがある方も多いのではないでしょうか?

その広告をUnity上で簡単に実装できるようにした仕組みがUnity Adsです。

Unity Ads - Unity マニュアル (unity3d.com)

Unity Adsで何が詰まったか?

私は下記のキャラクター物のマインスイーパーアプリを作成してリリースしました。

1日のプレイ回数を2回に制限しているのですが、広告再生のボタンをクリックするとプレイ回数が回復する構成にしています。

モード選択画面スクリーンショット

Unity Hub内のMobile Monetizationというテンプレートを使用して、この広告を実装しようとしたのですが、以下問題点があり苦戦する羽目に。

・テンプレートでは広告の読み込みボタン→広告の再生ボタンという構成になっている
わざわざユーザーに2回もボタンを押すUI構成にはしたくない。
広告の再生準備はモード選択画面に入ったときに自動的にしたい。

・別のシーンに遷移してから戻ってくると広告再生が出来ない
起動してからの初回表示時は正しく動いたが、一度タイトル画面に戻ったりゲーム画面に移ってから、再度モード選択画面に戻ると広告が再生出来なくなりました。
※回数制限回復制度をとっている本アプリでは致命的なバグでした。

おそらく、どちらか1つだけ引っかかったという人も多いと思うので1つずつ解消していきます。

まずはテンプレを利用したプロジェクトの作成

最初にUnity Hub内のテンプレを使用してプロジェクトを作成しましょう。
既にもうゲームは作ってあって、そこにAds入れたいんだけど…という人は一旦作ったプロジェクト全体をunitypackage化して、新しく作ったテンプレプロジェクト内にインポートして移植した方がスムーズかと思います。

Unity HubでMobile Monetizationのサンプルを選択し、プロジェクトを作成しましょう。

プロジェクトの作成

すると、このような画面が出てきたかと思います。
検索すると同じような情報がありますが、一応初期のセットアップ方法も書いておきます。

1.Get Startedを選択

2.Project Setting-ADS設定画面が自動で出てくるので、Unity Organizationsを選択 & Create New Projectを選択
まだOrganizationのIDを作成していない人はこちらを参考にID登録をしてください。
monetization getting started · unity3d-jp/unityads-help-jp Wiki (github.com)

3.ゲームが13歳未満を対象としているか選択
アメリカの児童の個人情報保護を目的とした法律に適合するために必要みたいです。

4.Adsをオンに変更する & Enable test modeにチェックを入れる
Adsをオンにすると自動的にGame Idというものが発行されます。ついでにEnable test modeにチェックを入れておきましょう。実機で動作確認をすることがあるかと思いますが、これにチェックを入れずに本番の広告を繰り返しテスト環境で再生してしまうと不正アクセスとしてアカウント停止されることもあるとのこと。注意しましょう。

ここまで来たら試しに再生ボタンで広告が使えるか試してみましょう。
リワード広告であればこのような画面が出ればOKです。

リワード広告サンプル画面

さて、ようやく本題ですね。1つずつサンプルの問題を解消していきましょう。

「テンプレートでは広告の読み込みボタン→広告の再生ボタンという構成になっている」問題

サンプルを触ればわかるかと思いますが、わざわざユーザーに広告ロードボタンなんて押させたくないですよね。
ということでシーン読み込み時に、自動で読み込むようにしましょう。

今回はリワード広告のみを対象にしていますが、他の広告タイプでもほぼ同様のやり方でOKです。

Scripts -> Ad ExamplesからRewarded Ad Exampleを開きます。
スクリプト内にある LoadAdButtonや_loadAdButtonを使用しているスクリプトを全てコメントアウトまたは削除していまいましょう。
最初の_loadAdButtonの変数定義をコメントアウトすると、一気にエラーとして該当する場所が出てきます。

最初の変数定義をコメントアウト
あとはエラーに従って全てコメントアウト

このloadAdButtonが何をしていたかというとボタンを押した際に、スクリプト内のLoadAd()関数を実行していました。
そのため、これをシーン読み込み時に自動で実行するようにします。

何やら注意書きが

この関数には「ちゃんとADSを初期化してから実行してね!」と注意書きがあります。このADSの初期化はシーン読み込み時にScripts内にあるAdsController.csで実行されています。
そのため、この初期化よりも後にLoadAd()を実行する必要がありますね。

必ずAds初期化はすぐに終わるので、ひとまずここではシーン読み込みから1秒後にAds読み込みを実行するようにしておけば良いでしょう。
※初期化に時間がかかる場合や、全く通信できない状態の時を考慮するのであればasync/awaitやフラグ処理等をしてケアしてください。個人的には初期化失敗しても広告再生できないだけなので、シンプルに時間遅延処理で良いんじゃないかと思います。

private void Start()
    {
        Invoke("LoadAd", 1.0f);
    }

これで読み込みボタンを使わず、広告が再生できるようになりました。

LoadRewardボタンをInactive化して消しても問題なく広告再生できた

「別のシーンに遷移してから戻ってくると広告再生が出来ない」問題

さて、これで広告の実装は出来そう!
モード選択画面にボタンを移植して、広告再生もできることを確認した。
これでOK!かと思いきや、罠があります。
一度別のシーンに遷移してから戻ってくると広告再生が出来なくなっているのです。

下記はモード選択画面を簡易的に作成したものです。
PlayGameボタンを押すと、別のPlayGameシーンに遷移し、その先にはモード選択画面に戻るボタンが配置してあります。

モード選択画面に最初に入ったときは問題なく広告も再生出来たのに、一度PlayGameシーンに遷移してから、戻ってくると広告再生ボタンが押しても再生されません。

何故か広告再生ボタンを押しても反応がない

デバックログをよく見てみると、最初はinitialization complete. -> Loading Ad.となっているのに、2回目の読み込み時にはinitialization completeがありません。
このinitialization completeのデバックログはAdsControllerが出力しています。該当の箇所を確認すると、、、

ここでボタンのリセット処理をしている

ありました。
initialization completeのログが出ていないということは、ここのボタンの初期化処理もしていません。
詳細は分かりませんが、AdsControllerでのAds初期化処理は1度しか実行されず、2回目以降はOnInitializationCompleteのイベントが発生しないためでしょう。

この初期化処理が実行されないと、ボタンを押してもShowAd関数が実行されません。

Initialize関数でボタンに広告再生実行を割り当てている

よって、このボタン初期化の処理はRewardスクリプト側に入れてしまいます。AdsControllerからはボタンの初期化処理を削除します。

ボタンの初期化はAdsControllerではしない
AdsControllerの最初のボタンの変数定義もまるっと削除できます。

そして、AdsControllerで実行していたボタンの初期化処理はReward側に移管。
広告読み込み後にボタンを初期化するようにLoadAd()の最後にInitialize()を実行すれば良いかと。

Rewardスクリプト側でInitializeを実行する
ちゃんとシーン遷移後も広告再生できるようになりました。

ちなみにこれをすることで完全にボタンや広告表示側の処理と、AdsControllerが分離出来ています。
そのため、AdsControllerはRewardよりも前に実行さえすれば、わざわざ広Rewardスクリプトと同じシーンにいる必要もありません。
よって、AdsController.csはタイトル画面等の最初に実行されるシーンに移しておくと良いと思います。

タイトル画面のシーンにはAds Controller.csを
モードセレクト画面ではRewardスクリプトを

このようにすることで無駄な初期化を実行しないという利点と、必ずAdsConrollerが先に実行されることが確定することで、1つ目の問題の対策として実施していたLoadAdの遅延処理が不要になり、Start()で即時読み込みでOKになります。

    private void Start()
    {
        //AdsController.csが先に実行されるのであれば遅延しなくてよい
        //Invoke("LoadAd", 1.0f);
        LoadAd();
    }

最後に

広告の実装でシーンを遷移するようにした場合、少しだけ罠がありましたというお話でした。
同じように苦戦する人がいた際に助けになれば幸いです。

なお、サンプルとして冒頭紹介したアプリですが、アプリの良い/悪い以前の問題で、あまりにもマインスイーパーの競合が多すぎて検索にすら出てこないという大爆死をしております。(笑)
※Google Play Store内で検索してアクセスされた回数が0という衝撃的な状況。

ストア検索で少しでも上の順位になるよう、もし記事が役に立ったという方は暇つぶし程度にダウンロード&評価してもらえると更に幸いです。(Androidのみ)

競合の多いジャンルのアプリなんて作るもんじゃないですね(戒め)


この記事が気に入ったらサポートをしてみませんか?