ゴイサギ日記

東京でエンジニアとして頑張って何とか生きてます。。ゆる~く更新していきます

【Unity】Android13対応メモ

Unityで開発したAndroidアプリを Android11 → Android13 に上げた際の色々を備忘録的に書いておく

経緯

GooglePlay に公開した Androidアプリが「アプリの安定性」に関わるポリシー違反に該当するとのメールを受信、対象アプリの Firebase Crashlytics を確認したところ、Android12以上端末で起動するとクラッシュする

以下はクラッシュ時のログ

Fatal Exception: java.lang.IllegalArgumentException
com.sample.app: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles. 

対策

対象アプリを記事作成時点(2023年11月)で対応必須となっている Android 13 に上げます。

Project Settings 更新

Minimum API Level は 21 を設定
Target API Level は 33 を設定

Custom Main Manifest にチェック
Custom Main Gradle Template にチェック
Custom Gradle Properties Template にチェック

Assets/Plugins/Android/AndroidManifest.xml に以下を追加

<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>

Assets/Plugins/Android/mainTemplate.gradle の dependencies に以下を追加

implementation 'androidx.work:work-runtime-ktx:2.7.0'

Assets/Plugins/Android/gradleTemplate.properties に以下を追加

android.useAndroidX=true
android.enableJetifier=true

その他

以下のエラーが出る場合、Assets/Firebase/Editorをこちらに置き換える

DllNotFoundException: Unable to load DLL 'FirebaseCppApp-6_15_2': The specified module could not be found.

【Unity】Object Pool の注意点

Object Poolとは?

オブジェクトを事前生成して使い回す手法です。
インスタンス生成によるCPU負荷(スパイク)を抑えるメリットがあります。

何度も使い回すオブジェクトに適用します。
(例:シューティングゲームのミサイル・レーザーなど)

Unity2021.3以降であればUnity標準のObjectPoolが使えます。
Unity - Scripting API: ObjectPool<T0>

注意点

Object Poolはポピュラーな最適化手法として話題になりますが幾つか注意点もあります。

初期化・終了の仕方

都度生成・破棄の場合、Unityにおける初期化はAwake(), Start(), 終了処理は OnDestroy() に記述しますが、ObjectPoolの場合、オブジェクトのアクティブ切り替えによる使い回しになるため 初期化は OnEnable(), 終了処理は OnDisable() に記述するなどの工夫が必要です。

UnityのOjectPoolを使う場合はコンストラクタで各種コールバックを指定できます。
Unity - Scripting API: Pool.ObjectPool_1.ObjectPool<T0>

メモリ使用量

オブジェクトを事前生成するため、都度生成・破棄と比較してメモリ使用量が増えます。

例えば、画面にミサイルが5個しか出ないのに、100個事前生成するなど必要以上に確保してメモリを圧迫する設計にしない注意が必要です。

プール作成のタイミング

特定フレームにまとめてオブジェクトを生成するため、そのタイミングでスパイク発生のリスクがあります。画面遷移や暗転時に生成を行うなどの工夫が必要です。

まとめ

Object Pool の注意点をまとめてみました。ゲーム仕様によっては上記以外の注意点も出てくると思うので上手く活用して快適に遊べるゲームを作れると良いですね ^_^

【Game】寿司ストップ

という反射神経寿司ゲーをリリースしました。
今回も色々とプログラム周り担当しました。

年内にゲームを3本リリースしたいなーと
チームメンバーと話していたので
なんとかもう1本作りたい!!

【Unity】Scene管理

自分なりのUnityのScene管理をまとめてみた。


あと本記事のSceneは.unityファイルを指します。

基本方針

想定環境

個人開発などの小規模プロジェクトでカジュアルゲーム想定、複雑な遷移は無し

Scene単位は大きく取る

自分の経験上、細かくすると仕様変更に耐えられないためです。

Multi Sceneで構成

ゲーム部分とシステム部分を分けたいので Multi Sceneで構成します。

Scene単位の機能

各Sceneの役割です。
(タイトル画面 > インゲーム画面へ遷移するゲームを例とする)

名前 役割
System シーン切り替え・入力・サウンド等ゲーム全体で使う常駐システム
Debug パラメータ調整・デバッグ機能ON/OFF・任意シーンへ直遷移等デバッグ関連
Title タイトル画面
InGame インゲーム画面

Debug版とRelease版の構成

開発(Debug版)と製品(Release版)で初回起動時の遷移を変えてます。

Debug版

System起動後、Debug画面へ


Debug画面です。ここから任意のSceneへ遷移します。

Release版

System起動後、Title画面へ

Multi Scene管理の注意点

ActiveSceneの変更を忘れずに

LoadSceneMode.Additive を使う場合は
SceneManager.SetActiveScene
アクティブScene を適切に切り替えます。

そうしないとGameObject生成時に親オブジェクト未指定ではデフォルトの配置がアクティブScene直下になるため前回Sceneに配置される問題が発生します。


Hierarchyビューで太字表示のものがアクティブScene

Release版から Debug Scene を除外

Release版でデバッグ機能が誤作動すると困るので
関連するSceneや処理は全て消します。

私はビルド時に以下のように除外してます。

BuildPlayerOptions options = new BuildPlayerOptions();
options.scenes = new string[] { "System", "Title", "InGame" }; // Debugを除外.
BuildReport report = BuildPipeline.BuildPlayer( options );

不要なSceneの削除

LoadSceneMode.AdditiveはSceneを破棄しないので注意が必要です。
SceneManager.UnloadSceneAsync を使い不要Sceneを削除します。

まとめ

今回はカジュアルゲーム向けでしたが
複雑なゲームではSceneを細かくを分けたり
Sceneを作業者単位で分けるといった工夫が ゲーム仕様によって必要になります。

