zawazawa雑記

ARKit2.0の状態保存と端末同期を使ってARPetを作ってみた

やったこと

ARKit2.0がぼちぼち出てきます出ました。それに伴いより多くの人が簡単に

  • Persistent AR Experience / 状態保存
  • Multiuser AR Experience / 端末同期

を実装し、多くの人に届ける事ができるようになります。これをいち早くキャッチアップし、実装しようと思いました。

どうやったか

ただ実装するだけではつまらないと感じたので、システム全体の流れがわかるようなアプリケーションにしました。また、今回はAR表現の進歩で実現が可能になりそうな「ARPet」を作ってみることにしました。

開発環境

  • macOSX
  • Unity-ARKit-Pluginのarkit2.0_beta branch
  • iOS12
  • Unity2017.4.2
  • Photon Unity Network
  • Xcode10

状態保存

UnityARWorldMapシーンをそのものを使えば基本的に大丈夫です。 このシーンでやってることは、「検出した平面や空間情報を端末に保存するやで。ロードする時は端末に保存されてるファイルを読み込んで保存した時と同じ風景を探すやで」って感じです。

またこの方法ではオブジェクトの保存ができません。参考に↓

f:id:zawazawahtn:20180831181226p:plain

ARWorldmapのSave&Loadにオブジェクトを結びつけたい場合は自分でそのオブジェクトのTransform情報の入ったjsonファイルを作成する必要があるみたいです。他にいい方法があれば教えてください。

端末同期

個人的に鬼門でした。実装を始めた当初は公式でも言及していたSharedSpheresを使用するつもりだったのですが、実装を始めて間も無くこの記事が出てしまいました。

blogs.unity3d.com

そうです、SharedSpheresは今後死んでしまうunetを使用していたのです。

そこで今回はPhoton Unity Networkを使用することにしました。

具体的には、

  • ARWorldMapを作成して受信端末に送信するためにARWorldMapをシリアライズする
byte[] locWorldBytes = localWorldMap.SerializeToByteArray(); 
  • PhotonではRPCでバイト列を送受信できるので(可能な型)受信端末に送信する
photonViewWorld.RPC("ShareWorldMap", PhotonTargets.OthersBuffered, locWorldBytes); 
  • 受信端末で以下のコードが動き、バイト列がデシリアライズされてARWorldMapが復元される
[PunRPC]
void ShareWorldMap(byte[] world_bytes){
    ARWorldMap worldMap = ARWorldMap.SerializeFromByteArray(world_bytes); 
・・・
  • その後受信端末側でAR体験をするためのconfig情報(検出平面や検出平面のexpandをするかどうかなど)を設定したsessionを開始する

おわりに

こちらのアプリはメルカリでサマーインターンをした時に作成したものです。そちらの記事もよかったら読んで下さい。

zawazawahtn.hatenablog.com

© UTJ/UCL