Sistemi di coordinate in Unity

Windows Mixed Reality supporta le app in un'ampia gamma di scalabilità di esperienze, dalle app solo orientamento e su larga scala fino alle app su scala locale. In HoloLens puoi andare oltre e creare app su scala mondiale che consentono agli utenti di camminare oltre i 5 metri, esplorando un intero piano di un edificio e oltre.

Il primo passaggio per creare un'esperienza di realtà mista in Unity consiste nel comprendere i sistemi di coordinate e scegliere la scalabilità dell'esperienza di destinazione dell'app.

Creazione di un'esperienza solo orientamento o su scala seduta

Spazio dei nomi:UnityEngine.XR
Type:XRDevice

Per creare un'esperienza di solo orientamento o su scala seduta, è necessario impostare Unity sul tipo di spazio di rilevamento stazionario. Lo spazio di rilevamento stazionario imposta il sistema di coordinate mondiali di Unity per tenere traccia del frame di riferimento fisso. Nella modalità di rilevamento stazionario, il contenuto inserito nell'editor proprio davanti alla posizione predefinita della fotocamera (in avanti è -Z) verrà visualizzato davanti all'utente all'avvio dell'app.

XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);

Spazio dei nomi:UnityEngine.XR
Type:InputTracking

Per un'esperienza di orientamento puro, ad esempio un visualizzatore video a 360 gradi (in cui gli aggiornamenti della testa posizionale rovinerebbero l'illusione), è quindi possibile impostare XR. InputTracking.disablePositionalTracking su true:

InputTracking.disablePositionalTracking = true;

Per un'esperienza su larga scala seduta, per consentire all'utente di più recente l'origine seduta, è possibile chiamare la richiesta XR. Metodo InputTracking.Recenter :

InputTracking.Recenter();

Creazione di un'esperienza su larga scala o su larga scala

Spazio dei nomi:UnityEngine.XR
Type:XRDevice

Per un'esperienza su larga scala o su scala locale, è necessario posizionare il contenuto rispetto al pavimento. Il motivo è che il piano dell'utente usa la fase spaziale, che rappresenta l'origine a livello di piano definita dell'utente e il limite facoltativo della sala, configurato durante la prima esecuzione.

Per assicurarsi che Unity funzioni con il sistema di coordinate globale a livello di piano, è possibile impostare e verificare che Unity usi il tipo di spazio di rilevamento RoomScale:

if (XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale))
{
    // RoomScale mode was set successfully.  App can now assume that y=0 in Unity world coordinate represents the floor.
}
else
{
    // RoomScale mode was not set successfully.  App cannot make assumptions about where the floor plane is.
}
  • Se SetTrackingSpaceType restituisce true, Unity ha cambiato correttamente il sistema di coordinate del mondo per tenere traccia del frame di fase di riferimento.
  • Se SetTrackingSpaceType restituisce false, Unity non è stato in grado di passare al frame di fase di riferimento, probabilmente perché l'utente non ha configurato un piano nel proprio ambiente. Anche se un valore restituito falso non è comune, può verificarsi se la fase è configurata in una stanza diversa e il dispositivo viene spostato nella stanza corrente senza che l'utente imposti una nuova fase.

Dopo che l'app ha impostato correttamente il tipo di spazio di rilevamento RoomScale, il contenuto posizionato sul piano y=0 verrà visualizzato sul pavimento. L'origine a 0, 0, 0 sarà la posizione specifica sul pavimento in cui si trovava l'utente durante l'installazione della stanza, con -Z che rappresenta la direzione in avanti che stavano affrontando durante l'installazione.

Spazio dei nomi:UnityEngine.Experimental.XR
Tipo:Limite

Nel codice dello script è quindi possibile chiamare il metodo TryGetGeometry sul tipo UnityEngine.Experimental.XR.Boundary per ottenere un poligono limite, specificando un tipo di limite TrackedArea. Se l'utente ha definito un limite (si recupera un elenco di vertici), è sicuro offrire all'utente un'esperienza su scala locale , in cui può spostarsi nella scena creata.

Nota

Il sistema eseguirà automaticamente il rendering del limite quando l'utente si avvicina. L'app non deve usare questo poligono per eseguire il rendering del limite stesso. Tuttavia, è possibile scegliere di disporre gli oggetti della scena usando questo poligono limite, per garantire che l'utente possa raggiungere fisicamente tali oggetti senza teletrasporto:

