先日Unityで開発したスマホ向けの趣味ゲームをめでたくストア(Google PlayとApp Store両方)に公開したのですが、これがもう想像以上に大変でした。
Unity上でゲームが完成したぞ〜〜となってからが本当に長かった。
一言で言うなら初見殺しが多すぎる。
自分は普段ゲーム開発をしているわけではなく、ストアにスマホゲームを公開するのも人生初でした。(昔小さなゲーム会社で見習いエンジニアを少しだけやっていたことはあります)
ビルドはUnityの初期設定ままだと通らないのは当たり前。
また、ここ数年で様々な情報取得に対して各ストアはどんどん厳しくなっているらしく、世はまさに大プライバシー時代。
軽い気持ちで「広告ってどんな感じか気になるし実装してみよ〜」などとUnity Adsを導入した結果、Google PlayしかりApp Storeしかり、対応することが次から次へと降ってきました。
今後またUnityでゲームを開発するかはわかりませんが、もがいた時間の供養および備忘録として対応したことを残しておこうと思います。
なお、やったことはメモ程度に簡潔に書くので詳しく知りたいときは参考ページを参照することを推奨。
環境
環境変わるだけでビルド結果等々が変わることはまちまちなのでメモ
- Unity: 2022.3.8f1 -> 2022.3.11f1 (Xcodeビルド不具合解消のため途中でアップデート)
- Unity Ads(Advertisement Legacy): 4.4.2
- Unity iOS 14 Advertising Support: 1.0.0
- XCode: 15
- PC: M2 MacBook Air
- OS: macOS Ventura 13.5.2
Google Play及びApp Store共通
リリース用データをPlayer Settingにて設定
なぜやったか
- アプリリリースに必須の項目
- しかし初期値は設定されており、例えばCompay Nameは"Default Company"になったりしてしまい変えるのを忘れると後で焦る
やったこと
- Company Name, Product Name, Versionの入力
- Versionは修正ビルドごとにインクリメント
- アイコン画像の設定
- アイコン用画像はInspector WindowにてTexture Type を
Editor GUI and Legacy GUI
に、Compression
をNone
に設定 - アイコンは512x512で作成すると後のストア登録のときにも使い回せて良さそう
- Android用には一枚絵以外に、背景のみ、メインビジュアルのみのものをそれぞれ用意し、Adaptive iconsに設定した
- アイコン用画像はInspector WindowにてTexture Type を
- Resolution and Presentationにて
Default Arientation
を設定。今回のゲームは縦向き固定のゲームだったのでPortrait
を選択 - Bundle Identifier, Bundle Version Codeの設定
- Bundle Version Codeはストアにアップロードするたびに値を増やさないとエラーになるらしいので注意
参考
プライバシーポリシーの用意
なぜやったか
- 世はまさに大プライバシー時代
- Google Play及びApp Store共にアプリを公開する際、プライバシーポリシーページのURLの入力が必須項目
- また、アプリ内にプライバシーポリシーを明記もしくは明記したページへのリンクが必要
- Prepare your app for review - Play Console Help
やったこと
- プライバシーポリシーを記載したWebページを用意し、そのページへのリンクをゲーム内のタイトル画面に設置
- 内容はUnity Ads用に用意された他ゲームのものを参考に作成
- 新たにサイト開設とかはめんどかったのでgistで公開
- https://gist.github.com/mich0w0h/8c6e333a00701e3bc4a129ed8e46ce46
参考
- リリースしたGoogleアプリが消されたのでプライバシーポリシー書いたら復活した【Unity】 - トマシープが学ぶ
- Unity Adsとプライバシーポリシー - エフアンダーバー
- Unityで作ったAndroidアプリがGoogle プライパシーポリシー違反で削除された時の解決方法 – くねおの電脳リサーチ
- プライバシーポリシー | 開発・公開中のアプリ
- にゃんこ・ザ・スライダー プライバシーポリシー | TODOWORKS
各ストアのData Collection Surveyに回答
なぜやったか
- Unity Adsによってデータ収集が発生しており、世は大プライバシー時代なので回答必須
やったこと
- Unityが公式で回答内容を用意してくれている
- 各ストア用の回答表を見ながらポチポチと回答を登録
- App Store用: Apple privacy survey for Unity Ads
- Google Play用: Google Play data safety section for Unity Ads
メインシーンにてFPSを60FPSに指定
なぜやったか
- 実機で動作テストしたらアニメーションがめっちゃカクカクしてた
- モバイルの場合は初期値に30FPSが設定されるらしく、これが原因
- FPSを上げると消費電力の上昇するというし、メインのゲームシーンでだけFPSを60に設定することにした
やったこと
- メインのゲームシーンで使用するスクリプトの
Start()
にてApplication.targetFrameRate = 60
を記述(Unity - Scripting API: Application.targetFrameRate)
参考
画像アセットのビルドサイズ削減
なぜやったか
- Google Playにビルドを初回アップロードした際、アプリサイズが88MBくらいあった
- 「このゲーム内容にしてはちょっと重すぎないか?」と思ってしまった
- 2Dゲームにおける二大サイズ容量要因である画像とフォントに対してアプローチすることに(フォントについては次のセクションで記述)
- 対応後は24MBになり、半分以下にサイズ削減できた
- そのままでもリリースはできたので完全に自己満
やったこと
- Sprite AssetをSpriteAltas化
- 対象画像はInspector Windowにて
Compression
をNone
に設定する。Warningが出たので。 - UIにSpriteを利用している際は
Tight Packing
、Allow Rotation
をオフにする
- 対象画像はInspector Windowにて
- TextureのInspector Windowにて
Max Size
をゲームの見た目を損ねない程度に減らす
参考
フォントアセットのビルドサイズ削減
なぜやったか
- 前述の「画像アセットのビルドサイズ削減」と以下同文
- 本セクションではTextMesh Proが主な対象
やったこと
Font Asset CreatorにてTextMesh Proアセット生成時に
Custom Characters
で使用する文字を限定し、Altas Resolution
を見た目を損ねない程度に減らす- 使用する文字だけに絞ったら表示がバグったのである程度の文字数はあったほうが良さそう
Importするフォントの文字を利用している文字だけにする。Inspector Windowにて
Character
欄でCustom Set
を、Custom Chars
欄に使う文字列を入力- これは一応やってみたがTextMeshPro利用時にも効果があるのかはわからない
- アンダーライン効果用の
_
(アンダースコア)や半角全角スペースなどは抜けやすいので注意 - ゲーム表示に問題ないか一度全部チェックしたほうが安心
参考
- 【Unity】TextMeshProの容量を指定した文字だけ入れて減らす手順 - はなちるのマイノート
- TextMeshProでアンダーラインが表示されない時の対処方法 #Unity - Qiita
- Unity : フォントデータから必要な文字だけインポートし、容量を軽くする - いんでぃーづ
Google Play向け
UnityのTarget API LevelをAPI level 34に変更
なぜやったか
- UnityでAndroid向けにビルドする際、Gradleにて下記エラーが発生
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 (省略) cannot find symbol (省略) symbol: variable TIRAMISU location: class VERSION_CODES
- 原因は上記variableがAndroid API 33以降でしか定義されてなく、存在しないvariableを参照していたこと
- Unityのデフォルト値ではAPI levelが低かったため、設定変更が必要
やったこと
- Unityにて
Player Settings > Other Settings > Identification > Target API Level
にてAPI level 34
を選択
UnityのAndroid向けビルド方法をIL2CPPに変更
なぜやったか
- Google Playは64bit版アプリしか受け付けておらず、また64bit版アプリのビルドはIL2CPPでしかできない
- Android向けビルドのデフォルトはMonoに設定されているため変更する必要がある
やったこと
- Unityにて
Player Settings > Other Settings > Configuration > Scripting Backend
にてIL2CPP
を選択
参考
Androidでのサウンド再生音遅延対策にCRI ADX2を導入
なぜやったか
- ビルドを実機で動作確認してたら、SEの再生があまりにも遅かった
- タップに反応してSEを鳴らす場合、さすがに違和感がありすぎたので対応
- 対応後はマシにはなったが、まだちょっと遅延は残っているものの趣味ゲームだしと許容
やったこと
- 導入方法はこちらの記事参照: Unityのサウンド機能をADXで強化する~とにかく早く音を鳴らす編~ #Android - Qiita
- 導入手順で作成したCriWareInitializerにて、
Android Config
のEnable SonicSYNC
を有効にする(デフォルトで有効だったが念のため) - 音を鳴らすのに利用するCRI Atom SourceはUnityのAudio Sourceと似たような動作をするもので、スクリプトからの呼び出しもほぼ同じような使い方ができる
- このコンポーネントの
Android Config
にてLow Latency Playback
を有効にするのを忘れないようにする(忘れそうになった)
- このコンポーネントの
参考
- Unityゲーム開発におけるAndroidのサウンド再生遅延対策 #Unity - Qiita
- Unityのサウンド機能をADXで強化する~とにかく早く音を鳴らす編~ #Android - Qiita
AndroidのKeystoreを作る
なぜやったか
- Google Playにアプリをアップロードする際に署名が必要
- Unity上でその署名用のKeystoreを発行できる
やったこと
- Unityの
Player Setting > Publishing Settings
にて作成 - 詳細手順はこちら参照: Unityで作ったAndroidアプリをGooglePlayで公開するまでの準備#AndroidのKeystoreを作る
- Keystore作成時に設定したパスワードはAndroid向けにビルドする際に
Player Settings > Publishing Settings
にて入力しておく必要があるためしっかり管理すること
参考
App Store向け
リリースの際の手順は基本的にこれ通りに進めればいけた
本当にこのページがよくまとまっていてほぼこれ通りに進めればいけたので貼っておきます
いくつか注意点
- XCodeでビルドしたプロジェクトを開いた際、Warningを解消していくと記事には書いてあるが、XCode15ではむしろWarningのまま放置しないとビルドが失敗した
- XCodeで
Automatically manage signing
をオンにしているとDeveloperプロファイルを参照しようとし存在しないとエラーになる。オフにして手動でDistribution用に作成したプロファイルを選択することで解決 - Archive作成時、
double-quoted include "LifeCycleListener.h" in framework header, expected angle-bracketed instead
といったエラーが発生したがUnityを最新版LTSにアップデートすることで解消 - ArchiveのValidate時に発生する
Invalid Bundle. The bundle at '〇〇.app/Frameworks/UnityFramework.framework' contains disallowed file 'Frameworks’
エラーはXCodeのAlways EmbedSwiftStandartLibraries
を修正することで解決
参考
- Bug - Multiple xCode issues after xCode update for iOS 17 - Unity Forum
- 【Unity】【Xcode】 Validate App エラー対応 Invalid Bundle. The bundle at '◯◯.app/Frameworks/UnityFramework.framework' contains disallowed file 'Frameworks'. - アプリ個人開発 まるブログ
ATT許可申請
なぜやったか
- 満を持してApp Store審査へアプリを提出したところリジェクトをくらった
- 広告でユーザートラッキングしてるならApp Tracking Transparency(ATT)を実装してねとのこと
- なにそれ…生粋のAndroidユーザーには未知の概念
- どうやらiOS 14以降、ユーザーデータを収集する前にポップアップを表示してユーザーに認可をもらう必要があるらしい
- その許可申請を用意されてるATT Frameworkで実装する必要があるとのこと
やったこと
- こちらの記事にて簡潔にやることがまとまっていたので丸パクリした: UnityAds で iOS 14 の App Tracking Transparency 対応 | AyaHime Software Studio
- Unityが公式で対応ガイドを用意しているので目を通しておく: iOS 14 technical integration guides
- 上記で実装したUnityのPostBuild処理スクリプトにてATT許可申請ダイアログに表示する文言を記入
- 文言の内容は各社のダイアログ事例を参考にした
参考
- UnityAds で iOS 14 の App Tracking Transparency 対応 | AyaHime Software Studio
- iOS 14 technical integration guides
- App Tracking Transparency | Apple Developer Documentation
- 各社の App Tracking Transparency のダイアログ事例と許可率について
- Apple ATT同意率を高めるデザイン、文言|Shun Harada
App Storeで表示されるdeveloper nameを変更したい
なぜやったか
- ゲームがApp Storeにリリース成功したので見に行ったらdeveloper name(販売元名)が自分の本名になっていた
- 自分としてはハンドルネームである
mich0w0h
を表示したい - 個人開発者だとApple Account名が強制的にdeveloper nameにされてしまうらしい。えー。Google Playでは自分で設定できたのに。。。
やったこと
大変恐れ入りますが、個人として登録しているデベロッパが App Store で App を販売する際は、正式な個人名を使用します。 貴社の創立者または共同創立者である場合は、メンバーシップを個人から法人に移行するリクエストを送信いただけます。
参考
iPhoneでサイレントモード時にもゲームサウンドを鳴らす
なぜやったか
- iPhoneでゲームプレイしたところサウンドが全く鳴らなかった
- 試しにインスタを開いたところそちらでは音が鳴っていた
- (当方iPhone実機を持っておらず、ストアリリース後に友人に頼んで動作検証してもらって発覚)
- どうやらiPhoneの仕様でサイレントモードがオンの場合、音楽は鳴らすがその他の音(カメラのシャッター音など)は鳴らさないようになっているらしい
- 通常サイレントモードに設定されているだろうし、それでせっかくのゲームサウンドが鳴らず無音のゲームだと思われたら寂しいので対応したい
やったこと
- サイレントモードで音を鳴らすには「このゲームの音は音楽再生ですよ」とiOSに伝える必要がある
- 具体的には
AudioSession
のCategory
をAVAudioSessionCategoryPlayback
にする - iOSのAPIをUnityから呼び出すため一工夫が必要で、Objective-Cで書いたPluginを用意しそちらをスクリプトで呼び出すことになる
- それ用のコードを公開している方がいたので、そちらを導入した
- Unity Editor上でゲームを再生すると
EntryPointNotFoundException
が発生するがこれは無視して良いらしい
参考
- 【Unity】iOSでサイレントモードでも音を出す
- Unity iOSビルドにてオーディオのバックグラウンド再生を行なう
- (20+) Unityユーザー助け合い所 | iPhone用に書き出したアプリで、iPhoneがマナーモード(サイレントモード | Facebook
- Unity,C#ファイルからネイティブプラグインでObjective-Cが呼び出せない
おわりに
リリース作業…大変だった…。
全てが未知だったので、予想外の作業や不具合がどんどん発生するし、環境依存すぎて解決方法が調べてもGPTに聞いても全然ヒットしないこともしばしばでした。
しかし大変だったけど後悔はしてません。終わってみれば色々なことを知れて楽しかったなーと思います。
今後またゲームをリリースするかわかりませんが、今回の経験を活かして次はもっとスムーズにできるはず…。
※ 公開したスマホゲームについては別途ブログ記事を書く予定です。