はじめに
ARFoundationのImageTrackingを使えば登録した画像マーカーを認識することにより、
任意のARオブジェクトを出現させることができます。
【参考リンク】:ARFoundationを触ってみた
実は画像マーカーを複数登録することも可能なようです。
今回はそれについて調べたのでメモします。
内容としては"認識した画像マーカーそれぞれの上にARオブジェクトを出す"だけに留めます。
下記のような難しい実装の手法をこの記事で書くわけでないということ予め明示しておきます。
×複数の画像マーカーの位置関係を固定した、広域対応のARの手法。
【参考リンク】:【GyroEye Holo】マーカー位置
デモ
画像マーカー二枚のそれぞれに対応したARオブジェクトを表示しています。
あまり用途は無いかもですが、ロスト時に非表示にする実装も試してみました。
バージョン情報
諸々名前 | バージョン |
---|---|
Unity | 2020.3.4f1 |
ARFoundation | 4.0.12 |
ARCore XR Plugin | 4.0.12 |
ARKit XR Plugin | 4.0.12 |
XR Plugin Management | 4.0.1 |
※Andoroidでしか試していませんが、ARFoundationなのでiosでも動くはず、、、です。
##下準備
バージョン情報に従って一通りビルドできるまでの環境構築が終わったら、下記画像を参考にReferenceImageLibrary
を作成します。
次にReferenceImageLibrary
を設定します。
あとはAR Session Origin
にAR Tracked Image Manager
を設定し、
Serialized Library
に先ほど作成したReferenceImageLibrary
を設定すれば準備完了です。
コード
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
/// <summary>
/// 画像マーカー複数対応のサンプル
/// </summary>
public class MultiMarker : MonoBehaviour
{
/// <summary>
/// マーカー用オブジェクトのプレハブ
/// </summary>
[SerializeField] private GameObject[] _arPrefabs;
/// <summary>
/// ARTrackedImageManager
/// </summary>
[SerializeField] private ARTrackedImageManager _imageManager;
/// <summary>
/// マーカー用オブジェクトのプレハブと文字列を紐づけた辞書
/// </summary>
private readonly Dictionary<string, GameObject> _markerNameAndPrefabDictionary = new Dictionary<string, GameObject>();
private void Start()
{
_imageManager.trackedImagesChanged += OnTrackedImagesChanged;
//辞書を作る 画像の名前とARオブジェクトのPrefabを紐づける
for (var i = 0; i < _arPrefabs.Length; i++)
{
var arPrefab = Instantiate(_arPrefabs[i]);
_markerNameAndPrefabDictionary.Add(_imageManager.referenceLibrary[i].name, arPrefab);
arPrefab.SetActive(false);
}
}
private void OnDisable()
{
_imageManager.trackedImagesChanged -= OnTrackedImagesChanged;
}
/// <summary>
/// 認識した画像マーカーに応じて紐づいたARオブジェクトを表示
/// </summary>
/// <param name="trackedImage">認識した画像マーカー</param>
private void ActivateARObject(ARTrackedImage trackedImage)
{
//認識した画像マーカーの名前を使って辞書から任意のオブジェクトを引っ張り出す
var arObject = _markerNameAndPrefabDictionary[trackedImage.referenceImage.name];
var imageMarkerTransform = trackedImage.transform;
//位置合わせ
var markerFrontRotation = imageMarkerTransform.rotation * Quaternion.Euler(90f, 0f, 0f);
arObject.transform.SetPositionAndRotation(imageMarkerTransform.transform.position, markerFrontRotation);
arObject.transform.SetParent(imageMarkerTransform);
//トラッキングの状態に応じてARオブジェクトの表示を切り替え
arObject.SetActive(trackedImage.trackingState == TrackingState.Tracking);
}
/// <summary>
/// TrackedImagesChanged時の処理
/// </summary>
/// <param name="eventArgs">検出イベントに関する引数</param>
private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
foreach (var trackedImage in eventArgs.added)
{
ActivateARObject(trackedImage);
}
foreach (var trackedImage in eventArgs.updated)
{
ActivateARObject(trackedImage);
}
}
}
やっていることは下記です。
①"ReferenceImageLibrary
に登録した画像の名前"と"表示したいARオブジェクトのPrefab"を辞書で紐づける。
②画像マーカー認識時に画像の名前に紐づけられたARオブジェクトを出現させる。
###ARTrackedImageManager.trackedImagesChanged
trackedImagesChanged
に画像マーカー認識時のイベントハンドラーを設定できます。
イベントハンドラーの引数であるARTrackedImagesChangedEventArgs
からは
下記3種類の情報をそれぞれのタイミングで得ることができます。
Type | Name | Description |
---|---|---|
List | added | The list of ARTrackedImages added since the last event. |
List | updated | The list of ARTrackedImages updated since the last event. |
List | removed | The list of ARTrackedImages removed since the last event. |
【引用元】:Struct ARTrackedImagesChangedEventArgs
added
とupdated
の使い道は理解できたのですが、removed
がいまいち使い道がわかりませんでした。
The list of ARTrackedImages removed since the last event.
という説明から、画像をロストした時?かと思い、
その前提で実装を組んでみましたが、何をやっても呼ばれずです。
使い道等知ってる方いたら教えてください。
###TrackingState
先ほど画像をロストした時
について実装を試みたと書きましたが、
それについてはTrackingState
が有効でした。
ARTrackedImage(認識した画像)から三種類取得できます。
TrackingState | Description |
---|---|
Limited | Some tracking information is available, but it is limited or of poor quality. |
None | Not tracking. |
Tracking | Tracking is working normally. |
【引用元】: Enum TrackingState
簡単に言うとLimited
は認識精度が低い時、None
は非認識時、Tracking
は認識した時 といった感じです。
##おわりに
画像マーカーを動かすと、再認識とロストを繰り返してARオブジェクトがカクカクし始めるので、
平面に固定することを前提として使った方がいいかも と色々と実験しながら思いました。
##参考リンク
AR Foundation Improved Image Tracking - Multiple Objects/Images - Unity Augmented Reality/AR