Table of Contents

접근 session 내의 ar 기능 구성 요소

실행 중인 session 내에서, Assembly 속성을 통해 각 기능 구성 요소에 접근할 수 있습니다. 이 문서는 이러한 구성 요소에 접근하는 방법과 접근 시 주의해야 할 사항에 대해 설명합니다.

시작하기 전에

편집 시 또는 시작 전 ar 구성 요소 설정

때로는 DesiredFocusMode와 같은 특정 구성 요소 옵션은 시작 전에 설정해야 합니다. 세션 시작 후 수동으로 구성 요소를 설정하고 시작하는 것을 원하지 않는다면, 세션 조립 전에 사용 가능한 모든 frame source 구성 요소를 미리 설정하는 간단한 방법이 있습니다. 조립 과정은 이러한 구성 요소 중 하나 이상을 유지하며 해당 설정을 적용합니다.

이때 FindAnyObjectByType<T>() 또는 GetComponent<T>() 등 Unity 기본 메서드를 사용하여 구성 요소를 찾은 후 설정할 수 있습니다.

[!참고] 이 방법으로 얻은 ar 구성 요소가 런타임에 세션에 포함될지는 확실하지 않습니다. 따라서 가능한 모든 경우에 대해 설정해야 합니다.

예를 들어, 아래 코드는 세션 조립 전에 모든 frame source 구성 요소의 초점 모드를 수정하는 과정을 보여줍니다:

void Awake()
{
    var allFrameSources = Session.GetComponentsInChildren<FrameSource>();
    foreach (var source in allFrameSources)
    {
        if (source is CameraDeviceFrameSource)
        {
            ((CameraDeviceFrameSource)source).DesiredFocusMode = autoFocus ? CameraDeviceFocusMode.Continousauto : CameraDeviceFocusMode.Medium;
        }
        else if (source is MotionTrackerFrameSource)
        {
            ((MotionTrackerFrameSource)source).DesiredFocusMode = autoFocus ? MotionTrackerCameraDeviceFocusMode.Continousauto : MotionTrackerCameraDeviceFocusMode.Medium;
        }
        else if (source is ARCoreFrameSource)
        {
            ((ARCoreFrameSource)source).DesiredFocusMode = autoFocus ? ARCoreCameraDeviceFocusMode.Auto : ARCoreCameraDeviceFocusMode.Fixed;
        }
        else if (source is ARKitFrameSource)
        {
            ((ARKitFrameSource)source).DesiredFocusMode = autoFocus ? ARKitCameraDeviceFocusMode.Auto : ARKitCameraDeviceFocusMode.Fixed;
        }
        else if (source is AREngineFrameSource)
        {
            ((AREngineFrameSource)source).DesiredFocusMode = autoFocus ? AREngineCameraDeviceFocusMode.Auto : AREngineCameraDeviceFocusMode.Fixed;
        }
        else if (source is ThreeDofCameraDeviceFrameSource)
        {
            ((ThreeDofCameraDeviceFrameSource)source).DesiredFocusMode = autoFocus ? ThreeDofCameraDeviceFocusMode.Auto : ThreeDofCameraDeviceFocusMode.Fixed;
        }
        else if (source is InertialCameraDeviceFrameSource)
        {
            ((InertialCameraDeviceFrameSource)source).DesiredFocusMode = autoFocus ? InertialCameraDeviceFocusMode.Auto : InertialCameraDeviceFocusMode.Fixed;
        }
        else if (source is ARFoundationFrameSource)
        {
            cameraManager.autoFocusRequested = autoFocus;
        }
    }
}

이 과정은 에디터에서도 완료할 수 있으며, 마찬가지로 모든 구성 요소를 설정해야 합니다:

alt text

여기서 ARCoreARFoundationFrameSourceARKitARFoundationFrameSource 두 frame source에 대한 설정은 Main Camera의 구성 요소에 있습니다.

[!경고] 이 방법으로 얻은 ar 구성 요소는 실행 전 설정에만 사용할 수 있습니다.
조립 과정이 ar 구성 요소를 필터링하기 때문에, 씬 계층 구조에서 얻은 ar 구성 요소는 세션에 포함되지 않아 제대로 작동하지 않을 수 있습니다.

실행 중에 조립된 AR 컴포넌트 사용하기

