Skapa och hitta fästpunkter med hjälp av Azure Spatial Anchors i Unity

Med Azure Spatial Anchors kan du dela fästpunkter i världen mellan olika enheter. Den stöder flera olika utvecklingsmiljöer. I den här artikeln går vi in på hur du använder Azure Spatial Anchors SDK i Unity för att:

  • Konfigurera och hantera en Azure Spatial Anchors-session korrekt.
  • Skapa och ange egenskaper för lokala fästpunkter.
  • Ladda upp dem till molnet.
  • Leta upp och ta bort molnbaserade fästpunkter.

Förutsättningar

För att slutföra den här guiden kontrollerar du att du har:

  • Läs igenom översikten över Azure Spatial Anchors.
  • En av snabbstarterna på 5 minuter har slutförts.
  • Grundläggande kunskaper om C# och Unity.
  • Grundläggande kunskaper om ARCore om du vill använda Android eller ARKit om du vill använda iOS.

Cross Platform

Initiera sessionen

Huvudinmatningspunkten för SDK:t är klassen som representerar din session. Vanligtvis deklarerar du ett fält i klassen som hanterar din vy och den interna AR-sessionen.

Läs mer om klassen CloudSpatialAnchorSession .

    CloudSpatialAnchorSession cloudSession;
    // In your view handler
    this.cloudSession = new CloudSpatialAnchorSession();

Konfigurera autentisering

För att få åtkomst till tjänsten måste du ange en kontonyckel, åtkomsttoken eller Microsoft Entra-autentiseringstoken. Du kan också läsa mer om detta på sidan Autentiseringskoncept.

Kontonycklar

Kontonycklar är en autentiseringsuppgift som gör att ditt program kan autentisera med Azure Spatial Anchors-tjänsten. Syftet med kontonycklar är att hjälpa dig att komma igång snabbt. Särskilt under utvecklingsfasen av programmets integrering med Azure Spatial Anchors. Därför kan du använda kontonycklar genom att bädda in dem i dina klientprogram under utvecklingen. När du går vidare efter utvecklingen rekommenderar vi starkt att du går över till en autentiseringsmekanism som är på produktionsnivå, som stöds av åtkomsttoken eller Microsoft Entra-användarautentisering. Om du vill hämta en kontonyckel för utveckling går du till ditt Azure Spatial Anchors-konto och går till fliken Nycklar.

Läs mer om klassen SessionConfiguration .

    this.cloudSession.Configuration.AccountKey = @"MyAccountKey";

Åtkomsttoken

Åtkomsttoken är en mer robust metod för att autentisera med Azure Spatial Anchors. Särskilt när du förbereder programmet för en produktionsdistribution. Sammanfattningen av den här metoden är att konfigurera en serverdelstjänst som klientprogrammet kan autentisera säkert med. Dina serverdelstjänstgränssnitt med AAD vid körning och med Azure Spatial Anchors Secure Token Service för att begära en åtkomsttoken. Den här token levereras sedan till klientprogrammet och används i SDK för att autentisera med Azure Spatial Anchors.

    this.cloudSession.Configuration.AccessToken = @"MyAccessToken";

Om en åtkomsttoken inte har angetts måste du hantera TokenRequired händelsen eller implementera tokenRequired metoden i ombudsprotokollet.

Du kan hantera händelsen synkront genom att ange egenskapen på händelseargumenten.

Läs mer om ombudet TokenRequiredDelegate .

    this.cloudSession.TokenRequired += (object sender, TokenRequiredEventArgs args) =>
    {
        args.AccessToken = @"MyAccessToken";
    };

Om du behöver köra asynkront arbete i hanteraren kan du skjuta upp inställningen av token genom att begära ett deferral objekt och sedan slutföra det, som i följande exempel.

    this.cloudSession.TokenRequired += async (object sender, TokenRequiredEventArgs args) =>
    {
        var deferral = args.GetDeferral();
        string myToken = await MyGetTokenAsync();
        if (myToken != null) args.AccessToken = myToken;
        deferral.Complete();
    };

Microsoft Entra-autentisering

Azure Spatial Anchors gör det också möjligt för program att autentisera med användartoken för Microsoft Entra-ID (Active Directory). Du kan till exempel använda Microsoft Entra-token för att integrera med Azure Spatial Anchors. Om ett företag underhåller användare i Microsoft Entra-ID kan du ange en Microsoft Entra-token för användare i Azure Spatial Anchors SDK. På så sätt kan du autentisera direkt till Azure Spatial Anchors-tjänsten för ett konto som ingår i samma Microsoft Entra-klientorganisation.

    this.cloudSession.Configuration.AuthenticationToken = @"MyAuthenticationToken";

