Table of Contents

Session中のAR機能コンポーネントへのアクセス

実行中のsession内では、Assemblyプロパティを通じて各機能コンポーネントにアクセスできます。このドキュメントでは、これらのコンポーネントへのアクセス方法と、アクセス時に留意すべき点について説明します。

開始する前に

編集時または起動前の AR コンポーネント設定

時には、特定のコンポーネントオプション(例: DesiredFocusMode)は、コンポーネント起動前に設定する必要があります。セッション開始後に手動で設定してコンポーネントを起動したくない場合、シンプルな方法は、セッションのアセンブリ前に使用される可能性のある全ての frame source コンポーネントを設定することです。アセンブリプロセスはこれらのコンポーネントの1つ以上を保持し、その設定を適用します。

この場合、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

ここで、ARCoreARFoundationFrameSource および ARKitARFoundationFrameSource の2つの 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イベントに注意を払うことを推奨します。

Frame source コンポーネントへのアクセス

ARAssembly.FrameSource プロパティを使用して frame source コンポーネントにアクセスできます。正常に動作する session では、ARAssembly.FrameSource は厳密に1つだけ存在します。

session を使用する際には、通常、ARAssembly.FrameSource にアクセスして、ランタイムで実際に使用されている frame source コンポーネントのタイプを特定し、そのコンポーネント固有のプロパティやメソッドにアクセスする必要があります。

例えば、以下のコードは、frame source の違いに応じて異なる平面検出方法を使用する方法を示しています:

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 コンポーネントにアクセスできます。シーン内に複数のカメラが存在する場合、ARで使用されているカメラをすばやく見つける方法です。

例えば、以下のコードはセッション内のカメラを取得し、シーン内のオブジェクトに対してレイキャストを実行する方法を示しています:

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

Access origin component

ARAssembly.Origin プロパティを使用して origin コンポーネントにアクセスできます。

例えば、以下のコードは session 内の 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 は、運動追跡機能が有効な session でのみ存在します。

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 によってレンダリングが行われる session でのみ有効です。一般的に、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.FrameRecorderは、FramePlayerを使用する場合など、まれなケースでは利用できません。

次のステップ

関連トピック

  • フレームデータソース は frame source とそのランタイム選択方法について説明しています
  • XR Origin は AR シーンにおける origin コンポーネントの目的について説明しています
  • カメラ は AR シーンにおける camera コンポーネントの目的について説明しています
  • EIFファイルの録画FrameRecorder の詳細な使用方法について説明しています