Unityで作ったゲームでHyper Casual Game向けにSupersonicで必要となるSDKを統合してiOS向けビルドを行いました。
Xcodeプロジェクトをそのままビルドしてアプリ化するまでに起こったエラーと解決策をまとめます。
ビルド環境
・以下のUnity SDKを統合
Facebook, AppsFlyer, GameAnalytics
・WindowsでUnityをiOS向けのビルド
・MacbookでXcodeプロジェクトをビルド
ビルドに必要なファイルがなくてビルドエラーを起こす。
エラーコード:
FBUnityInterface.mm 'FBSDKCoreKit/FBSDKCoreKit.h' file not found
ビルドに必要なファイルないので集める必要があります。
今回のエラー内容はFacebook向けのものが足りませんが、Unityでビルドした段階ではAppsFlyer, GameAnalyticsのSDKのビルドタイミングで同じような内容のエラーが出るので必要なファイルを集めまる必要があります。
CocoaPodsで必要なライブラリを集める
Xcodeプロジェクトフォルダを見るとPodfile
があり、そこに必要なライブラリが書かれています。
(ない場合は作る必要があるがUnityでビルドした場合はあると思われます)
以下の作業をターミナル
で行います。
(作業を行う前にXcodeは閉じてください)
- CocoaPodsをインストールする
$ sudo gem install cocoapods
- 初期セットアップ
$ pod setup
- プロジェクトフォルダに移動する(例)
$ cd /Users/user/Desktop/XcodeBuildTest/
- ライブラリをインストールする(Podfileがない場合は作る必要があります)
$ pod install
インストールでエラーが出た場合は以下を試してから再度インストールしてください。
$ pod update
それでもエラーが出る場合:Bus Error at 0x00000001051f4000
intelのCPUでは問題が起きていませんが、M1などMacのCPUだとエラーが出るようです。
ターミナルから以下のコマンドを実行します。
$ gem install --user-install ffi -- --enable-libffi-alloc
参考:
https://stackoverflow.com/questions/68553842/error-installing-a-pod-bus-error-at-0x00000001045b8000
インストールが完了すると以下のプロジェクトフォルダに以下のファイルができます。
Unity-iPhone.xcworkspace
このファイルでXcodeを開くと左側のナビゲーターにUnity-iPhone
の下にPods
が追加されます。
Podsが追加されているのを確認したらXcodeで再度ビルドします。
does not contain bitcode.
エラーコード:
'/Users/user/Library/Developer/Xcode/DerivedData/Unity-iPhone-envkqihsknqcxhfguhvskqfjbnqp/Build/Products/ReleaseForRunning-iphoneos/FBAEMKit/FBAEMKit.framework/FBAEMKit' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Users/user/Library/Developer/Xcode/DerivedData/Unity-iPhone-envkqihsknqcxhfguhvskqfjbnqp/Build/Products/ReleaseForRunning-iphoneos/FBAEMKit/FBAEMKit.framework/FBAEMKit' for architecture arm64
解決方法:
XcodeのBuild Settings -> Build Options -> Enable Bitcode
をNo
にセットします。
注意点としてTARGETS
にUnity-iPhone, Unity-iPhone Tests, UnityFramework
と並んでいますが、ターゲット毎にBitcodeをNoに設定しないと同じエラーが出ます。
念の為PROJECT
のUnity-iPhone
もBitcodeがNoになっていることを確認してみてください。
Command PhaseScriptExecution failed with a nonzero exit code
エラーコード:
Command PhaseScriptExecution failed with a nonzero exit code
ナビゲータに表示されている情報が少なすぎるのナビゲータのリストアイコンShow the Report navigator
を選択します。
エラーの詳細:
Showing Recent Issues /Users/user/Library/Developer/Xcode/DerivedData/Unity-iPhone-envkqihsknqcxhfguhvskqfjbnqp/Build/Intermediates.noindex/Unity-iPhone.build/ReleaseForRunning-iphoneos/UnityFramework.build/Script-9D3DC87A221D90AB00B2960B.sh: line 2: /Users/user/Desktop/Xcode/XcodeBuildTest/MapFileParser.sh: Permission denied
MapFileParser.sh
のファイルを実行するためのパーミッションが足りないことがわかります。
解決方法:
ターミナルでファイルの場所に移動して実行権限を追加する。
$ chmod +x MapFileParser.sh
起動直後にアプリが落ちる
エラーコード:
UnityFramework [access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSUserTrackingUsageDescription key with a string value explaining to the user how the app uses this data.
エラーコードはiPhoneをMacに繋いだままXcodeのデバッグウィンドウで確認します。
Info.plist
にNSUserTrackingUsageDescription
のkeyを追記する必要があることがわかります。
毎回Info.plist
に追記するのは面倒なのでUnityでビルドするときに追記されるようにします。
以下エディタ用のスクリプトをAssets/Scripts/Editor
などに配置します。
using UnityEditor;
using UnityEditor.Callbacks;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
using System.IO;
public class PostBuildStep {
// Set the IDFA request description:
const string k_TrackingDescription = "Your data will be used to provide you a better and personalized ad experience.";
[PostProcessBuild(0)]
public static void OnPostProcessBuild(BuildTarget buildTarget, string pathToXcode) {
if (buildTarget == BuildTarget.iOS) {
AddPListValues(pathToXcode);
}
}
// Implement a function to read and write values to the plist file:
static void AddPListValues(string pathToXcode) {
// Retrieve the plist file from the Xcode project directory:
string plistPath = pathToXcode + "/Info.plist";
PlistDocument plistObj = new PlistDocument();
// Read the values from the plist file:
plistObj.ReadFromString(File.ReadAllText(plistPath));
// Set values from the root object:
PlistElementDict plistRoot = plistObj.root;
// Set the description key-value in the plist:
plistRoot.SetString("NSUserTrackingUsageDescription", k_TrackingDescription);
// Save changes to the plist:
File.WriteAllText(plistPath, plistObj.WriteToString());
}
}