Table of Contents

Accedere ai componenti AR nella sessione

Durante l'esecuzione di una sessione, è possibile accedere ai componenti delle varie funzionalità tramite la proprietà Assembly. Questo documento spiega come accedere a questi componenti e a cosa fare attenzione.

Prima di iniziare

Configurare i componenti AR in editor o prima dell'avvio

In alcuni casi, alcune opzioni dei componenti, come DesiredFocusMode, devono essere configurate prima dell'avvio del componente. Se non si vuole configurare e avviare manualmente i componenti dopo l'avvio della sessione, un modo semplice è configurare in anticipo tutti i componenti frame source che potrebbero essere usati prima dell'assemblaggio della sessione. Il processo di assemblaggio conserverà uno o più di questi componenti e applicherà la configurazione.

In questo caso si può usare qualsiasi metodo di base di Unity, come FindAnyObjectByType<T>() o GetComponent<T>(), per trovare i componenti e configurarli.

Nota

Non è certo quali componenti AR ottenuti con questo metodo verranno inclusi nella sessione a runtime. Pertanto, è necessario configurare tutte le possibilità.

Per esempio, il codice seguente mostra come modificare il focus mode di tutti i componenti frame source prima dell'assemblaggio della sessione:

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

Lo stesso procedimento può essere eseguito anche nell'editor; anche in questo caso è necessario configurare tutti i componenti.

alt text

Tra questi, la configurazione dei due frame source ARCoreARFoundationFrameSource e ARKitARFoundationFrameSource si trova sul componente Main Camera.

Avvertenza

I componenti AR ottenuti con questo metodo possono essere usati solo per la configurazione prima dell'esecuzione. Poiché il processo di assemblaggio filtra i componenti AR, quelli ottenuti dalla gerarchia della scena potrebbero non essere inclusi nella sessione e non funzionare correttamente.

Usare a runtime i componenti AR assemblati

I componenti AR usati nella sessione vengono determinati solo dopo l'assemblaggio. Prima che l'assemblaggio sia completato, nessun componente AR può essere usato. I componenti assemblati sono accessibili tramite la proprietà Assembly.

Assembly può essere usata quando lo stato della sessione è >= Assembled. In pratica, dopo il completamento del metodo Assemble(), la proprietà Assembly viene assegnata e può essere usata per accedere ai componenti della sessione. Dopo l'arresto o il danneggiamento della sessione, la proprietà Assembly viene svuotata e i componenti non sono più accessibili.

È possibile controllare lo stato State della sessione per capire quando è possibile accedere ai componenti AR:

if (Session.State >= ARSession.SessionState.Ready)
{
    // Assembly utilizzabile
}
else
{
    // Assembly non utilizzabile
}

Si può anche sottoscrivere l'evento StateChanged per ottenere i cambiamenti di stato della sessione e accedere ai componenti AR nel momento giusto. In genere, per intercettare lo stato Ready, bisogna sottoscrivere l'evento StateChanged prima dell'avvio della sessione; in pratica, farlo in Awake() è sicuro:

void Awake()
{
    Session.StateChanged += (state) =>
    {
        if (Session.State == ARSession.SessionState.Ready)
        {
            // Assembly utilizzabile; da qui in poi rimane accessibile finché la sessione non si ferma o si danneggia
        }
        else if (Session.State < ARSession.SessionState.Ready)
        {
            // Assembly non utilizzabile; da qui in poi resta inaccessibile finché la sessione non viene riavviata
        }
        else
        {
            // Assembly utilizzabile, di solito non serve gestire questo caso
        }
    };
}
Attenzione

Se i componenti AR ottenuti con FindAnyObjectByType<T>() o GetComponent<T>() sono sicuramente inclusi nella sessione, possono essere usati anche a runtime. È sicuro conservare il riferimento a questi componenti, ma quando li si usa è necessario assicurarsi che la sessione sia in esecuzione e che i componenti siano inclusi correttamente, altrimenti possono verificarsi eccezioni o comportamenti imprevisti. Prima dell'avvio della sessione e dopo il suo arresto questi componenti non possono funzionare. Si consiglia di prestare comunque attenzione allo stato State e all'evento StateChanged.

Accesso al componente frame source

È possibile usare la proprietà ARAssembly.FrameSource per accedere al componente frame source. In una sessione normale, ARAssembly.FrameSource esiste una e una sola volta.

Quando si usa la sessione, in genere è necessario accedere a ARAssembly.FrameSource per determinare il tipo reale del frame source usato a runtime, così da poter accedere alle proprietà e ai metodi specifici del componente.

Per esempio, il codice seguente mostra come usare metodi diversi di rilevamento dei piani in base al 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;
        }
    }
}

Accesso al componente frame filter

È possibile usare la proprietà ARAssembly.FrameFilters per accedere ai componenti frame filter. In una sessione normale, la lista ARAssembly.FrameFilters può contenere più componenti dello stesso tipo.

Per esempio, il codice seguente mostra come ottenere un MegaTrackerFrameFilter nella sessione e registrare l'evento corrispondente:

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

Accesso al componente camera

È possibile usare la proprietà ARAssembly.Camera per accedere al componente camera. Se nella scena ci sono più camere, questo è un modo rapido per trovare quella usata da AR.

Per esempio, il codice seguente mostra come ottenere la camera della sessione ed eseguire il raycast sugli oggetti della scena:

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

Accesso al componente origin

È possibile usare la proprietà ARAssembly.Origin per accedere al componente origin.

Per esempio, il codice seguente mostra come ottenere l'origin della sessione e visualizzare nella scena un cono che rappresenta la posizione e l'orientamento dell'attuale 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);
}

Va notato che qui bisogna prima verificare se ARAssembly.Origin esiste.

Nota

ARAssembly.Origin esiste solo nelle sessioni in cui è abilitato il tracking del movimento.

Accesso al componente CameraImageRenderer

È possibile usare la proprietà ARAssembly.CameraImageRenderer per accedere al componente CameraImageRenderer.

Per esempio, il codice seguente può ottenere il RenderTexture dell'immagine della fotocamera fisica:

RenderTexture renderTexture;

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

Va notato che qui bisogna prima verificare se ARAssembly.CameraImageRenderer esiste.

Nota

ARAssembly.CameraImageRenderer è valido solo nelle sessioni in cui il rendering è eseguito da EasyAR. In genere non è valido con AR Foundation o sui visori, dove il rendering dell'immagine della fotocamera fisica è eseguito da AR Foundation o dall'SDK del visore.

Accesso al componente FrameRecorder

È possibile usare la proprietà ARAssembly.FrameRecorder per accedere al componente FrameRecorder.

Per esempio, il codice seguente avvia la registrazione; la posizione del file dipende dalla configurazione e, per impostazione predefinita, viene salvato nella cartella di archiviazione dell'app:

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

Va notato che qui bisogna prima verificare se ARAssembly.FrameRecorder esiste.

Nota

ARAssembly.FrameRecorder in alcuni casi non è utilizzabile, ad esempio quando si usa FramePlayer.

Passi successivi

Argomenti correlati