유니티 AR TrackedImage Manager에 대해서 #AR Foundation

AR Tracked Image Manager란?

ARTrackedImageManager

 

ARTrackedImageManager는 trackable manager의 한 유형으로, 2D Image를 추적할 때 사용되는 매니저 입니다.

AR Tracked Image Manager는 Real World(실제 현실 공간)에서 감지된 각 Image에 대해 매칭되는 게임 오브젝트를 생성합니다.

 

(좌)  null일 때 빈 GameObject 생성 / (우) null이 아니고 ARTrackedImage가 자동으로 붙는

 

Tracked Image Prefab은 이미지를 감지했을 때 생성되는 GameObject입니다.

만약 Tracked Image Prefab이 null이면 매니저는 ARTrackedImage 컴포넌트만 있는 빈 GameObject를 생성합니다. 반대로 null이 아니지만 프리팹이 ARTrackedImage 컴포넌트를 가지고 있지 않다면, 매니저는 해당 컴포넌트를 추가합니다.

 

 

trackable managers란? 🔽

더보기

trackable managers란?

AR Foundation에는 다양한 유형의 추적 가능한 객체를 관리하는데, 이를 trackable managers라고 합니다.
예를 들어 plane, point 클라우드, 앵커, 얼굴, 몸, 이미지 및 3D 객체가 해당됩니다.

trackable managersXRImageTrackingSubsystem을 래핑하며 해당 데이터를 사용하여 추적 가능한 객체와 그에 해당하는 게임 오브젝트를 관리합니다.

예를 들어, ARPlaneManager 'XRPlaneSubsystem'에서 제공하는 데이터를 사용하여 ARPlane 추적 가능한 객체를 생성합니다.

 

  Reference Image Library / 만드는 방법

 

이미지가 감지되기 전에 ARTrackedImageManager Reference Image Library에 컴파일된 Ref Image를 찾도록 지시해야 하며, 이 라이브러리에 있는 '이미지만' 감지합니다.

 

용어 설명
Reference image XRImageTrackingSubsystem이 Real World에서 찾으려고 하는 이미지입니다. 서브시스템은 감지된 이미지를 참조 이미지와 연결합니다. 
Reference image library Reference image를 모아둔 곳입니다.

 


콜백 함수

ARTrackedImageManager trackedImagesChanged 이벤트를 구독하여 이미지가 추가되거나(처음 감지될 때), 업데이트되거나 제거될 때마다 알림을 받을 수 있습니다.

[SerializeField]
ARTrackedImageManager m_TrackedImageManager;

void OnEnable() => m_TrackedImageManager.trackedImagesChanged += OnChanged;

void OnDisable() => m_TrackedImageManager.trackedImagesChanged -= OnChanged;

void OnChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
    foreach (var newImage in eventArgs.added)
    {
        // Handle added event
    }

    foreach (var updatedImage in eventArgs.updated)
    {
        // Handle updated event
    }

    foreach (var removedImage in eventArgs.removed)
    {
        // Handle removed event
    }
}

 


 

Tracking State

State 설명
None 이미지가 추적되고 있지 않는 상태를 뜻합니다. 
Limited 이미지는 추적되고 있지만 제대로 추적되지 않는 상태를 뜻합니다. 

        1. 카메라에 보이지 않도록 이미지를 가리는 경우.
        2. 이미지가 움직이는 이미지로 추적되지 않는 경우. 예를 들어 maxNumberOfMovingImages를 초과하는 경우.
Tracking 이미지를 활발하게 추적하고 있는 상태를 뜻합니다

 


추적 중인 모든 Trackable Image 목록 조회하는 방법

void ListAllImages()
{
    foreach (var trackedImage in m_TrackedImageManager.trackables)
    {
        Debug.Log($"Image: {trackedImage.referenceImage.name} is at " +
                  $"{trackedImage.transform.position}");
    }
}

 


특정 Trackable Image에 접근하는 방법

ARTrackedImage GetImageAt(TrackableId trackableId)
{
    return m_TrackedImageManager.trackables[trackableId];
}

 


여러개의 Trackable Images를 참조하는 방법

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

[System.Serializable]
public struct PlaceablePrefabs
{
    public string name; // name corresponding to the tracked image name
    public GameObject prefab;
}

public class ARImageMultipleObjectsSpawner : MonoBehaviour
{
    private ARTrackedImageManager imgManager;

    public PlaceablePrefabs[] prefabs;

    private Dictionary<string, GameObject> spawnedPrefabs = new Dictionary<string, GameObject>();

    private void Awake()
    {
        imgManager = GetComponent<ARTrackedImageManager>();
        
        foreach (PlaceablePrefabs prefab in prefabs)
        {
            // instantiate the prefab and store to the dictionary
            GameObject instantiated = Instantiate(prefab.prefab, Vector3.zero, Quaternion.identity);
            instantiated.name = prefab.name;
            spawnedPrefabs.Add(instantiated.name, instantiated);
            instantiated.SetActive(false);

        }
    }

    private void OnEnable()
    {
        imgManager.trackedImagesChanged += OnImageChanged;
    }

    private void OnDisable()
    {
        imgManager.trackedImagesChanged -= OnImageChanged;
    }

    private void OnImageChanged(ARTrackedImagesChangedEventArgs args)
    {

        foreach (ARTrackedImage img in args.added)
        {
            UpdateSpawned(img);
        }

        foreach (ARTrackedImage img in args.updated)
        {
            UpdateSpawned(img);
        }

        foreach (ARTrackedImage img in args.removed)
        {
            // disable the prefab that has the same name than the image
            spawnedPrefabs[img.referenceImage.name].SetActive(false);
        }

    }
    
    private void UpdateSpawned(ARTrackedImage img)
    {
        string name = img.referenceImage.name;

        GameObject spawned = spawnedPrefabs[name];

        Debug.Log("spawned " + spawned.name);


        // only update when tracking state is good
        if (img.trackingState == TrackingState.Tracking)
        {
            Debug.Log("Updating image "+ img.referenceImage.name+" at "+img.transform.position);

            spawned.transform.position = img.transform.position;
            spawned.transform.rotation = img.transform.rotation;
            spawned.SetActive(true);
        } else
        {
            // poor or no tracking state
            spawned.SetActive(false);

        }
    }
}

 

세팅

 

결과