Precis som med åtkomsttoken måste du hantera tokenRequired-händelsen om en Microsoft Entra-token inte har angetts eller implementera metoden tokenRequired i ombudsprotokollet.

Du kan hantera händelsen synkront genom att ange egenskapen på händelseargumenten.

    this.cloudSession.TokenRequired += (object sender, TokenRequiredEventArgs args) =>
    {
        args.AuthenticationToken = @"MyAuthenticationToken";
    };

Om du behöver köra asynkront arbete i hanteraren kan du skjuta upp inställningen av token genom att begära ett deferral objekt och sedan slutföra det, som i följande exempel.

    this.cloudSession.TokenRequired += async (object sender, TokenRequiredEventArgs args) =>
    {
        var deferral = args.GetDeferral();
        string myToken = await MyGetTokenAsync();
        if (myToken != null) args.AuthenticationToken = myToken;
        deferral.Complete();
    };

Konfigurera sessionen

Anropa Start() för att aktivera sessionen för att bearbeta miljödata.

Om du vill hantera händelser som genererats av sessionen bifogar du en händelsehanterare.

Läs mer om Start-metoden .

#if UNITY_ANDROID || UNITY_IOS
    this.cloudSession.Session = aRSession.subsystem.nativePtr.GetPlatformPointer();
#elif UNITY_WSA || WINDOWS_UWP
    // No need to set a native session pointer for HoloLens.
#else
    throw new NotSupportedException("The platform is not supported.");
#endif

    this.cloudSession.Start();

Ange ramar till sessionen

Den rumsliga fästpunktssessionen fungerar genom att mappa utrymmet runt användaren. Det hjälper dig att avgöra var fästpunkter finns. Mobila plattformar (iOS och Android) kräver ett internt anrop till kameraflödet för att hämta ramar från plattformens AR-bibliotek. HoloLens genomsöker däremot hela tiden miljön, så det finns inget behov av ett specifikt samtal som på mobila plattformar.

Läs mer om Metoden ProcessFrame .

#if UNITY_ANDROID || UNITY_IOS
    XRCameraFrame xRCameraFrame;
    if (aRCameraManager.subsystem.TryGetLatestFrame(cameraParams, out xRCameraFrame))
    {
        long latestFrameTimeStamp = xRCameraFrame.timestampNs;

        bool newFrameToProcess = latestFrameTimeStamp > lastFrameProcessedTimeStamp;

        if (newFrameToProcess)
        {
            session.ProcessFrame(xRCameraFrame.nativePtr.GetPlatformPointer());
            lastFrameProcessedTimeStamp = latestFrameTimeStamp;
        }
    }
#endif

Ge feedback till användaren

Du kan skriva kod för att hantera sessionens uppdaterade händelse. Den här händelsen utlöses varje gång sessionen förbättrar sin förståelse för din omgivning. Om du gör det kan du:

  • UserFeedback Använd klassen för att ge feedback till användaren när enheten flyttas och sessionen uppdaterar sin miljötolkning. Gör
  • Fastställ vid vilken tidpunkt det finns tillräckligt med spårade rumsliga data för att skapa spatiala fästpunkter. Du avgör detta med antingen ReadyForCreateProgress eller RecommendedForCreateProgress. När ReadyForCreateProgress är över 1 har vi tillräckligt med data för att spara ett moln spatialt fästpunkt, men vi rekommenderar att du väntar tills RecommendedForCreateProgress är över 1 för att göra det.

Läs mer om ombudet SessionUpdatedDelegate .

    this.cloudSession.SessionUpdated += (object sender, SessionUpdatedEventArgs args) =>
    {
        var status = args.Status;
        if (status.UserFeedback == SessionUserFeedback.None) return;
        this.feedback = $"Feedback: {Enum.GetName(typeof(SessionUserFeedback), status.UserFeedback)} -" +
            $" Recommend Create={status.RecommendedForCreateProgress: 0.#%}";
    };

Skapa ett rumsligt molnfästpunkt

Om du vill skapa ett rumsligt molnankare skapar du först en fästpunkt i plattformens AR-system och skapar sedan en molnmotsvarighet. Du använder CreateAnchorAsync() metoden .

Läs mer om klassen CloudSpatialAnchor .

    // Create a local anchor, perhaps by hit-testing and spawning an object within the scene
    Vector3 hitPosition = new Vector3();
#if UNITY_ANDROID || UNITY_IOS
    Vector2 screenCenter = new Vector2(0.5f, 0.5f);
    List<ARRaycastHit> aRRaycastHits = new List<ARRaycastHit>();
    if(arRaycastManager.Raycast(screenCenter, aRRaycastHits) && aRRaycastHits.Count > 0)
    {
        ARRaycastHit hit = aRRaycastHits[0];
        hitPosition = hit.pose.position;
    }
