🍎

visionOS の Enterprise API をUnityで使う時のPostProcessBuild 設定

に公開

概要

ホロラボ林です。

Apple Vision Proには 法人向けアプリのみで利用できる Enterprise APIs があります。

これらの機能はUnityアプリでも利用することができるのですが、Xcode上で行う Capability の設定をCI環境において自動化できるよう、Unity の PostProcessBuild のハマったところと、設定例を紹介します。

UnityでVisionPro開発をして、ビルド環境を構築しようとするごく少数の方向けの話です。

EnterpriseAPIについて

Enterprise APIs 自体に関しては、ホロラボメンバーが、以下の記事を書いているので、参照ください。

  • Enterprise API概要の説明

https://zenn.dev/hololab/articles/avp-001-12be095f3d0309

  • カメラアクセス機能と OpenAI API との連携の実装

https://zenn.dev/hololab/articles/d64201dbd98309

Unityアプリからの利用/力こそパワー💪

Enterprise APIs の機能はUnityで開発したアプリでも利用できます。
今回は Increased performance headroom の機能をUnityアプリで利用をしたく、PostProcessBuildにて、Capabilityの設定を追加する事を試しました。

Increased performance headroom の機能はApple Vision Pro の通常のパフォーマンスでは満たすことのできない高度な処理を、Apple Vision Proが本来持っているパフォーマンスを最大限に引き出すことが可能な機能です。

https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.app-compute-category

放熱ややバッテリーの消費と引き換えに、デバイスのパワーを引き出す、富豪的プログラミングの醍醐味のような機能です。

パワー💪

実装コード例 とポイント

で、実装例です。

ポイント1: PBXProject.GetPBXProjectPath がおかしい

最初iOSでよくやるように実装したところ DirectoryNotFoundException が出て正常に動作しませんでした。

DirectoryNotFoundException: Could not find a part of the path "/xxxx/Builds/visionOS/Unity-iPhone.xcodeproj/project.pbxproj".

よくよく見てみると

PBXProject.GetPBXProjectPath(path); は Unity-iPhone.xcodeproj を返すのに、実際のプロジェクトは Unity-VisionOS.xcodeproj となっていました。

そのため、無理くり置換する処理を入れています。この辺りはそのうちUnity側で改善するかもしれません。

projPath = projPath.Replace("Unity-iPhone.xcodeproj", "Unity-VisionOS.xcodeproj");

ポイント2: com.apple.developer.app-compute-category は array of strings

これは自分が悪いのですが、
key:com.apple.developer.app-compute-category のvalue は string ではなくarray of stringsでした。
この辺もちょっとハマりました。

という事で、以下のような実装で目的の動作ができました。

using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;

public class AddCapabilityPostProcessor
{
    [PostProcessBuild(0)]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
    {
        if (buildTarget != BuildTarget.VisionOS)
            return;

        string projPath = PBXProject.GetPBXProjectPath(path);
        //やむなくファイル名を置換する
        projPath = projPath.Replace("Unity-iPhone.xcodeproj", "Unity-VisionOS.xcodeproj");
        var proj = new PBXProject();
        proj.ReadFromFile(projPath);

        string targetGuid = proj.GetUnityMainTargetGuid();
        // Entitlements ファイルのパスを取得/作成
        string entitlementsFileName = "visionOS.entitlements";
        string entitlementsPath = Path.Combine(path, entitlementsFileName);

        // 既存の entitlements ファイルがなければ新規作成
        PlistDocument entitlements = new PlistDocument();
        if (File.Exists(entitlementsPath))
        {
            entitlements.ReadFromFile(entitlementsPath);
        }
        else
        {
            entitlements.Create();
        }

        // Capability を追加
        PlistElementDict rootDict = entitlements.root;
        rootDict.SetBoolean("com.apple.developer.kernel.increased-memory-limit", true);
        //performance-headroom を追加したいので、app-compute-categoryを設定する
        var arr = rootDict.CreateArray("com.apple.developer.app-compute-category");
        arr.AddString("high");

        // 保存
        entitlements.WriteToFile(entitlementsPath);

        // Xcode プロジェクトに entitlements ファイルを設定
        proj.AddFile(entitlementsPath, entitlementsFileName);
        proj.SetBuildProperty(targetGuid, "CODE_SIGN_ENTITLEMENTS", entitlementsFileName);

        // 保存
        proj.WriteToFile(projPath);
    }
}

おしまい。


https://zenn.dev/hololab/articles/6fea13ae43e903

ホロラボのテックブログ

Discussion