『ユニテのひみつ』のひみつ 3 広告表示

先日、RPG MAKER UNITEで作成したスマホ向けのアプリ『ユニテのひみつ』をリリースしました。

Android
https://play.google.com/store/apps/details?id=jp.windbellrrr.app.unite.basic

iOS
https://apps.apple.com/app/secret-of-unite/id6450209741

本エントリは『ユニテのひみつ』作る際に、どのような改造をUNITEへしたのか、また、どんなアドオンを作成したのかを、何回かに分けて解説していく内容の第三回となります。

※ホントは毎日更新しようと思っていたのですが、一部の界隈で話題になっていた「太ったおばさん」の作品を読んでいたら、日記を書く時間が取れませんでした。

使用している広告について

『ユニテのひみつ』は無料のスマホアプリとしてリリースしようと考えていたので、やはり広告を入れたいと思い、使用経験のあるAdMobを選択しました。
AdMobには、Unity向けのプラグインが用意されているので、プログラムがわかる方なら比較的簡単()にゲームの中に広告を組み込むことができます。

AdMob > Mobile Ads SDK (Unity)
https://developers.google.com/admob/unity/quick-start?hl=ja

『ユニテのひみつ』では以下の3つのタイプの広告を自作のアドオンによって表示させています。

・アプリ起動時広告 
プレイヤーがアプリをフォアグラウンドに戻したときに表示される広告です。
プレイヤーがゲームを一時中断し、再度ゲームを復帰させたタイミングで表示されます。

・インタースティシャル広告
画面遷移のタイミング等で表示するための広告です。
『ユニテのひみつ』では、2番目のマップから3番目のマップへ移動する時と、4番目のマップで回答をミスった時、*番目のマップから元の場所へ戻る時に表示しています。

・リワード広告
広告を(最後まで)見ることによって報酬が得られるタイプの広告です。
『ユニテのひみつ』では、3番目のマップである目的を達成したい時と、4番目のマップでヒントをもらいたいときに、プレイヤーの意志によって見ることができます。

自作のアドオンについて

『ユニテのひみつ』では、広告を表示するためのアドオンを新規に作成しました。
このアドオンは、AdMobのUnity向けプラグインと連携して広告を表示します。

このアドオンには以下のような設定項目があります。

・テスト広告を使うかどうか
 オンにするとすべての広告にテストIDを使用します
・起動時に自動で広告初期化処理を行うどうか
 オンにすると、アドオン初期化時にすべての広告の初期化処理(ロード処理)を自動で行います
 『ユニテのひみつ』ではオフにして、必要に応じて初期化処理を実行しています
・アプリ起動時/インタースティシャル/リワード広告を使うかどうか
 それぞれの広告を使用するかどうかを設定します
 自動で初期化を行う場合にこの設定を参照します
・各広告用のID
 各広告用に用意されたIDを設定します
 それぞれの広告タイプに対し、Android用、iOS用を設定できます
・テストデバイスのID
 Android/iOSのテストデバイスのIDを設定します(現在はそれぞれ一台分のみ設定可能)
FPS表示
 FPSを表示するかどうかを設定します
 広告表示のアドオンにこの機能がある必然性はないのですが、デバッグ中にあるとめちゃめちゃ便利なので、結局最後まで外せませんでした。

また、このアドオンには以下のようなイベントコマンドとして使えるアドオンコマンドがあります。

・インタースティシャル/リワード広告初期化
 引数:非同期で結果を受け取るための変数のID
 インタースティシャル/リワード広告を初期化(ダウンロード)します。
 結果は非同期で指定した変数に設定されます。
 ※結果は非同期で返るため、別途専用のイベントで判定する必要があります
・インタースティシャル広告表示
 引数:結果を受け取るための変数のID
 ダウンロード済みの広告を表示します。
・リワード広告表示
 引数:非同期で結果を受け取るための変数のID
 ダウンロード済みの広告を表示します。
 リワード広告の結果はほとんどのケースで非同期で返るため、別途専用のイベントで判定しています。
FPS表示切替
 FPSの表示状態を変更します。
 イベントのコマンドでFPS表示を切り替えられますが、『ユニテのひみつ』では使っていません。
 『ユニテのひみつ』ではタイトルに専用のボタンを設けて表示/非表示を切り替えられるようにしていますが、これは独自実装のプログラムからこのアドオンのイベントコマンド用関数を呼び出しています。

なお、アドオン作成の際、鈴木YE(役演亭)様の以下の記事を参考にさせていただきました。ありがとうございます。
https://yakuentei.jp/article/gamedev/unity_rmu_addon/

広告SDKとの連携

広告は別途初期化(広告データのダウンロード)しないと表示できません。
よって、まず初期化処理を行い、それが成功した後、初めて表示できるようになります。
『ユニテのひみつ』では、以下のようにアドオンコマンドを呼び出して、広告を初期化するタイミングと表示するタイミングを分けています。

