Självstudie: Gränssnitt och anpassade modeller

I den här guiden får du lära dig att:

  • Lägg till Mixed Reality Toolkit i projektet
  • Hantera modelltillstånd
  • Konfigurera Azure Blob Storage för modellinmatning
  • Ladda upp och bearbeta modeller för återgivning

Förutsättningar

Kom igång med Mixed Reality Toolkit (MRTK)

MIXED REALITY Toolkit (MRTK) är ett plattformsoberoende verktyg för att skapa upplevelser med mixad verklighet. Vi använder MRTK 2.8.3 för dess interaktions- och visualiseringsfunktioner.

Den officiella guiden för att importera MRTK innehåller några steg som vi inte behöver göra. Endast dessa tre steg är nödvändiga:

  • Importera Mixed Reality Toolkit/Mixed Reality Toolkit Foundation version 2.8.3 till projektet via Mixed Reality Feature Tool (Importera MRTK).
  • Kör konfigurationsguiden för MRTK (Konfigurera MRTK).
  • Lägg till MRTK i den aktuella scenen (Lägg till i scenen). Använd ARRMixedRealityToolkitConfigurationProfile här i stället för den föreslagna profilen i självstudien.

Importera tillgångar som används av den här självstudien

Från och med det här kapitlet implementerar vi ett grundläggande modell-view-controller-mönster för mycket av det material som omfattas. Modelldelen av mönstret är Azure Remote Rendering specifik kod och tillståndshantering relaterad till Azure Remote Rendering. Vyn och kontrollantdelarna i mönstret implementeras med hjälp av MRTK-tillgångar och vissa anpassade skript. Det går att använda modellen i den här självstudien utan att view-controller implementeras här. Med den här separationen kan du enkelt integrera koden som finns i den här självstudien i ditt eget program där den tar över view-controller-delen av designmönstret.

Med introduktionen av MRTK finns det flera skript, prefabs och tillgångar som nu kan läggas till i projektet för att stödja interaktioner och visuell feedback. Dessa tillgångar kallas självstudietillgångar och paketeras i ett Unity-tillgångspaket som ingår i Azure Remote Rendering GitHub i \Unity\TutorialAssets\TutorialAssets.unitypackage.

  1. Klona eller ladda ned Git-lagringsplatsen Azure Remote Rendering om du laddar ned extrahera zip-filen till en känd plats.
  2. I Unity-projektet väljer du Tillgångar –> Importpaket –> Anpassat paket.
  3. Gå till katalogen där du klonade eller packa upp Azure Remote Rendering-lagringsplatsen i utforskaren och välj sedan den .unitypackage som finns i Unity –> TutorialAssets –> TutorialAssets.unitypackage
  4. Välj knappen Importera för att importera paketets innehåll till projektet.
  5. I Unity-redigeraren väljer du Mixed Reality Toolkit –> Verktyg –> Uppgradera MRTK Standard Shader för Lightweight Render Pipeline från det översta menyfältet och följer anvisningarna för att uppgradera skuggningen.

När MRTK och självstudietillgångarna har konfigurerats dubbelkollas att rätt profil har valts.

  1. Välj MixedRealityToolkit GameObject i scenhierarkin.
  2. Under komponenten MixedRealityToolkit i Inspector växlar du konfigurationsprofilen till ARRMixedRealityToolkitConfigurationProfile.
  3. Spara ändringarna genom att trycka på Ctrl+S .

Det här steget konfigurerar FRÄMST MRTK med standardprofilerna HoloLens 2. De angivna profilerna är förkonfigurerade på följande sätt:

  • Stäng av profileraren (Tryck på 9 om du vill aktivera/inaktivera den eller säg "Visa/dölj profilerare" på enheten).
  • Stäng av ögonögamarkören.
  • Aktivera Unity-musklick så att du kan klicka på MRTK-gränssnittselement med musen i stället för den simulerade handen.

Lägg till appmenyn

De flesta vykontrollanter i den här självstudien arbetar mot abstrakta basklasser i stället för mot betongklasser. Det här mönstret ger mer flexibilitet och gör att vi kan tillhandahålla visningskontrollanterna åt dig, samtidigt som du får lära dig azure-Remote Rendering-koden. För enkelhetens skull har klassen RemoteRenderingCoordinator ingen abstrakt klass och dess vystyrenhet fungerar direkt mot betongklassen.

