Unity iOS プロジェクトにIGAWorksのSDKを組み込むメモ

Unity iOSアプリでadbrixを使うためにIGAWorksのSDKを組み込むメモです。公式に提供されている情報のままやるとエラーが出たり設定が煩雑だったりするので一部に手を加えます。

## 動作確認
* Unity2017.1.1f1
* IgaworksUnityPlugin_iOS_2.4.0_r1
* XCodeEditor-for-Unity [05962b4](https://github.com/dcariola/XCodeEditor-for-Unity/commit/05962b460db97de189275c5d5435f30cdd3787eb)

## 普通に組み込む
公式のドキュメントにそってunitypackageをインポートします。デフォルトでは全てのSDKがインポートされるので、不要なものはチェックを外します。
<img width="510" alt="スクリーンショット 2017-10-25 15.14.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/2490/60fc7e19-c7cd-7e55-d8a5-e227b8136f70.png">

## ビルドする
この状態でビルドするとエラーが出ます。

```
IOException: Sharing violation on path /Users/ntotani/Documents/unity/igaworks sample/build/ios/Unity-iPhone.xcodeproj/project.pbxproj
System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/FileStream.cs:320)
System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share)
(wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
System.IO.StreamWriter..ctor (System.String path, Boolean append, System.Text.Encoding encoding, Int32 bufferSize) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/StreamWriter.cs:124)
System.IO.StreamWriter..ctor (System.String path, Boolean append)
(wrapper remoting-invoke-with-check) System.IO.StreamWriter:.ctor (string,bool)
System.IO.File.CreateText (System.String path) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:159)
UnityEditor.XCodeEditor.XCProject.Save () (at Assets/Editor/third_party/XCodeEditor-for-Unity/XCProject.cs:596)
UnityEditor.IgaworksCoreEditor.XCodePostProcess.OnPostProcessBuild (BuildTarget target, System.String path) (at Assets/IgaworksCore/Editor/IgaworksCorePostProcess.cs:28)
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/MethodBase.cs:115)
UnityEditor.Build.BuildPipelineInterfaces+AttributeCallbackWrapper.OnPostprocessBuild (BuildTarget target, System.String path) (at /Users/builduser/buildslave/unity/build/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs:86)
UnityEditor.Build.BuildPipelineInterfaces.OnBuildPostProcess (BuildTarget platform, System.String path, Boolean strict) (at /Users/builduser/buildslave/unity/build/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs:318)
UnityEditor.HostView:OnGUI()
```

これはSDKが依存しているXCodeEditor-for-Unityというライブラリのバグで、 Xcodeプロジェクトの設定ファイルに変更を加える処理中にファイルを閉じ忘れていることに起因します。当該箇所を変更するとエラーが無くなり、ビルドすることができます。

```diff:Assets/Editor/third_party/XCodeEditor-for-Unity/XCProject.cs
@@ -74,7 +74,9 @@ namespace UnityEditor.XCodeEditor
                        }

                        projectFileInfo = new FileInfo( Path.Combine( this.filePath, "project.pbxproj" ) );
-                       string contents = projectFileInfo.OpenText().ReadToEnd();
+                       StreamReader sr = projectFileInfo.OpenText();
+                       string contents = sr.ReadToEnd();
+                       sr.Close();

                        PBXParser parser = new PBXParser();
                        _datastore = parser.Decode( contents );
```

## ビルドオプションを自動で設定したい
公式のドキュメントにはビルド後に生成されたXcodeプロジェクトを直接編集して`-all_load`フラグを付与するようにありますが、ビルドの度に手動で編集するのは危険なので自動化します。

## ライブラリを更新
SDKが内包している`XCodeEditor-for-Unity`はOSSのライブラリで、これを最新版にすると自動で設定するオプションが使えます。[XCodeEditor-for-Unity](https://github.com/dcariola/XCodeEditor-for-Unity)から最新版をダウンロードし、上書きします。以下のようなエラーが出ます。

```
Assets/Editor/third_party/XCodeEditor-for-Unity/XCMod.cs(4,14): error CS0246: The type or namespace name `MiniJSON' could not be found. Are you missing an assembly reference?
```

これは、依存ライブラリがIGAWorks用に書き換えられているのが原因ですが、実際は別のライブラリに差し替えられているので参照箇所自体を消してしまって大丈夫です。

```diff:Assets/Editor/third_party/XCodeEditor-for-Unity/XCMod.cs
@@ -1,7 +1,6 @@
 using UnityEngine;
 using System.Collections;
 using System.IO;
-using Json = MiniJSON;

 namespace UnityEditor.XCodeEditor
 {
```

また、元のライブラリ`Assets/Editor/MiniJSON.cs`も不要なので削除します。

## 設定ファイルも更新する
最新版のライブラリ用に一部を書き換えます。

```diff:Assets/IgaworksCore/Editor/IgaworksCorePostProcess.cs
@@ -23,7 +23,7 @@ namespace UnityEditor.IgaworksCoreEditor
                                var files = System.IO.Directory.GetFiles(projModPath, "*.projmods", System.IO.SearchOption.AllDirectories);
                                foreach (var file in files)
                                {
-                                       project.ApplyMod(Application.dataPath, file);
+                                       project.ApplyMod(System.IO.Path.Combine(Application.dataPath, file));
                                }
                                project.Save();
```

```diff:Assets/IgaworksCore/Editor/iOS/fixup.projmods
@@ -1,12 +1,7 @@
 {
   "group": "IgaworksCore",
   "patches": [],
-  "libs": [
-    "IgaworksCore/Editor/iOS/IgaworksCore/libIgaworksCoreLib.a:<group>",
-  ],
-  "librarysearchpaths": [
-    "IgaworksCore/Editor/iOS/IgaworksCore/",
-  ],
+  "libs": [],
   "frameworks": [
        "iAd.framework:weak",
        "CoreTelephony.framework:weak",
@@ -18,13 +13,14 @@
        "libxml2.dylib:weak"
   ],
   "headerpaths": [
-    "IgaworksCore/Editor/iOS",
+    "",
   ],
   "files": [
-    "IgaworksCore/Editor/iOS/IgaworksCorePlugin.mm",
-    "IgaworksCore/Editor/iOS/IgaworksCorePlugin.h",
+    "IgaworksCore/libIgaworksCoreLib.a",
+    "IgaworksCorePlugin.mm",
+    "IgaworksCorePlugin.h",
   ],
   "folders": [],
   "excludes": ["^.*\\.meta$", "^.*\\.mdown^", "^.*\\.pdf$"],
-  "other_ldflags": ["-all_load"]
+  "buildSettings": {"OTHER_LDFLAGS": ["-all_load"]}
 }
```

## IDFA
IDFAに対応する場合、iOSネイティブでの処理が別途必要です。ドキュメントにあるようにビルド後の`UnityAppController.mm`を編集するのは危険なので、サブクラスを定義してそこで処理するようにします。

```objc++:Assets/Plugins/iOS/MyAppController.mm
#import "UnityAppController.h"
#import <AdSupport/AdSupport.h>
#import <IgaworksCore/IgaworksCore.h>

@interface MyAppController : UnityAppController
@end

@implementation MyAppController

- (void)preStartUnity
{
    if (NSClassFromString(@"ASIdentifierManager")){
        NSUUID *ifa = [[ASIdentifierManager sharedManager] advertisingIdentifier];
        BOOL isAppleAdvertisingTrackingEnabled = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];
        [IgaworksCore setAppleAdvertisingIdentifier:[ifa UUIDString] isAppleAdvertisingTrackingEnabled:isAppleAdvertisingTrackingEnabled];
    }
}

@end

IMPL_APP_CONTROLLER_SUBCLASS(MyAppController)
```

定義したファイルを`Assets/Plugins/iOS`以下に入れて完了です。

## 実行
以上でビルドのための設定は完了です。後はドキュメント通りシーンに必要なコンポーネントを追加し、APIキーを初期化用コードに渡します。

## リンク
* http://help.igaworks.com/hc/ja/3_3/Content/Article/sdk_installation_unity