#elif WINDOWS_UWP || UNITY_WSA
    RaycastHit hit;
    if (this.TryGazeHitTest(out hit))
    {
        hitPosition = hit.point;
    }
#endif

    Quaternion rotation = Quaternion.AngleAxis(0, Vector3.up);
    this.localAnchor = GameObject.Instantiate(/* some prefab */, hitPosition, rotation);
    this.localAnchor.AddComponent<CloudNativeAnchor>();

    // If the user is placing some application content in their environment,
    // you might show content at this anchor for a while, then save when
    // the user confirms placement.
    CloudNativeAnchor cloudNativeAnchor = this.localAnchor.GetComponent<CloudNativeAnchor>();
    if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); }  
    CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor;
    await this.cloudSession.CreateAnchorAsync(cloudAnchor);
    this.feedback = $"Created a cloud anchor with ID={cloudAnchor.Identifier}");

Som vi beskrev tidigare behöver du tillräckligt med miljödata som samlas in innan du försöker skapa ett nytt rumsligt molnankare. Det innebär ReadyForCreateProgress att måste vara över 1, men vi rekommenderar att du väntar tills RecommendedForCreateProgress är över 1 för att göra det.

Läs mer om metoden GetSessionStatusAsync .

    SessionStatus value = await this.cloudSession.GetSessionStatusAsync();
    if (value.RecommendedForCreateProgress < 1.0f) return;
    // Issue the creation request ...

Ange egenskaper

Du kan välja att lägga till vissa egenskaper när du sparar dina molnbaserade fästpunkter. Som vilken typ av objekt som sparas eller grundläggande egenskaper som om det ska aktiveras för interaktion. Det kan vara användbart vid identifiering: du kan omedelbart återge objektet för användaren, till exempel en bildram med tomt innehåll. Sedan får en annan nedladdning i bakgrunden ytterligare tillståndsinformation, till exempel den bild som ska visas i ramen.

Läs mer om egenskapen AppProperties .

    CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor() { LocalAnchor = localAnchor };
    cloudAnchor.AppProperties[@"model-type"] = @"frame";
    cloudAnchor.AppProperties[@"label"] = @"my latest picture";
    await this.cloudSession.CreateAnchorAsync(cloudAnchor);

Uppdatera egenskaper

Om du vill uppdatera egenskaperna för en fästpunkt använder UpdateAnchorProperties() du metoden. Om två eller flera enheter försöker uppdatera egenskaper för samma fästpunkt samtidigt använder vi en optimistisk samtidighetsmodell. Vilket innebär att den första skrivningen kommer att vinna. Alla andra skrivningar får felet "Samtidighet": en uppdatering av egenskaperna skulle behövas innan du försöker igen.

Läs mer om metoden UpdateAnchorPropertiesAsync .

    CloudSpatialAnchor anchor = /* locate your anchor */;
    anchor.AppProperties[@"last-user-access"] = @"just now";
    await this.cloudSession.UpdateAnchorPropertiesAsync(anchor);

Du kan inte uppdatera platsen för en fästpunkt när den har skapats i tjänsten – du måste skapa ett nytt fästpunkt och ta bort den gamla för att spåra en ny position.

Om du inte behöver hitta ett fästpunkt för att uppdatera dess egenskaper kan du använda GetAnchorPropertiesAsync() metoden som returnerar ett CloudSpatialAnchor objekt med egenskaper.

Läs mer om metoden GetAnchorPropertiesAsync .

    var anchor = await cloudSession.GetAnchorPropertiesAsync(@"anchorId");
    if (anchor != null)
    {
        anchor.AppProperties[@"last-user-access"] = @"just now";
        await this.cloudSession.UpdateAnchorPropertiesAsync(anchor);
    }

Ange förfallotid

Det går också att konfigurera fästpunkten så att den upphör att gälla automatiskt vid ett visst datum i framtiden. När en fästpunkt upphör att gälla kommer den inte längre att finnas eller uppdateras. Förfallodatum kan bara anges när fästpunkten skapas innan den sparas i molnet. Det går inte att uppdatera förfallodatum efteråt. Om ingen förfallotid anges när fästpunkten skapas upphör fästpunkten endast att gälla när den tas bort manuellt.

Läs mer om egenskapen Expiration .

    cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(7);

Leta upp ett rumsligt molnfästpunkt