var vertices = new List<Vector3>();
if (UnityEngine.Experimental.XR.Boundary.TryGetGeometry(vertices, Boundary.Type.TrackedArea))
{
    // Lay out your app's content within the boundary polygon, to ensure that users can reach it without teleporting.
}

Creazione di un'esperienza su scala mondiale

Spazio dei nomi:UnityEngine.XR.WSA
Type:WorldAnchor

Per esperienze reali su scala mondiale in HoloLens che consentono agli utenti di andare oltre i 5 metri, sono necessarie nuove tecniche oltre quelle usate per le esperienze su scala locale. Una tecnica chiave che si userà consiste nel creare un ancoraggio spaziale per bloccare un cluster di ologrammi esattamente sul posto nel mondo fisico, indipendentemente dalla distanza in cui l'utente ha effettuato il roaming e quindi trovare nuovamente gli ologrammi nelle sessioni successive.

In Unity si crea un ancoraggio spaziale aggiungendo il componente WorldAnchor Unity a un GameObject.

Aggiunta di un ancoraggio globale

Per aggiungere un ancoraggio globale, chiama AddComponent<WorldAnchor>() sull'oggetto gioco con la trasformazione che vuoi ancorare nel mondo reale.

WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();

È tutto. Questo oggetto gioco sarà ora ancorato alla posizione corrente nel mondo fisico. È possibile che le coordinate del mondo Unity si adattino leggermente nel tempo per garantire l'allineamento fisico. Usare la persistenza per trovare di nuovo questa posizione ancorata in una sessione futura dell'app.

Rimozione di un ancoraggio globale

Se non vuoi più che GameObject sia bloccato in una posizione fisica del mondo e non intendi spostarlo in questo fotogramma, puoi semplicemente chiamare Destroy nel componente World Anchor.

Destroy(gameObject.GetComponent<WorldAnchor>());

Se vuoi spostare il GameObject in questo fotogramma, devi chiamare DestroyImmediate.

DestroyImmediate(gameObject.GetComponent<WorldAnchor>());

Spostamento di un gameobject ancorato a un mondo

Non è possibile spostare l'oggetto GameObject mentre è presente un ancoraggio mondiale. Se è necessario spostare il gameobject in questo frame, è necessario:

  1. DestroyImmediate il componente World Anchor
  2. Spostare l'oggetto GameObject
  3. Aggiungere un nuovo componente World Anchor a GameObject.
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
gameObject.transform.position = new Vector3(0, 0, 2);
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();

Gestione delle modifiche di individuabilità

Un WorldAnchor potrebbe non essere individuabile nel mondo fisico in un momento specifico. In questo caso, Unity non aggiornerà la trasformazione dell'oggetto ancorato. Questa operazione può anche cambiare durante l'esecuzione di un'app. Se non si gestisce la modifica della individuabilità, l'oggetto non verrà visualizzato nella posizione fisica corretta nel mondo.

Per ricevere una notifica sulle modifiche di individuabilità:

  1. Sottoscrivere l'evento OnTrackingChanged
  2. Gestire l'evento

L'evento OnTrackingChanged verrà chiamato ogni volta che l'ancoraggio spaziale sottostante cambia tra uno stato di locatable e non locatable.

anchor.OnTrackingChanged += Anchor_OnTrackingChanged;

Gestire quindi l'evento:

private void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
{
    // This simply activates/deactivates this object and all children when tracking changes
    self.gameObject.SetActiveRecursively(located);
}

A volte gli ancoraggi si trovano immediatamente. In questo caso, questa proprietà isLocated dell'ancoraggio verrà impostata su true quando viene restituito AddComponent<WorldAnchor>(). Di conseguenza, l'evento OnTrackingChanged non verrà attivato. Un modello pulito consiste nel chiamare il gestore OnTrackingChanged con lo stato IsLocated iniziale dopo aver collegato un ancoraggio.

Anchor_OnTrackingChanged(anchor, anchor.isLocated);

Checkpoint di sviluppo successivo

Se si segue il percorso di checkpoint di sviluppo di Unity che è stato definito, si sta esplorando i Realtà mista blocchi predefiniti principali. Da qui è possibile continuare con il blocco predefinito successivo:

In alternativa, passare a Realtà mista funzionalità e API della piattaforma:

È sempre possibile tornare ai checkpoint di sviluppo di Unity in qualsiasi momento.

Vedere anche