iOS13が公開されたことで、beta版をインストールしなくてもUnityでARKit3の新規のHuman Segmentaionなどが使えるようになりました。対応端末はiPhone X以降です。
実験としてこのようなアプリを作ってみました。
電子書籍のジャニーズになれるアプリを作りました。 #madewithunity pic.twitter.com/kSrx0eRk4D
— Koki Ibukuro (@asus4) 2019年10月11日
が、開発中、実機で確認するのがとても面倒でした。ARKitはiPhone搭載のカメラのセンサを使うため、実機じゃないと動きません。毎回Unityからビルド→Xcodeプロジェクトに書き出し→実機で確認。のステップを踏まなくてはいけません。毎回実機確認に5分くらいかかります。ARKit2まではARKit Remote for Unityで、Unity Editorとつなげてデバックができました。とところが、ARKit3の機能に対応しら新しいUnityライブラリである、AR Foundation (動作時点ではver 3.0.0-preview.3
)ではリモートデバックができないようです。公式スレッドによれば開発中だけど難航しているようです。
なにかを作るときにはツールから作るのをモットーにしているので、Unity Editorにリモートで送信できるツールを作ってみました。現在はHuman Segmentation関係の機能しか用意していませんが、普通に動きそうです。
Making an ARFoundation remote tool will improve development speed #madewithunity pic.twitter.com/J8kBIzeagW
— Koki Ibukuro (@asus4) 2019年10月16日
ソースコードはこちら。
仕組みはシンプルで、iPhoneからARに必要な情報を送ります。
- NDI
- RGBカメラ(YCbCr色空間) 映像
- Depth 映像
- Human Segmentation 映像
- WebSocket
- カメラmatrixとかの情報
NDIはWi-Fi経由だと遅いのですが、USB経由で接続すると0.3秒くらいの遅延で収まりました。
Hack C#でprivateプロパティだけなstructを作る
シミュレータを作るときに困った点を一つ。ARFoundationはコア部分はネイティブC++プラグイン。そちらで生成したstructをやり取りしているので、C#から見えるstructはプロパティが全部プライベートでした。
[StructLayout(LayoutKind.Sequential)] public struct XRCameraFrame { public long timestampNs { get { return m_TimestampNs; } } long m_TimestampNs; public Matrix4x4 projectionMatrix { get { return m_ProjectionMatrix; } } Matrix4x4 m_ProjectionMatrix; ... }
↑このようなクラス構造。Unityでもunsafe{}を使えばこのようなstructでも作れますが、ライブラリ化を考えるとなるべくunsafe以外の方法でstructを作ったほうが良いため、以下の様な共用体をつくることで解決しました。c#で共用体って作れるんですね…。
[StructLayout(LayoutKind.Sequential)] public struct MyCameraFrame { public long timestampNs; public Matrix4x4 projectionMatrix; ... } [StructLayout(LayoutKind.Explicit)] public struct CameraFrameUnion { [FieldOffset(0)] public MyCameraFrame a; [FieldOffset(0)] public XRCameraFrame b; } void main() { var union = new CameraFrameUnion() { a = new MyCameraFrame() { // これはいじれる! timestampeNS = 1000, } } // 共用体なので、aを作るとbもできる! XRCameraFrame b = union.b; }