세션에서 실행되는 AR 컴포넌트는 조립이 완료된 후에야 확정됩니다. 조립이 완료되기 전에는 어떤 AR 컴포넌트도 사용할 수 없습니다. 조립된 AR 컴포넌트는 Assembly 속성을 통해 접근할 수 있습니다.

Assembly는 세션의 상태가 >= Assembled인 경우에 사용할 수 있습니다. 구체적으로, Assemble() 메서드 실행이 완료된 후에야 Assembly 속성에 값이 할당되어 세션 컴포넌트에 접근할 수 있습니다. 세션이 중지되거나 손상된 후에는 Assembly 속성이 지워져 컴포넌트에 더 이상 접근할 수 없습니다.

스크립트에서 세션의 State를 확인하여 AR 컴포넌트에 접근 가능한 시점을 판단할 수 있습니다:

if (Session.State >= ARSession.SessionState.Ready)
{
    // Assembly 사용 가능
}
else
{
    // Assembly 사용 불가
}

또는 StateChanged 이벤트를 구독하여 세션 상태 변화를 감지하고 적절한 시점에 AR 컴포넌트에 접근할 수 있습니다. 일반적으로 Ready 상태를 확실히 포착하려면 세션 시작 전에 StateChanged 이벤트를 구독해야 합니다. 보통 Awake()에서 구독하는 것이 안전합니다:

void Awake()
{
    Session.StateChanged += (state) =>
    {
        if (Session.State == ARSession.SessionState.Ready)
        {
            // Assembly 사용 가능. 이후 세션이 중지되거나 손상될 때까지 계속 접근 가능.
        }
        else if (Session.State < ARSession.SessionState.Ready)
        {
            // Assembly 사용 불가. 이후 세션이 재시작될 때까지 계속 접근 불가.
        }
        else
        {
            // Assembly 사용 가능. 일반적으로 처리할 필요 없음.
        }
    };
}
주의

FindAnyObjectByType<T>() 또는 GetComponent<T>() 등의 방법으로 AR 컴포넌트를 가져오면 해당 컴포넌트는 반드시 세션에 포함되며, 런타임에서도 사용할 수 있습니다.
이러한 컴포넌트에 대한 참조를 저장하는 것은 안전하지만, 사용 시에는 세션이 실행 중이고 해당 컴포넌트가 세션에 올바르게 포함되어 있는지 반드시 확인해야 합니다. 그렇지 않으면 예외가 발생하거나 예상치 못한 동작이 발생할 수 있습니다.
세션 시작 전과 중지 후에는 이러한 컴포넌트는 작동하지 않습니다. 이러한 방법을 사용하더라도 세션의 StateStateChanged 이벤트를 주의 깊게 살펴보는 것이 좋습니다.

프레임 소스 컴포넌트 접근

ARAssembly.FrameSource 속성을 통해 프레임 소스 컴포넌트에 접근할 수 있습니다. 정상 작동하는 세션 내에서 ARAssembly.FrameSource는 반드시 하나만 존재합니다.

세션을 사용할 때, 일반적으로 ARAssembly.FrameSource에 접근하여 런타임에 실제로 사용되는 프레임 소스 컴포넌트 유형을 확인해야 합니다. 이를 통해 해당 컴포넌트의 고유 속성과 메서드에 접근할 수 있습니다.

예를 들어, 아래 코드는 프레임 소스에 따라 서로 다른 평면 감지 방법을 사용하는 방법을 보여줍니다:

void PlaceObject(Vector2 touchPosition)
{
    if (Session.Assembly.FrameSource is MotionTrackerFrameSource)
    {
        Ray ray = Session.Assembly.Camera.ScreenPointToRay(touchPosition);
        if (Physics.Raycast(ray, out var hitInfo))
        {
            TouchRoot.transform.position = hitInfo.point;
        }
    }
    else if (Session.Assembly.FrameSource is ARFoundationFrameSource)
    {
        var raycastManager = Session.Assembly.Origin.Value.GetComponent<UnityEngine.XR.ARFoundation.ARRaycastManager>();
        var hits = new List<UnityEngine.XR.ARFoundation.ARRaycastHit>();
        if (raycastManager.Raycast(touchPosition, hits, UnityEngine.XR.ARSubsystems.TrackableType.PlaneWithinPolygon))
        {
            var hitPose = hits[0].pose;
            TouchRoot.transform.position = hitPose.position;
        }
    }
}

