hyoromoのブログ

最近はVRSNS向けに作ったものについて書いています

Unityでカジュアルゲームのアウトゲーム開発


カジュアルゲームを開発する時にだいたい必要になってくるアウトゲーム部分にスポットを当て、カジュアルゲームである「TAMATH」アプリ開発時にどういった機能を実装したか書きます。

開発環境
  • Unity2022.3.11f1
ゲーム仕様

「TAMATH」は10年くらい前に流行ってた数学問題を早解きするゲームです。
9マスのパネルを指でなぞり、お題に出された数字になるよう数式を一筆書きで作るゲームとなっています。
youtu.be

ここから先の内容を把握するために1度ゲームをプレイする事をオススメします。1プレイ後にお進みください。
App Storeページ
Google Playページ


シンプルなインゲームに対し、以下のアウトゲームを実装しています。

  • ローカライズ
  • ランキング
  • アプリ内課金
  • 広告
  • シェア機能
  • システムUI(マルチ解像度対応)

では、それぞれどのような実装を行ったか項目ごとに掘り下げて書いていきます。

ローカライズ

Unity公式が提供してくれているLocalizationパッケージを使用してローカライズ対応を行いました。

各言語のテキスト入稿方法は2種類あります。

  • 方法その1

    対応言語を登録すると表にKey/各言語テキストが登録可能になります。登録したテキストはコードから呼び出し可能です
  • 方法その2

    Track ChangesをONにしている間、「表示したいテキスト」「フォントサイズ」「座標」等をInspectorから変更すると変更内容がActive Locale言語として登録されます。テキスト自体は「その1」の表に書き出され、フォントサイズ/座標等は対象コンポーネントに情報がアタッチされます

TextMeshProで各言語を綺麗に表示させたい場合、メインとなるFont Assetを決め、対象AssetのInspectorからFallback Font Assetsを設定するとメインから順に表示する文字コードが無ければ順にFont Assetをチェックしていきます。

注意点としては別々のフォントファミリーを設定した場合、例えばアルファベットと漢字が印象の異なる見た目になってしまいます。なので、例えばNoto Sansなどのサポート言語幅の多いフォントを扱うと良いです。

アプリ起動時に端末言語を元に自動的に言語切替を行ったり、アプリ上で言語切替を追加してコードで手動切替する事も可能です。方法はマニュアルを参照ください。
Localizationを全部語ると1エントリー分の分量になるため、全容を書くのはまたの機会にしておきます。

ランキング


こちらもUnity公式が提供してくれているLeaderboardsパッケージを使っています。
主に以下の機能が提供されています。

  • 表示スコアは「最高スコア」「最後のスコア」「総合したスコア」の3種類から選べる
  • スコアの並び順は「高い順」「低い順」の2種類から選べる
  • リセットするかは「しない」「定期的(n分/n時間/n日/n週間/nヶ月)」「指定した日に1度だけ」
  • リセットしたランキングをアーカイブ*1「する」「しない」
  • プレイヤーの順に応じた階層分け*2を「する」「しない」
  • 開発環境と本番環境を分けることが出来る
  • プレイヤー名を手動設定できる*3

Unity Gaming ServicesからLeaderboardsを有効にすることで利用可能です。
Web上の管理画面からリーダーボードを新規作成し、コード上からは対象リーダーボードIDに対してスコアを送信したり取得するだけ。とっても簡単に実装できます。

こちらも全部語ると1エントリー分の分量になるため、全容を書くのはまたの機会にしておきます。

ローカル通知

これまたUnity公式が提供してくれているMobile Notificationsパッケージを使いました。


ProjectSettingsのMobile NotificationsからiOS/Androidそれぞれの設定を行い、提供されているAPIで通知設定してあげるだけです。

Androidでは注意点が2つあります。

  • Androidは通知アイコンが基本モノクロな点。なので、色鮮やかにしたり背景ベタ塗りすると何なのか分からなくなります。
  • Android13から、プッシュ通知のユーザー許諾が必須となっています。以下をコールするだけで良いのですが、これを忘れると機能しなくなるので注意です。
new PermissionRequest();
アプリ内課金

Unity公式が提供してくれているIn App Purchasingパッケージを使います。

ざっくり使い方説明
1. Unity上のPackage Managerから最新の「In App Purchasing」をインポート
3. Project Settings > Services > In-App Purchases を開き、このサービス自体を有効にします
4. Web上のUnityプロジェク設定ページにて、Googleライセンスキー*4を登録

5. Unityに戻り、課金の実装をする
これはググればたくさん記事があります

注意点はアプリ内課金を扱う場合、iOSの場合はWeb上から課金アイテム登録時に消費型/非表示型を選択出来ます。ですが、Androidの場合はそれがありません。Unity上の以下の購入APIの第2引数で決まってしまうので注意が必要です。

ConfigurationBuilder#AddProduct("ITEM_ID", ProductType.NonConsumable);

