本日、会社で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に移植する際には注意が必要です。