・いもうとの部屋
いもうとがパーティに加わったタイミングで変数の値を変化させ、その変数の値を条件にして出現するイベントで一連の初期化処理とともにインタースティシャル広告初期化コマンドを呼び出し、広告をダウンロードしています。

変数の値によって出現する広告初期化用イベント

変数の値によって出現する広告初期化用イベント

初期化処理の結果は水晶玉みたいなオブジェクトのイベントで受け、結果の値に応じて玉の画像を変更しています(成功なら緑、失敗なら赤)。

インタースティシャル広告初期化成功時の水晶玉

インタースティシャル広告初期化成功時の水晶玉

いもうとが言っていた水晶玉に関するなんだかよくわからないセリフを見た人もいるかもしれませんが、このことを示していたんですね。
そして、この部屋から脱出するタイミングで、広告を表示しています。

シャロンの部屋
部屋に入ったタイミングで二人のセリフが流れますが、これが終わったタイミングでスイッチをオンにし、それを条件にしてリワード広告初期化コマンドを呼び出し、広告をダウンロードしています。
この部屋ではマップの上の方にある照明(籠に入った薪を燃やすタイプのもの)で初期化の成否がわかるようになっています(成功していたら火が燃えて、失敗すると火が消える)。

リワード広告初期化成功時(灯りがともる)

リワード広告初期化成功時(灯りがともる)

そしてあることをした後でシャロンに話しかけると、広告を見るかどうかを確認されます。
リワード広告は、報酬を得たいプレイヤーが自ら見ることを選ぶタイプの広告であるため、このように選択肢を出してプレイヤーに表示するかどうかをゆだねています。
そして広告を最後まで見終わると、成功の結果が変数に設定されるので、それを条件にして出現するイベントでシナリオを進めるようにしています。
※漫画アプリなどでよくある一日一回ポイントがもらえる動画広告がリワード広告です。パズルゲーム等でスタミナを回復するために見る広告などもリワード広告になります。

広告表示アドオン公開の難しさ

広告表示アドオンは、当初うまく実装できたら公開しようと思っていたのですが、現在はいくつかの理由により公開予定はありません。
その理由を簡単に説明すると、以下となります。
「現在のアドオンでは、広告関連で必要になるすべての問題を解決できていない」
「このアドオンさえ入れれば誰でも簡単に広告が出せるようになるわけではない」

以下が理由の詳細となります。

・別途広告SDKをインポートする必要がある
上の方でもリンクを張っていますが、AdMobから提供されている「Mobile Ads SDK (Unity)」を別途プロジェクトにインポートする必要があります。

AdMob > Mobile Ads SDK (Unity)
https://developers.google.com/admob/unity/quick-start?hl=ja

これは、広告表示アドオンをインポートする「前」に、インポートする必要があります。広告SDKをインポートする前に広告表示アドオンをインポートしてしまうと、ビルドエラーが発生し、ゲームが実行できない状態に陥ります。
また、広告SDKをインポートするだけでAndroidビルドがエラーになったりします。
通常は新規に広告を組み込むケースならエラーにならないことが多いのですが、今回はエラーとなったので驚きました(しかも見たことないエラーが出ていました)(※1)。
さらに、ビルドが通っても、実際には広告が表示されないというケースにも遭遇しました(※2)。
これらは自力で(エラーメッセージをググったりして)解決する必要がありますが、Unity使いで広告実装経験のある方ならまだしも、純粋なツクラーの方だとおそらくこの段階で躓いてしまうと思われます。

※1:今回Androidビルド時に遭遇したエラーの内容は以下の通り
WARNING: The option setting 'android.enableR8=false' is deprecated.
It will be removed in version 5.0 of the Android Gradle plugin.
You will no longer be able to disable R8
対処方法:
Minimum API Levelをあげる(Player Settings>Other Settings>Identification内)
Android 5.1 Lolipop (API level 22)」→  「Android 7.0 ‘Nougat'(API level 24)」
参考:  https://teammoko.jp/unity_error_asm7

※2:実行時ログを確認したところ、初期化のあたりでエラーが発生している模様
java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/lifecycle/DefaultLifecycleObserver;
対処方法:
最近のSDKへのコミットで削除されている依存関係の記述を復活させる
参考:
説明→ https://github.com/googleads/googleads-mobile-unity/issues/2645
取り込むべき差分→ https://github.com/googleads/googleads-mobile-unity/commit/598e82e48b7b19ba8bbc3d4c6a70fa9b27d4fe63

・別途AdMobのアカウントや広告IDの取得が必要
アプリでAdMobの広告を表示するためには、AdMobのアカウントを作成し、AdMobの管理画面でアプリを追加し、広告ユニットを追加し……といった作業が別途必要です。

AdMob スタートガイド
https://support.google.com/admob/?hl=ja#topic=7383088

ググればやり方を説明しているサイトは見つかりますし、そこまで難しい作業でもありません。
ただ、何も知らない方が初めてそれらの作業を行う場合、いろいろ躓きポイントがあるのではと予想されます。

