以前UnityでiOS用にビルドしたXcodeのプロジェクトをRuby gemのxcodeprojを使って編集していたが、そういう外部のスクリプトを使ってしまうとCloud Buildが利用できなくなるという問題がある。外部のスクリプトじゃなくてC#などで編集できればUnityの環境で閉じられるので便利。

XCodeEditor-for-Unityというオープンソースのものもあって使えるんだが、ここはUnity5から組み込まれているという、Unity Technologies純正のXcodeAPIを使ってみよう。

使い方は UnityでのXcode設定をUnityEditorのスクリプトだけで自動化する - 株式会社CFlatの明後日スタイルのブログ を見ればほぼ充分。

上記のサイトで扱われてない項目で、プラグインのObjCのソースに -fno-objc-arc をつける必要があるものがあったので、 SetCompileFlagsForFile を使って行っている:

using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Collections.Generic;
using System.IO;

public class ModifyXcodeProj {
  [PostProcessBuild(200)]  // FacebookのPostprocessの優先(100)よりも後に行われるようにする
  public static void OnPostprocessBuild(BuildTarget buildTarget, string path) {
    if (buildTarget == BuildTarget.iOS)
      if (!OnPostprocessBuildForiOS(path))
        EditorApplication.Exit(1);  // エラー終了
  }

  private static bool OnPostprocessBuildForiOS(string path) {
    string projPath = PBXProject.GetPBXProjectPath(path);
    PBXProject proj = new PBXProject();
    proj.ReadFromFile(projPath);

    string targetName = "Unity-iPhone";
    string targetGuid = proj.TargetGuidByName(targetName);
    if (targetGuid == null) {
      Debug.LogError("Cannot find " + targetName);
      return false;
    }

    // Facebookのソースのコンパイルフラグに "-fno-objc-arc" を追加
    List<string> flags = new List<string>() {"-fno-objc-arc"};
    foreach (string filePath in new string[]{"Facebook/FbUnityInterface.mm"}) {
      string fileGuid = proj.FindFileGuidByProjectPath(filePath);
      if (fileGuid == null) {
        Debug.LogError("Cannot find " + filePath);
        return false;
      }
      proj.SetCompileFlagsForFile(targetGuid, fileGuid, flags);
    }

    // システムのフレームワークを追加
    foreach (string framework in new string[] {"StoreKit.framework", "CoreTelephony.framework"}) {
      proj.AddFrameworkToProject(targetGuid, framework, false);
    }

    // 書き出し
    File.WriteAllText(projPath, proj.WriteToString());

    return true;
  }
}

注意点

  • ソースファイルにコンパイルフラグを追加する処理を別メソッドに分離して、PBXProjectクラスのインスタンスを渡すようにしようとしたが、そのように変更するとエディタ上でアプリを実行しようとしただけで(ビルドじゃないのに)エディタごと落ちるという謎の現象が発生するので、単一のメソッドで全て処理する必要がある…