Table of Contents

session 内の AR 機能コンポーネントへのアクセス

実行中の session では、Assembly プロパティを通じてさまざまな機能コンポーネントにアクセスできます。この記事では、これらのコンポーネントへのアクセス方法と、利用時の注意点を説明します。

開始前

編集時または起動前に AR コンポーネントを設定する

場合によっては、DesiredFocusMode のような一部のコンポーネント設定を、コンポーネントの起動前に設定する必要があります。session 起動後に手動でコンポーネントを設定して起動したくない場合は、session の組み立て前に、使用される可能性のあるすべての frame source コンポーネントを設定しておくのが簡単です。組み立て処理は、それらのコンポーネントのうち 1 つ以上を保持し、その設定を適用します。

このときは、FindAnyObjectByType<T>()GetComponent<T>() などの Unity の基本メソッドを使ってコンポーネントを見つけ、その後で設定できます。

注記

この方法で取得した AR コンポーネントが実行時に session に含まれるかどうかは不確定です。したがって、あり得るすべてのケースを設定する必要があります。

たとえば、次のコードは、session の組み立て前にすべての 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 コンポーネントが session に含まれない可能性があり、その場合は正常に動作しません。

実行中に組み上げ済みの AR コンポーネントを使う

session 内で実行される AR コンポーネントは、組み立て後に確定します。組み立てが完了するまでは、どの AR コンポーネントも使用できません。組み上げ済みの AR コンポーネントには、Assembly プロパティからアクセスできます。

Assembly は session の状態が >= Assembled のときに使用できます。具体的には、Assemble() メソッドの実行完了後に Assembly プロパティへ値が入るので、そこから session コンポーネントへアクセスできます。session が停止または破損した後は、Assembly プロパティはクリアされ、コンポーネントにはアクセスできなくなります。

スクリプト内で session の State を確認すれば、その時点で AR コンポーネントにアクセスできるかどうかを判断できます。

if (Session.State >= ARSession.SessionState.Ready)
{
    // Assembly は使用可能
}
else
{
    // Assembly は使用不可
}

StateChanged イベントを購読して session の状態変化を受け取り、適切なタイミングで AR コンポーネントにアクセスすることもできます。一般に、Ready 状態を確実に受け取るには、session start の前に StateChanged イベントを購読する必要があります。通常は Awake() で購読しておくのが安全です。

void Awake()
{
    Session.StateChanged += (state) =>
    {
        if (Session.State == ARSession.SessionState.Ready)
        {
            // Assembly は使用可能です。この後、session が停止または破損するまで Assembly にアクセスできます
        }
        else if (Session.State < ARSession.SessionState.Ready)
        {
            // Assembly は使用できません。この後、session が再起動されるまで Assembly にはアクセスできません
        }
        else
        {
            // Assembly は使用可能です。通常は処理不要です
        }
    };
}
注意

FindAnyObjectByType<T>()GetComponent<T>() などの方法で取得した AR コンポーネントが必ず session に含まれることが分かっている場合は、実行時にも使用できます。
これらのコンポーネントへの参照を保持すること自体は安全ですが、使用時には session が実行中であり、これらのコンポーネントが正しく session に含まれていることを必ず確認してください。そうしないと、例外や予期しない動作が起こる可能性があります。
session 開始前と停止後は、これらのコンポーネントは動作しません。そのような使い方でも、session の StateStateChanged イベントを確認することを推奨します。

フレームソースコンポーネントへのアクセス

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;
        }
    }
}

フレームフィルターコンポーネントへのアクセス

ARAssembly.FrameFilters プロパティを使って frame filter コンポーネントにアクセスできます。通常動作する session では、ARAssembly.FrameFilters リスト内の任意の型のコンポーネントが複数存在することがあります。

たとえば、次のコードは session 内の MegaTrackerFrameFilter を取得し、対応するイベントを登録する例です。

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

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

ARAssembly.Camera プロパティを使って camera コンポーネントにアクセスできます。シーン内に複数の camera がある場合でも、AR で使われている camera をすばやく見つける手段になります。

たとえば、次のコードは session 内の camera を取得し、シーン内の物体にレイ判定を行う例です。

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

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

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

たとえば、次のコードは session 内の origin を取得し、現在の camera の位置と向きを表す錐体をシーンに表示する例です。

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 や HMD を使っている場合は無効で、その場合の物理カメラ映像の描画は AR Foundation または HMD SDK が担当します。

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

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

たとえば、次のコードで録画を開始できます。ファイルの保存先は設定に依存し、既定ではアプリの内部保存ディレクトリに保存されます。

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

ここでは、ARAssembly.FrameRecorder が存在するかを先に確認する必要があります。

注記

ARAssembly.FrameRecorder は、FramePlayer を使う場合など、まれな状況では使用できません。

後続手順

  • session の実行結果を取得する 方法を学びます。これらの結果には AR コンポーネントの実行出力が含まれます。
  • さらに、次のサンプルを通してコンポーネントのアクセス方法を確認できます。

関連トピック

  • フレームデータソース は frame source とその実行時の選択方法を説明します。
  • XR Origin は AR シーンにおける origin コンポーネントの役割を説明します。