Att kunna hitta en tidigare sparad molnlokal fästpunkt är en av de främsta orsakerna till att använda Azure Spatial Anchors. För detta använder vi "Watchers". Du kan bara använda en Watcher i taget. flera bevakare stöds inte. Det finns flera olika sätt (kallas även Anchor Locate Strategies) en Watcher kan hitta en moln spatial fästpunkt. Du kan använda en strategi för en bevakare i taget.

  • Leta upp fästpunkter efter identifierare.
  • Leta upp fästpunkter som är anslutna till en tidigare fästpunkt. Du kan lära dig mer om ankarrelationer här.
  • Leta upp fästpunkt med hjälp av omlokalisering av grova objekt.

Kommentar

Varje gång du hittar en fästpunkt försöker Azure Spatial Anchors använda de miljödata som samlas in för att utöka den visuella informationen i fästpunkten. Om du har problem med att hitta ett fästpunkt kan det vara användbart att skapa ett fästpunkt och sedan hitta det flera gånger från olika vinklar och ljusförhållanden.

Om du letar upp molnbaserade fästpunkter efter identifierare kan du lagra molnbaserad fästpunktsidentifierare i programmets serverdelstjänst och göra den tillgänglig för alla enheter som kan autentisera den korrekt. Ett exempel på detta finns i Självstudie: Dela spatiala fästpunkter mellan enheter.

Instansiera ett AnchorLocateCriteria objekt, ange de identifierare som du letar efter och anropa CreateWatcher metoden i sessionen genom att ange din AnchorLocateCriteria.

Läs mer om metoden CreateWatcher .

    AnchorLocateCriteria criteria = new AnchorLocateCriteria();
    criteria.Identifiers = new string[] { @"id1", @"id2", @"id3" };
    this.cloudSession.CreateWatcher(criteria);

När din bevakare har skapats utlöses AnchorLocated händelsen för varje ankarpunkt som begärs. Den här händelsen utlöses när en fästpunkt finns eller om fästpunkten inte kan placeras. Om den här situationen inträffar anges orsaken i statusen. När alla fästpunkter för en bevakare har bearbetats, hittats eller inte hittats utlöses LocateAnchorsCompleted händelsen. Det finns en gräns på 35 identifierare per bevakare.

Läs mer om ombudet AnchorLocatedDelegate .

    this.cloudSession.AnchorLocated += (object sender, AnchorLocatedEventArgs args) =>
    {
        switch (args.Status)
        {
            case LocateAnchorStatus.Located:
                CloudSpatialAnchor foundAnchor = args.Anchor;
                // Go add your anchor to the scene...
                break;
            case LocateAnchorStatus.AlreadyTracked:
                // This anchor has already been reported and is being tracked
                break;
            case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
                // The anchor was deleted or never existed in the first place
                // Drop it, or show UI to ask user to anchor the content anew
                break;
            case LocateAnchorStatus.NotLocated:
                // The anchor hasn't been found given the location data
                // The user might in the wrong location, or maybe more data will help
                // Show UI to tell user to keep looking around
                break;
        }
    }

Ta bort fästpunkter

Att ta bort fästpunkter när de inte längre används är en bra idé att ta med tidigt i utvecklingsprocessen och metoderna för att hålla dina Azure-resurser rensade.

Läs mer om metoden DeleteAnchorAsync .

    await this.cloudSession.DeleteAnchorAsync(cloudAnchor);
    // Perform any processing you may want when delete finishes

Ta bort fästpunkt utan att hitta

Om du inte kan hitta en fästpunkt men ändå vill ta bort den kan du använda API:et GetAnchorPropertiesAsync som tar ett anchorId som indata för att hämta CloudSpatialAnchor objektet. Du kan sedan skicka det här objektet till DeleteAnchorAsync för att ta bort det.

var anchor = await cloudSession.GetAnchorPropertiesAsync(@"anchorId");
await this.cloudSession.DeleteAnchorAsync(anchor);

Pausa, återställa eller stoppa sessionen

Om du vill stoppa sessionen tillfälligt kan du anropa Stop(). Om du gör det stoppas alla bevakare och miljöbearbetning, även om du anropar ProcessFrame(). Du kan sedan anropa Start() för att återuppta bearbetningen. När du återupptar underhålls miljödata som redan har samlats in i sessionen.

Läs mer om stop-metoden .

    this.cloudSession.Stop();

Om du vill återställa miljödata som har samlats in i sessionen kan du anropa Reset().

Läs mer om metoden Återställ .

    this.cloudSession.Reset();

Om du vill rensa korrekt efter en session anropar Dispose()du .

Läs mer om metoden Förfoga bort .

    this.cloudSession.Dispose();

Nästa steg

I den här guiden har du lärt dig hur du skapar och hittar fästpunkter med hjälp av Azure Spatial Anchors SDK. Om du vill veta mer om ankarrelationer fortsätter du till nästa guide.