Nu kan du lägga till prefab AppMenu i scenen för visuell feedback om det aktuella sessionstillståndet. AppMenu visar även den modalpanel som användaren använder för att auktorisera programmet att ansluta till ARR.

  1. Leta upp AppMenu-prefab i Assets/RemoteRenderingTutorial/Prefabs/AppMenu

  2. Dra AppMenu-prefab till scenen.

  3. Om du ser en dialogruta för TMP Importer följer du anvisningarna för att importera TMP Essentials. Stäng sedan dialogrutan Importer eftersom exemplen och extrafunktionerna inte behövs.

  4. AppMenu har konfigurerats för att automatiskt ansluta och tillhandahålla modal för att samtycka till att ansluta till en session, så att vi kan ta bort förbikopplingen som placerades tidigare. På RemoteRenderingCoordinator GameObject tar du bort förbikopplingen för auktorisering som vi implementerade tidigare genom att trycka på knappen "-" på händelsen Vid begäran om auktorisering .

    Ta bort förbikoppling.

  5. Testa visningskontrollanten genom att trycka på Spela upp i Unity-redigeraren.

  6. I redigeraren, nu när MRTK har konfigurerats, kan du använda WASD-tangenterna för att ändra positionen för vyn och hålla höger musknapp + flytta musen för att ändra visningsriktningen. Prova att "köra" runt scenen lite för att få en känsla för kontrollerna.

  7. På enheten kan du höja upp handflatan för att anropa AppMenu, i Unity-redigeraren, använda snabbtangenten "M".

  8. Om du har tappat bort menyn trycker du på M-tangenten för att kalla på menyn. Menyn placeras nära kameran för enkel interaktion.

  9. AppMenu presenterar ett gränssnittselement för auktorisering till höger om AppMenu. Från och med nu bör du använda det här användargränssnittselementet för att auktorisera appen för att hantera fjärråtergivningssessioner.

    Auktorisera användargränssnitt

  10. Stoppa Unity från att spela för att fortsätta med självstudien.

Hantera modelltillstånd

Vi behöver ett nytt skript med namnet RemoteRenderedModel som är till för spårningstillstånd, som svarar på händelser, utlöse händelser och konfiguration. RemoteRenderedModel lagrar i princip fjärrsökvägen för modelldata i modelPath. Den lyssnar efter tillståndsändringar i RemoteRenderingCoordinator för att se om den automatiskt ska läsa in eller ta bort den modell som den definierar. Den GameObject som har RemoteRenderedModel kopplad till är den lokala överordnade filen för fjärrinnehållet.

