本日、会社でARKitとWebRTCのデモと技術解説をまとめたサイトを公開しました。
・ARKit Examples http://arkit.r-u.co.jp/
・WebRTC Examples http://webrtc.r-u.co.jp/
ARKit Examplesでは、プログラミング的な解説というよりは、ARの体験を作る上での技術的な解決策について主に触れたので、
ここではその前のARKitをUnityで動かすための基本的なクラスを解説できればと思います。
Unity-ARKi-Pluginの入手
Unityのアセットストアで公式のプラグインが提供されています。
Unity ARKit Plugin - アセットストア
https://www.assetstore.unity3d.com/jp/#!/content/92515
基本的には上記と同じものですが、Bitbucketから最新のものを取得することも可能です。
Unity-Technologies / Unity-ARKit-Plugin — Bitbucket
https://bitbucket.org/Unity-Technologies/unity-arkit-plugin
基本的なクラス
最低限ARKitを動かすには下記の3クラスが必要です。
UnityEngine.XR.iOS.UnityARVideo
iOSデバイスのカメラの映像をCommandBuffer経由でUnity内のCameraに描画するクラス。カメラにAddComponentして使用します。
ClearMaterialプロパティにはYUVMaterialを設定してください。
またCameraにSkyBoxなどが映ると、カメラの映像が隠されてしまうので、CameraのClear FlagsはDepth Onlyに設定する必要があります。
UnityARCameraNearFar
Unity内のCameraのClipping PlanesのNear/Farを適切に設定するクラス。メインカメラにAddComponentして使用します。
UnityARCameraManager
Cameraの動きを端末の動きと同期させるほか、いくつかの項目を設定するクラス。任意のGameObjectにAddComponentして、Cameraの参照を渡して使用します。
この状態で、実行中にMainCameraのPositionをDebug.Logなどで確認すると、
MainCameraの位置がカメラの動きに同期して動いていることがわかります。
UnityARSessionNativeInterface
また、重要なクラスとしてUnityARSessionNativeInterfaceがあります。
こちらは名前の通り、ネイティブのARKitとの橋渡しを行う役割を持っており、
後述の検出結果の取得はこのクラスのdelegateとして受け取ることが可能です。
ARKitの検出した特徴点を受け取る
ARKitの検出した特徴点の更新は
UnityARSessionNativeInterface.ARFrameUpdatedEvent
というdelegateメソッドで受け取ることが可能です。
public void Start()
{
UnityARSessionNativeInterface.ARFrameUpdatedEvent += ARFrameUpdated;
}
public void ARFrameUpdated(UnityARCamera camera)
{
Vector3[] pointCloud = camera.pointCloudData;
}
UnityARCameraにpointCloudDataプロパティがあり、
特徴点の位置がVector3の配列で格納されています。
なお、Unity ARKit Plugin内のサンプルでは、
PointCloudParticleExampleというクラスで該当の処理が実装されています。
ARKitの検出した平面情報(床情報)を受け取る
ARKitの検出した平面情報は
UnityARSessionNativeInterface.ARAnchorAddedEvent
UnityARSessionNativeInterface.ARAnchorUpdatedEvent
UnityARSessionNativeInterface.ARAnchorRemovedEvent
という3つのdelegateメソッドで受け取ることが可能です。
public void Start()
{
UnityARSessionNativeInterface.ARAnchorAddedEvent += AddAnchor;
UnityARSessionNativeInterface.ARAnchorUpdatedEvent += UpdateAnchor;
UnityARSessionNativeInterface.ARAnchorRemovedEvent += RemoveAnchor;
}
public void AddAnchor(ARPlaneAnchor arPlaneAnchor)
{
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
public void RemoveAnchor(ARPlaneAnchor arPlaneAnchor)
{
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
public void UpdateAnchor(ARPlaneAnchor arPlaneAnchor)
{
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
}
ARPlaneAnchorという構造体に平面情報が格納されています。
平面情報をGameObjectに反映させるには、
必要な情報を格納の上、ARPlaneAnchorGameObjectを用い、
下記のように対象のGameObjectとARPlaneAnchorをセットで持たせます。
targetGameObject.name = arPlaneAnchor.identifier;
ARPlaneAnchorGameObject arpag = new ARPlaneAnchorGameObject ();
arpag.planeAnchor = arPlaneAnchor;
arpag.gameObject = UpdatePlaneWithAnchorTransform(targetGameObject, arPlaneAnchor);
また、ARPlaneAnchorはPointCloudと違い、
連続性を持っているので下記のようにして状態を更新します。
UpdatePlaneWithAnchorTransform(arpag.gameobject, arPlaneAnchor);
なお、Unity ARKit Plugin内のサンプルでは、
UnityARAnchorManagerというクラスで該当の処理が実装されています。
UnityARAnchorManagerでは、UnityARUtilityに平面用の単一のprefabを持たせる実装になっており、
単一のprefabで問題ない場合は、UnityARAnchorManagerとUnityARUtilityを利用するのがスムーズです。
現実に合わせた影を表示する
影を表示するには、下記の3つの手順が必要になります。
- UnityARCameraManagerのEnableLightEstimationをtrueに
- Unity上にDirectionalLightを作成し、UnityARAmbientをAddComponentする
- 影のみ表示するためのMaterialとしてshadowPlaneMaterialが用意されているので、床などに設定する
Unity Editor上でデバッグする
Unity ARKit Plugin内にはUnityARKitRemoteというSceneファイルがあります。
そのSceneをiPhone実機で動かすことで、Unity RemoteのようにUnity Editor上でARKitを動作させることができます。
手順としては下記となります。
1 ARKitRemoteConnection プレハブをSceneに配置
2 Unity Editor上でRunを実行
3 iOS端末でUnityARKitRemote Sceneの入ったアプリを開く
4 UnityのConsole、Connected Playerから"iPhone"などを選択
5 UnityのGameウィンドウ内に"Start Remote ARKit Session"というボタンが出るのでクリック
これでiOSデバイスで映したカメラ情報およびARKit情報をUnity Editorで受け取ることができます。
映像と認識結果を連続で飛ばしていることもあり、遅延がかなり大きいのですが、ビルドに時間のかかるプロジェクトなどでは有用かと思います。
そのほか
9/13日現在では、Unity ARKit PluginはMetal依存となっているようです。
OpenGLES系で行なっていた描画処理などが動かない場合があるため、
既存のProjectをARKitに移植する際には注意が必要です。