また、アプリ再インストール等で課金情報がローカルから消失するケースがあります。そのために、各プラットフォームでは以下の対応を行うのが一般的です。

  • iOSは課金画面に復元ボタンを設け、ボタンが押下されると課金済みアイテムの反映を行う
    これはAppleの規約に書いてあるため、復元(Restore)が無いとリジェクトされます
  • Androidはアプリたしか規約に書いてなかったと思うので自由です。iOSと同じにしているアプリがあったり、起動時に自動復元させている開発者も居ます。私は後者です
広告

AdMobを導入しています。広告種類は全部で6種類。

広告種類 表示箇所
バナー メイン/リザルト/設定/ランキング画面の下部に表示
レクタングル メイン画面で一時停止した画面下部に表示
インタースティシャル リザルト画面で、ベストスコアでは無かった時に表示
動画リワード 課金画面に配置。広告視聴したら24時間の間は他広告が表示されないのが報酬(課金効果を1日体験)
アプリ起動 アプリがバックグランドから復帰した時に表示

「インタースティシャル/アプリ起動」広告はAdMob管理画面上からフリークエンシー キャップを掛けています。これにより例えば1時間に1回だけ表示等の表示制限をコントロールします。



なお、iOS14からはATT対応*5が必要となります。
こちらはUnity公式が提供してくれているiOS 14 Advertising Supportパッケージを導入し、呼び出すコードをコピペすれば表示されます。

他注意点としては、iOSは広告枠を作成して初めてテスト広告*6のリクエストを行ってから1週間くらいテスト広告が表示されません。

シェア機能

SNSシェア機能です。メッセージのみ、メッセージ+画像付きなど色々なパターンでのシェアを想定して実装しておくと使いたい時に楽できます。
公式提供が無いため独自実装するorサードパーティ製を使うことになります。
サードパーティ製だと「UnityNativeShare」や「SocialConnector」がよく使われているようです。ですが、いずれも保守されなくなっているためiOS/Androidそれぞれネイティブコードでシェア機能実装するのが無難かと個人的には思っています。
コードを書くと長くなるので割愛。よくある機能なためググればいくらでも情報は出てくるかと思います。


気を付ける点はiOSの場合、画像の共有を行うと UIActivityViewController API を使う事になるかと思います。こいつ曲者でして、メッセージ又は画像を受け取る事が可能なアプリ一覧 + 画像保存項目も表示されます。
アプリが画像をカメラロールへ保存する場合、NSPhotoLibraryAddUsageDescriptionキーに保存理由のメッセージを設定しなければリジェクトされます。

解析

GoogleFirebase Analytics/Crashlyticsを使いました。
Firebase Analyticsではどの難易度が遊ばれているか、といったイベントデータも集計しています。
ただこれはUnity Analyticsでやってもいいし、iOS/Androidには独自のクラッシュレポートが管理画面上から閲覧可能なためCrashlyticsも入れるかは好みです。

レビュー依頼

iOSは以下を表示させたいタイミングで雑に呼べばいいだけです。iOSのレビューはOS側が表示管理しており、いつ表示すべきかはOS判断となっています。なので何度もコールしたけど最初の1回しか表示されないといった事になります。

UnityEngine.iOS.Device.RequestStoreReview()

AndroidGoogle提供のGoogle Play In-app Reviewパッケージを使ってレビュー依頼を表示可能です。
ライブラリ導入して数行コードを書く必要がありまますが、先程のリンク先に全て書いてあるので参照ください。

システムUI(マルチ解像度対応)

マルチ解像度は「Canvas設定で頑張る」以上のことは言えません。
ただUnity上でメジャー端末での確認手段として、Unity公式が提供してくれているDevice Simulator Devicesを使うのがオススメです。

追加するとGameタブの左上にSimulator切り替えが出来るようになり、設定する事で対応端末のフレームが表示されます。機種ごとのUI配置可能な領域であるSafeArea*7も考慮され、コード上でSafeArea対応を行ってPlayModeに切り替えると

のように画面上部のノッチを考慮したUI配置で表示されます。

SafeArea対応については以下リンク先のやり方をベースに対応させて頂きました。
kingmo.jp

まとめ

シンプルなゲームでもちゃんとリリースしようと思うと工数掛かるな〜と改めて思いました。
でも1度自分用のアウトゲーム部分作れば、次回から使い回せば良いんで1回だけ気合を入れて作ってみると良いです。

*1:アーカイブ化すると過去ランキングデータとして参照出来ます

*2:ソシャゲの対人ゲーによくあるランク分け

*3:未設定の場合は適当な仮名が勝手に入りますが、PlayerNameを取得すると空扱いな点に注意ください

*4:Google Play Consoleサイトの収益化セットアップページにあるライセンス項目にあるキーの事です

*5:広告のトラッキングを許諾してもらう

*6:ここでいうテスト広告とは正規広告IDを使って表示時にテスト端末で表示したときの広告を指しています。

*7:ノッチ/homebar以外の領域