参考

Unity - Scripting API: SceneManager

【Game】反省会

以前リリースした「瞬間!レジ袋」の反省会です。
小規模な開発でも学べる事はある!!

良かった点

デバッグメニュー

一番最初に作りました。
主に以下の用途で重宝しました。
・制限時間、スコア倍率等のバランス調整
・自動正解、時間無制限等のデバッグ機能
・確認したいシーンに即移動
・セーブデータの内容確認(実機も確認出来て便利)

パラメータ設計

開発前にシートでシミュレーションしました。
途中で仕様変えたので全てその通りに行かなかったけどシートをメンバー間で共有してパラメータの共通認識を持てたのは良かったです。

悪かった点

ゲームデザイン

面白いゲームを作るにはどうすれば良いかは永遠のテーマ・・
今回の反省点は最初に要素を入れ過ぎて開発に時間かかってしまった・・

最初は上図の制限時間とライフがある遊びでした。

Firebase Crashlytics 対応

単純に面倒で後回しにしてました。
心の中で別に大した問題起きないだろうと思ってました。
そしたら、デバッグ期間にAndroidでクラッシュする不具合が出る始末、、
急いで実装しました。
チームのみんな、ゴメンナサイ・・ (TAT)

まとめ

次の開発に活かせそうな内容が出てきたので、やっぱり反省会は大事!

【Unity】Google Mobile Ads 更新後にiOSビルドに失敗する

Google Mobile Ads を v6.1.2 にアプデしたら
CocoaPods関連でエラーがあったので備忘録的にまとめておきます。

不具合

iOSビルド時に以下のエラーが出力されビルドが失敗する

iOS framework addition failed due to a CocoaPods installation failure. This will will likely result in an non-functional Xcode project.

After the failure, "pod repo update" was executed and succeeded. "pod install" was then attempted again, and still failed. This may be due to a broken CocoaPods installation. See: https://guides.cocoapods.org/using/troubleshooting.html for potential solutions.

pod install output:

Analyzing dependencies
[!] `Google-Mobile-Ads-SDK` requires CocoaPods version `>= 1.9.0`, which is not satisfied by your current version, `1.8.4`.

pod repo update output:

Updating spec repo `cocoapods`

原因

MacにインストールされているCocoaPodsのバージョンが古い

[!] `Google-Mobile-Ads-SDK` requires CocoaPods version `>= 1.9.0`, which is not satisfied by your current version, `1.8.4`.

解決方法

以下コマンドで CocoaPods を指定バージョンに更新

sudo gem install -v1.9.0 cocoapods -n /usr/local/bin

しかし、以下のエラーが発生

Building native extensions. This could take a while...
ERROR:  Error installing cocoapods:
    ERROR: Failed to build gem native extension.

    current directory: /Library/Ruby/Gems/2.6.0/gems/ffi-1.15.4/ext/ffi_c
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby -I /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0 -r ./siteconf20211229-38719-1beaswp.rb extconf.rb
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/$(RUBY_BASE_NAME)
    --with-ffi_c-dir
    --without-ffi_c-dir
    --with-ffi_c-include
    --without-ffi_c-include=${ffi_c-dir}/include
    --with-ffi_c-lib
    --without-ffi_c-lib=${ffi_c-dir}/lib
    --enable-system-libffi
    --disable-system-libffi
    --with-libffi-config
    --without-libffi-config
    --with-pkg-config
    --without-pkg-config
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:467:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:546:in `block in try_link0'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/tmpdir.rb:93:in `mktmpdir'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:543:in `try_link0'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:570:in `try_link'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:672:in `try_ldflags'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:1832:in `pkg_config'
    from extconf.rb:9:in `system_libffi_usable?'
    from extconf.rb:42:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/ffi-1.15.4/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Library/Ruby/Gems/2.6.0/gems/ffi-1.15.4 for inspection.
Results logged to /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-19/2.6.0/ffi-1.15.4/gem_make.out

rubyバージョンが古いのが原因、
こちらを参考に最新版3.1.0(2021/12/29時点)をインストール
(rubyのバージョンが切り替わらない場合はこちらを参考)

先程のコマンドを再実行、無事、CocoaPods のアプデに成功

と思ったら、iOSビルドで別のエラー発生、、

iOS framework addition failed due to a CocoaPods installation failure. This will will likely result in an non-functional Xcode project.

After the failure, "pod repo update" was executed and succeeded. "pod install" was then attempted again, and still failed. This may be due to a broken CocoaPods installation. See: https://guides.cocoapods.org/using/troubleshooting.html for potential solutions.

pod install output:

Analyzing dependencies
[!] `GoogleAppMeasurement` requires CocoaPods version `>= 1.10.2`, which is not satisfied by your current version, `1.9.0`.

CocoaPods を 1.10.2 以上にする必要あり

[!] `GoogleAppMeasurement` requires CocoaPods version `>= 1.10.2`, which is not satisfied by your current version, `1.9.0`.

バージョンを書き換えて再実行

今度は無事にiOSビルドが通りました! いやはや、とても疲れました・・^_^ ;

参考

MacでRubyをインストールする方法をわかりやすく解説【初心者必見】 | 侍エンジニアブログ
Rubyのバージョンが切り替わらない時の対処法! #Ruby - Qiita

【Game】瞬間!レジ袋

という暇つぶしアプリをリリースしました。
チームで活動しており色々とお手伝いさせていただきました。

AdMob、Firebase まわりで苦労したので この辺も含めて開発内容は記事化したいと思ってます。

そして、ほぼ一年近くブログを更新してないのに気付きました。。(^_^;)