Frame filter 컴포넌트 접근

ARAssembly.FrameFilters 속성을 사용하여 frame filter 컴포넌트에 접근할 수 있습니다. 정상 작동하는 세션에서 ARAssembly.FrameFilters 목록 내의 모든 유형의 컴포넌트는 여러 개 존재할 수 있습니다.

예를 들어, 다음 코드는 세션에서 MegaTrackerFrameFilter을 가져오고 해당 이벤트를 등록하는 방법을 보여줍니다:

var megaTracker = session.Assembly.FrameFilters.Where(f => f is MegaTrackerFrameFilter).FirstOrDefault() as MegaTrackerFrameFilter;
if (megaTracker)
{
    megaTracker.LocalizationRespond += (response) =>
    {
    };
}

Camera 컴포넌트 접근

ARAssembly.Camera 속성을 사용하여 camera 컴포넌트에 접근할 수 있습니다. scene에 여러 camera가 있는 경우, AR에서 사용하는 camera를 빠르게 찾는 방법입니다.

예를 들어, 아래 코드는 session의 camera를 가져와 scene 내 객체에 대해 raycast를 수행하는 방법을 보여줍니다:

var ray = Session.Assembly.Camera.ScreenPointToRay(screenPoint);
if (Physics.Raycast(ray, out var hitInfo))
{
    TouchRoot.transform.position = hitInfo.point;
};

Access origin 컴포넌트

ARAssembly.Origin 속성을 사용하여 origin 컴포넌트에 접근할 수 있습니다.

예를 들어, 다음 코드는 세션에서 origin을 가져와 현재 카메라 위치와 방향을 나타내는 피라미드를 장면에 표시하는 방법을 보여줍니다:

if (session.Assembly.Origin.OnSome)
{
    GameObject frustum = Instantiate(CameraFrustumPrefab, session.Assembly.Camera.transform.position, session.Assembly.Camera.transform.rotation);
    frustum.transform.SetParent(session.Assembly.Origin.Value.transform);
}

여기서는 먼저 ARAssembly.Origin의 존재 여부를 확인해야 합니다.

참고

ARAssembly.Origin은 모션 추적 기능이 활성화된 세션에서만 존재합니다.

CameraImageRenderer 컴포넌트에 접근하기

ARAssembly.CameraImageRenderer 속성을 사용하여 CameraImageRenderer 컴포넌트에 접근할 수 있습니다.

예를 들어, 다음 코드는 물리적 카메라 이미지의 RenderTexture를 가져옵니다:

RenderTexture renderTexture;

void Awake()
{
    Session.StateChanged += (state) =>
    {
        if (state == ARSession.SessionState.Ready && Session.Assembly.CameraImageRenderer.OnSome)
        {
            Session.Assembly.CameraImageRenderer.Value.RequestTargetTexture((_, texture) => renderTexture = texture);
        }
    };
}

여기서는 ARAssembly.CameraImageRenderer의 존재 여부를 먼저 확인해야 합니다.

참고

ARAssembly.CameraImageRenderer는 EasyAR이 화면을 렌더링하는 세션에서만 유효합니다. 일반적으로 AR Foundation이나 헤드셋을 사용할 때는 무효하며, 이때 물리적 카메라 화면 렌더링은 AR Foundation이나 헤드셋 SDK에서 수행됩니다.

FrameRecorder 컴포넌트에 액세스

ARAssembly.FrameRecorder 속성을 사용하여 FrameRecorder 컴포넌트에 액세스할 수 있습니다.

예를 들어, 다음 코드는 녹화를 시작하며 파일 저장 위치는 구성에 따라 결정됩니다. 기본적으로 애플리케이션 내부 저장소 디렉터리에 저장됩니다:

if (session.Assembly.FrameRecorder.OnSome)
{
    var frameRecorder = session.Assembly.FrameRecorder.Value;
    frameRecorder.enabled = true;
}

여기서는 먼저 ARAssembly.FrameRecorder의 존재 여부를 확인해야 합니다.

[!참고] ARAssembly.FrameRecorderFramePlayer를 사용할 때와 같은 일부 경우에는 사용할 수 없습니다.

다음 단계

관련 주제