Observera att Skriptet RemoteRenderedModel implementerar BaseRemoteRenderedModel, som ingår i Självstudietillgångar. Den här anslutningen gör att fjärrmodellens vystyrenhet kan bindas till skriptet.

  1. Skapa ett nytt skript med namnet RemoteRenderedModel i samma mapp som RemoteRenderingCoordinator. Ersätt hela innehållet med följande kod:

    // Copyright (c) Microsoft Corporation. All rights reserved.
    // Licensed under the MIT License. See LICENSE in the project root for license information.
    
    using Microsoft.Azure.RemoteRendering;
    using Microsoft.Azure.RemoteRendering.Unity;
    using System;
    using UnityEngine;
    using UnityEngine.Events;
    
    public class RemoteRenderedModel : BaseRemoteRenderedModel
    {
        public bool AutomaticallyLoad = true;
    
        private ModelState currentModelState = ModelState.NotReady;
    
        [SerializeField]
        [Tooltip("The friendly name for this model")]
        private string modelDisplayName;
        public override string ModelDisplayName { get => modelDisplayName; set => modelDisplayName = value; }
    
        [SerializeField]
        [Tooltip("The URI for this model")]
        private string modelPath;
        public override string ModelPath
        {
            get => modelPath.Trim();
            set => modelPath = value;
        }
    
        public override ModelState CurrentModelState
        {
            get => currentModelState;
            protected set
            {
                if (currentModelState != value)
                {
                    currentModelState = value;
                    ModelStateChange?.Invoke(value);
                }
            }
        }
    
        public override event Action<ModelState> ModelStateChange;
        public override event Action<float> LoadProgress;
        public override Entity ModelEntity { get; protected set; }
    
        public UnityEvent OnModelNotReady = new UnityEvent();
        public UnityEvent OnModelReady = new UnityEvent();
        public UnityEvent OnStartLoading = new UnityEvent();
        public UnityEvent OnModelLoaded = new UnityEvent();
        public UnityEvent OnModelUnloading = new UnityEvent();
    
        public UnityFloatEvent OnLoadProgress = new UnityFloatEvent();
    
        public void Awake()
        {
            // Hook up the event to the Unity event
            LoadProgress += (progress) => OnLoadProgress?.Invoke(progress);
    
            ModelStateChange += HandleUnityStateEvents;
        }
    
        private void HandleUnityStateEvents(ModelState modelState)
        {
            switch (modelState)
            {
                case ModelState.NotReady:  OnModelNotReady?.Invoke();  break;
                case ModelState.Ready:     OnModelReady?.Invoke();     break;
                case ModelState.Loading:   OnStartLoading?.Invoke();   break;
                case ModelState.Loaded:    OnModelLoaded?.Invoke();    break;
                case ModelState.Unloading: OnModelUnloading?.Invoke(); break;
            }
        }
    
        private void Start()
        {
            //Attach to and initialize current state (in case we're attaching late)
            RemoteRenderingCoordinator.CoordinatorStateChange += Instance_CoordinatorStateChange;
            Instance_CoordinatorStateChange(RemoteRenderingCoordinator.instance.CurrentCoordinatorState);
        }
    
        /// <summary>
        /// Listen for state changes on the coordinator, clean up this model's remote objects if we're no longer connected.
        /// Automatically load if required
        /// </summary>
        private void Instance_CoordinatorStateChange(RemoteRenderingCoordinator.RemoteRenderingState state)
        {
            switch (state)
            {
                case RemoteRenderingCoordinator.RemoteRenderingState.RuntimeConnected:
                    CurrentModelState = ModelState.Ready;
                    if (AutomaticallyLoad)
                        LoadModel();
                    break;
                default:
                    UnloadModel();
                    break;
            }
        }
    
        private void OnDestroy()
        {
            RemoteRenderingCoordinator.CoordinatorStateChange -= Instance_CoordinatorStateChange;
            UnloadModel();
        }
    
        /// <summary>
        /// Asks the coordinator to create a model entity and listens for coordinator state changes
        /// </summary>
        [ContextMenu("Load Model")]
        public override async void LoadModel()
        {
            if (CurrentModelState != ModelState.Ready)
                return; //We're already loaded, currently loading, or not ready to load
    
            CurrentModelState = ModelState.Loading;
    
            ModelEntity = await RemoteRenderingCoordinator.instance?.LoadModel(ModelPath, this.transform, SetLoadingProgress);
    
            if (ModelEntity != null)
                CurrentModelState = ModelState.Loaded;
            else
                CurrentModelState = ModelState.Error;
        }
    
        /// <summary>
        /// Clean up the local model instances
        /// </summary>
        [ContextMenu("Unload Model")]
        public override void UnloadModel()
        {
            CurrentModelState = ModelState.Unloading;
    
            if (ModelEntity != null)
            {
                var modelGameObject = ModelEntity.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
                Destroy(modelGameObject);
                ModelEntity.Destroy();
                ModelEntity = null;
            }
    
            if (RemoteRenderingCoordinator.instance.CurrentCoordinatorState == RemoteRenderingCoordinator.RemoteRenderingState.RuntimeConnected)
                CurrentModelState = ModelState.Ready;
            else
                CurrentModelState = ModelState.NotReady;
        }
    
        /// <summary>
        /// Update the Unity progress event
        /// </summary>
        /// <param name="progressValue"></param>
        public override void SetLoadingProgress(float progressValue)
        {
            LoadProgress?.Invoke(progressValue);
        }
    }
    

