XREAL Air 2 Ultra:Image Tracking を使いこなす(複数マーカー制御)
はじめに
特定のマーカー1つを追従させるだけでなく、「画像Aを見たらオブジェクトA」「画像Bを見たらオブジェクトB」と、画像に応じて表示内容を切り替えたいケースは多いです。
今回は、ヒエラルキー上のオブジェクトを有効活用して、画像名(Name)ベースで表示を制御する方法を解説します。
ImageTracking導入は、以下を参照してください。
1. Hierarchy方式 vs Prefab方式
AR Foundationでオブジェクトを表示するには、大きく分けて2つのアプローチがあります。今回のサンプルでは、リソース管理が容易な Hierarchy方式 を採用しています。
| 特徴 | Hierarchy方式 | Prefab方式 |
|---|---|---|
| 仕組み | シーン上に配置済みのオブジェクトを動かす | 検知のたびにプレハブを生成・破棄する |
| 同時表示 | 単一のUIを使い回すのに適している | 複数の画像を同時に出すのに適している |
| 負荷 | 生成・破棄がないため軽量 | 頻繁に検知・ロストすると負荷がかかる |
| 参照 | 他のスクリプトとの連携が容易 | 動的に生成されるため参照の管理が複雑 |
使い分けの基準
「今見ているものに対して1つだけ情報を出す」マニュアル的なアプリなら、Hierarchy方式がシンプルでパフォーマンスも高く、おすすめです。
2. 実装:NamedImageTrackingAction.cs
このスクリプトは、Image Libraryで設定した「画像の名前」と「表示したいオブジェクト」を紐付けます。
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using System;
using System.Collections.Generic;
namespace Studist.XrealSampler.XREAL003.Domain
{
public class NamedImageTrackingAction : MonoBehaviour
{
[Serializable]
public struct ImageMapping
{
public string imageName; // Image Libraryで設定した名前
public GameObject targetObject; // 表示させたいヒエラルキー上のオブジェクト
}
[SerializeField] ARTrackedImageManager _trackedImageManager;
[SerializeField] List<ImageMapping> _mappings;
void OnEnable() => _trackedImageManager.trackedImagesChanged += OnChanged;
void OnDisable() => _trackedImageManager.trackedImagesChanged -= OnChanged;
void OnChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
// 新規検知
foreach (var newImage in eventArgs.added)
{
UpdateObject(newImage, true);
}
// 更新(追従)
foreach (var updatedImage in eventArgs.updated)
{
// トラッキング状態が「Tracking」の時だけ位置を更新
UpdateObject(updatedImage, updatedImage.trackingState == TrackingState.Tracking);
}
// 消失
foreach (var removedImage in eventArgs.removed)
{
UpdateObject(removedImage, false);
}
}
private void UpdateObject(ARTrackedImage trackedImage, bool isActive)
{
if (trackedImage == null || trackedImage.referenceImage == null) return;
// ライブラリで設定した画像名を取得
string referenceName = trackedImage.referenceImage.name;
foreach (var mapping in _mappings)
{
if (mapping.imageName == referenceName)
{
if (mapping.targetObject != null)
{
mapping.targetObject.SetActive(isActive);
if (isActive)
{
mapping.targetObject.transform.position = trackedImage.transform.position;
mapping.targetObject.transform.rotation = trackedImage.transform.rotation;
}
}
break;
}
}
}
}
}
3. セットアップのポイント
Image LibraryのNameを確認
XR Reference Image Library を開き、各画像に付けた Name(例: Guide_A, Guide_B)を確認してください。これがスクリプトとの紐付けキーになります。
インスペクターでの紐付け
-
XR OriginなどにNamedImageTrackingActionをアタッチ。 - Mappings リストを追加。
-
Image Nameにライブラリの画像名を正確に入力し、Target Objectにヒエラルキー上の対応するパネルをアタッチ。
ヒエラルキー上のターゲットオブジェクトは、あらかじめ
SetActive(false)で非表示にします。
4. 実際に動かしてみた感想
検知レスポンス
視野に対象の画像を入れた瞬間の反応が非常に良く、ストレスなく画像検知が始まります。
角度に強いトラッキング
画像に対して真っ直ぐ向き合う必要はなく、机の上に置いた状態などの「斜めの角度」からでも問題なく検知・追従してくれます。
追従の限界
ゆっくりとした動きには正確に追従しますが、画像を素早く動かしすぎると追従が少し遅れる傾向があります。
また、複数の画像を同時に動かすと、検知が不安定になります。
実用上は、静止しているコンテンツを出す用途が最適だと感じました。