・広告関連で必要になるすべての処理が現在アドオンでまかなえていない
本来は広告関連で必要になるすべての処理をアドオンでまかなう必要がありますが、現在それができていません。
具体的に言うと、iOSで必要になるIDFA関連メッセージ表示処理周りです。
現在は以下のような実装で行っています。
Objective-Cで実装されたIDFAダイアログ表示関数を持つソースをPlugin/iOS配下に配置
・上記関数をキックするためのC#スクリプトをアドオンとは別に作成(以前使っていたものを流用)
・上記C#スクリプトをアタッチしたオブジェクトをTitleシーンに配置(Titleシーンの改造)
・IDFA用の各言語用のテキストをUnityのLocalization機能で定義(アドオン外の機能でテキストを定義)
・上記だけだとAppStoreアップロード時何故かエラーになるため、別途Xcode上でIDFAメッセージ(のダミーデータ)をinfo.plistへ追加
※一番上はアドオンパッケージに含めれば良いだけで、それ以外もアドオン側に組み込むことはやろうと思えばおそらく可能なはず。現在は面倒なのでやってないだけです。

また、アプリ公開の数日後、突然AdMob管理画面に以下のような表示が出てきました。

AdMobで今後必要になると思われるGDPRメッセージ対応

AdMobで今後必要になると思われるGDPRメッセージ対応

これはどうやら、今後AdMob広告を一部の国(EEA(欧州経済領域)および英国)向けに配信する場合、対応が必須となるGDPRメッセージ対応に関する警告のようです。
これに関しては全く未知でしたので、今後対応を考える必要があります。
もちろん現在の広告表示アドオン内には、このGDPRメッセージ対応は含まれていません。

GDPRメッセージ対応に関するドキュメントはこちら(自分用のメモ)
https://support.google.com/admob/answer/10113207

GDPRメッセージ対応に関するUnity向けのドキュメントはこちら(自分用のメモ)
https://developers.google.com/admob/unity/privacy?hl=ja

※め、めんどくさそう…

・広告を表示するにあたり、学ばなければならないルールがある
AdMobには広告を表示するためのルール(ポリシー)があり、それに準拠する必要があります。

AdMobヘルプ ポリシー
https://support.google.com/admob/?hl=ja#topic=2745287

これは別途利用する方それぞれが学ばなければなりません。
また、アプリの開発中に本番の広告を表示すると、アカウントをBANされるおそれがあります。
そのため、開発中はテスト広告を有効にしたり、開発に使うスマホのテストデバイスIDを(広告を組み込んだアプリを実行した際に出力されるログを確認して)登録し、テスト広告を表示できる状態でテストする必要があります。
スマホのテストデバイスIDを確認するには、Androidならコンソールやコマンドプロンプトからadbコマンドを使います。iOSならXcode上でログを確認します。
ログを確認するだけでも、Android/iOS開発の基礎的な知識が必要になってきます。

・そもそもGoogle PlayやAppStoreにアプリをリリースするためにはいろいろな作業が必要
これは広告とは直接関係ないですが、スマホアプリをリリースしたことのない方が、Google PlayやAppStoreでアプリをリリースする場合、さまざまな作業が必要になります。
まず開発用アカウントを用意する必要があります。
次にリリースするアプリを専用の管理画面で登録し、アプリのスクショや説明文などを登録する必要があります。
また、広告を利用する場合、さらに面倒な質問に答える必要があります(GooglePlayの場合は「ポリシーとプログラム>アプリのコンテンツ」周り)。
このあたりにもたくさんの躓きポイントが予想されます。

また、GooglePlayにアプリをリリースするには、アプリのダウンロードサイズを150MB以下にする必要があります。
現在、「基本アセットのみ」で新規作成したUNITEのプロジェクトに最低限のイベントだけ入れてビルドすると、700MBを超えるサイズのバイナリが生成されます。これをどうにか150MB以下になるまで削る作業が発生します。
※詳しくは以前私が書いた記事「RPG Maker Uniteで実行バイナリサイズ削減チャレンジ」を参照願います。

このように、スマホアプリで広告を表示するには、クリアすべき様々な工程があります。
私の方で「広告関連で必要になるすべての処理」をうまい具合にアドオンに取り込むことができたとしても、上記のあらゆる工程で躓いてしまう人が出てくることが予想されます。
それらの方がアドオン公開者である私にサポートを求めてきたら……と考えると、公開するのはちょっと難しいです。
以上がアドオンを公開しない理由となります。

終わりに

いろいろ書いてしまいましたが、上記の内容は、あくまでAdMob広告やスマホアプリに関する知識のない純粋なツクラーの方が広告表示に当たって越えなければならないハードルの話です。
Unityに慣れていて、広告ライブラリの利用経験がある方なら、広告表示アドオンを作るのは難しくないです。
広告の魅力は、やはり「収益が得られる」ことだと思います。
そのために、さまざまハードルを越える価値はきっとあるはずです。
この記事が少しでもそのための助けになれば幸いです。