I de mest grundläggande termerna innehåller RemoteRenderedModel de data som behövs för att läsa in en modell (i det här fallet SAS eller builtin:// URI) och spårar fjärrmodelltillståndet. När det är dags att läsa in modellen LoadModel anropas metoden på RemoteRenderingCoordinator och entiteten som innehåller modellen returneras för referens och avlastning.

Läs in testmodellen

Nu ska vi testa det nya skriptet genom att läsa in testmodellen igen. För det här testet behöver vi ett spelobjekt för att innehålla skriptet och vara överordnat till testmodellen, och vi behöver också en virtuell fas som innehåller modellen. Fasen förblir fast i förhållande till den verkliga världen med hjälp av en WorldAnchor. Vi använder ett fast steg så att själva modellen fortfarande kan flyttas runt senare.

  1. Skapa ett nytt tomt spelobjekt i scenen och ge det namnet ModelStage.

  2. Lägga till en World Anchor-komponent i ModelStage

    Lägg till WorldAnchor-komponent

  3. Skapa ett nytt tomt spelobjekt som underordnat ModelStage och ge det namnet TestModel.

  4. Lägg till RemoteRenderedModel-skriptet i TestModel.

    Lägg till RemoteRenderedModel-komponent

  5. Fyll i Model Display Name och Model Path med "TestModel" respektive "builtin://Engine".

    Ange modellinformation

  6. Placera TestModel-objektet framför kameran, vid position x = 0, y = 0, z = 3.

    Placera objekt

  7. Kontrollera att AutomaticallyLoad är aktiverat.

  8. Testa programmet genom att trycka på Spela upp i Unity-redigeraren.

  9. Bevilja auktorisering genom att klicka på knappen Anslut så att appen kan skapa en session, ansluta till den och automatiskt läsa in modellen.

Titta på konsolen när programmet fortskrider genom dess tillstånd. Tänk på att vissa tillstånd kan ta lite tid att slutföra och det kanske inte finns några förloppsuppdateringar på ett tag. Så småningom ser du loggar från modellinläsningen och sedan kort efter den renderade testmodellen i scenen.

Prova att flytta och rotera TestModel GameObject via transformeringen i inspektören eller i scenvyn och observera omvandlingarna i spelvyn.

Unity-logg

Etablera Blob Storage i Azure och anpassad modellinmatning

Nu kan vi prova att läsa in din egen modell. För att göra det måste du konfigurera Blob Storage på Azure, ladda upp och konvertera en modell och sedan läsa in modellen med hjälp av RemoteRenderedModel-skriptet . Inläsningsstegen för den anpassade modellen kan hoppas över på ett säkert sätt om du inte har en egen modell att läsa in just nu.

Följ stegen som anges i snabbstarten: Konvertera en modell för återgivning. Hoppa över avsnittet Infoga ny modell i snabbstartsexempelapp för den här självstudien. När du har matat in modellens SAS-URI (Shared Access Signature) fortsätter du.

Läsa in och återge en anpassad modell

  1. Skapa en ny tom GameObject i scenen och ge den ett namn som liknar din anpassade modell.

  2. Lägg till RemoteRenderedModel-skriptet i det nyligen skapade GameObject.

    Lägg till RemoteRenderedModel-komponent

  3. Fyll i Model Display Name med ett lämpligt namn för din modell.

  4. Fyll i Model Path med modellens SAS-URI (Signatur för delad åtkomst) som du skapade i steget Etablera Blob Storage i Azure och anpassad modellinmatning .

  5. Placera GameObject framför kameran, vid position x = 0, y = 0, z = 3.

  6. Kontrollera att AutomaticallyLoad är aktiverat.

  7. Testa programmet genom att trycka på Spela upp i Unity-redigeraren.

    Konsolen visar det aktuella sessionstillståndet och även modellen som läser in förloppsmeddelanden när sessionen är ansluten.

  8. Ta bort ditt anpassade modellobjekt från scenen. Den bästa upplevelsen för den här självstudien är med testmodellen. Även om flera modeller stöds i ARR, skrevs den här självstudien för att bäst stödja en enda fjärrmodell i taget.

Nästa steg

Nu kan du läsa in dina egna modeller i Azure Remote Rendering och visa dem i ditt program! Därefter vägleder vi dig genom att manipulera dina modeller.