Share via


Zelfstudie: Interfaces en aangepaste modellen

In deze zelfstudie leert u het volgende:

  • Mixed Reality Toolkit toevoegen aan het project
  • Status van model beheren
  • Azure Blob-opslag configureren voor modelopname
  • Modellen uploaden en bewerken voor weergave

Vereisten

Aan de slag met Mixed Reality Toolkit (MRTK)

MRTK is een platformoverschrijdende toolkit voor het bouwen van Mixed Reality-ervaringen. We gebruiken MRTK 2.8.3 voor de interactie- en visualisatiefuncties.

De officiële handleiding voor het importeren van MRTK bevat enkele stappen die we niet hoeven uit te voeren. Alleen deze drie stappen zijn nodig:

  • Het importeren van de 'Mixed Reality Toolkit/Mixed Reality Toolkit Foundation' versie 2.8.3 in uw project via het Mixed Reality Feature Tool (IMPORT MRTK).
  • Voer de configuratiewizard van MRTK (MRTK configureren) uit.
  • MRTK toevoegen aan de huidige scène (Toevoegen aan scène). Gebruik hier het ARRMixedRealityToolkitConfigurationProfile in plaats van het voorgestelde profiel in de zelfstudie.

Assets importeren voor deze zelfstudie

Vanaf dit hoofdstuk implementeren we een basispatroon model-view-controller voor een groot deel van het materiaal dat wordt behandeld. Het modeldeel van het patroon is de specifieke code van Azure Remote Rendering en het statusbeheer voor Azure Remote Rendering. De onderdelen weergave en besturingselementen van het patroon worden geïmplementeerd met MRTK-assets en een aantal aangepaste scripts. Het is mogelijk om het model in deze zelfstudie te gebruiken zonder de weergavecontroller die hier is geïmplementeerd. Met deze scheiding kunt u eenvoudig de code in deze zelfstudie integreren in uw eigen toepassing, waarbij het weergavecontrollergedeelte van het ontwerppatroon wordt overgenomen.

Met de introductie van MRTK zijn er meerdere scripts, prefabs en assets die nu aan het project kunnen worden toegevoegd ter ondersteuning van interacties en visuele feedback. Deze assets die tutorial assets worden genoemd, worden gebundeld in een Unity Asset-pakket, dat is opgenomen in de Azure Remote Rendering GitHub in '\Unity\TutorialAssets\TutorialAssets.unitypackage'.

  1. Kloon of download de git-opslagplaats Azure Remote Rendering. Als u het downloadt, moet u het zip-bestand uitpakken in een bekende locatie.
  2. Kies in uw Unity-project assets -> Pakket importeren -> Aangepast pakket.
  3. Navigeer in de Bestandenverkenner naar de map waar u de Azure Remote Rendering-opslagplaats hebt gekloond of uitgepakt en selecteer vervolgens de .unitypackage gevonden in Unity -> TutorialAssets -> TutorialAssets.unitypackage
  4. Selecteer de knop Importeren om de inhoud van het pakket te importeren in uw project.
  5. Selecteer in de Unity-editor Mixed Reality Toolkit -> Hulpprogramma's -> MRTK Standard Shader upgraden voor Lightweight Render Pipeline in de bovenste menubalk en volg de aanwijzingen om de shader bij te werken.

Zodra MRTK en de zelfstudieassets zijn ingesteld, controleert u of het juiste profiel is geselecteerd.

  1. Selecteer in de scène-hiërarchie MixedRealityToolkit GameObject.
  2. Schakel in de Inspector, onder het onderdeel MixedRealityToolkit het configuratieprofiel over op ARRMixedRealityToolkitConfigurationProfile.
  3. Druk op Ctrl+S om uw wijziging op te slaan.

Met deze stap configureert u MRTK voornamelijk met de standaardprofielen HoloLens 2. De opgegeven profielen worden vooraf geconfigureerd op de volgende manieren:

  • Schakel de Profiler uit (druk op 9 om het in of uit te schakelen of zeg "Profiler weergeven/verbergen" op het apparaat).
  • Schakel de cursor oogtracering uit.
  • Schakel Unity-muisklikken in, zodat u op MRTK-gebruikersinterface-elementen kunt klikken met de muis in plaats van met de gesimuleerde hand.

Het app-menu toevoegen

De meeste besturingselementen voor weergave in deze zelfstudie kunnen worden gebruikt voor abstracte basisklassen in plaats van concrete klassen. Dit patroon biedt meer flexibiliteit en hiermee kunnen we u de weergavebesturingselementen bieden, terwijl u nog steeds de Azure Remote Rendering-code leert kennen. Voor het gemak heeft de klasse RemoteRenderingCoordinator geen abstracte klasse opgegeven en werkt de weergavecontroller rechtstreeks ten opzichte van de concrete klasse.

U kunt nu de prefab AppMenu toevoegen aan de scène voor visuele feedback van de huidige sessiestatus. In het AppMenu wordt ook het modale deelvenster weergegeven dat de gebruiker gebruikt om de toepassing te autoriseren om verbinding te maken met ARR.

  1. De prefab AppMenu zoeken in Assets/RemoteRenderingTutorial/Prefabs/AppMenu

  2. Sleep de prefab AppMenu in de scène.

  3. Als u een dialoogvenster voor TMP Importer ziet, volgt u de aanwijzingen om TMP Essentials te importeren. Sluit vervolgens het importdialoogvenster, omdat de voorbeelden en extra's niet nodig zijn.

  4. Het AppMenu is geconfigureerd om automatisch een verbinding te maken en de modaal te bieden voor verbinding met een sessie, zodat we de omleiding die eerder is ingesteld, kunnen verwijderen. Verwijder op het GameObject RemoteRenderingCoordinator de omleiding voor autorisatie die we eerder hebben geïmplementeerd door op de knop '-' te drukken op de gebeurtenis Bij autorisatieaanvraag.

    Bypass verwijderen.

  5. Test het weergavebesturingselement door op Afspelen te drukken in de Unity Editor.

  6. U kunt, nu MRTK is geconfigureerd, in de Editor de WASD-sleutels gebruiken om de positie van uw weergave te wijzigen en de rechtermuisknop vasthouden en de muis verplaatsen om uw weergaverichting te wijzigen. Probeer door de scène te bewegen om te zien hoe de besturingselementen werken.

  7. Op het apparaat kunt u uw palm heffen om het AppMenu op te roepen, in de Unity Editor gebruikt u de sneltoets 'M'.

  8. Als u het menu niet meer kunt vinden, drukt u op de toets 'M' om het menu op te roepen. Het menu wordt in de buurt van de camera geplaatst voor eenvoudige interactie.

  9. Het AppMenu bevat een UI-element voor autorisatie rechts van het AppMenu. Vanaf nu moet u dit UI-element gebruiken om de app te autoriseren om remote rendering-sessies te beheren.

    Gebruikersinterface autoriseren

  10. Stop het afspelen van Unity om door te gaan met de zelfstudie.

Status van model beheren

We hebben een nieuw script nodig met de naam RemoteRenderedModel voor het bijhouden van de status, het reageren op gebeurtenissen, het activeren van gebeurtenissen en de configuratie. RemoteRenderedModel slaat het externe pad op voor de modelgegevens in modelPath. Er wordt geluisterd naar statuswijzigingen in de RemoteRenderingCoordinator om te zien of het gedefinieerde model automatisch moet worden geladen of verwijderd. Het GameObject waaraan het RemoteRenderedModel is gekoppeld, is het lokale bovenliggende object voor de externe inhoud.

U ziet dat het script RemoteRenderedModel, BaseRemoteRenderedModel uit Zelfstudie-assets implementeert. Met deze verbinding kan de weergavecontroller voor het externe model worden gekoppeld aan uw script.

  1. Maak een nieuw script met de naam RemoteRenderedModel in dezelfde map als RemoteRenderingCoordinator. Vervang de volledige inhoud door de volgende code:

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

Eenvoudig gezegd, bevat RemoteRenderedModel de gegevens die nodig zijn om een model te laden (in dit geval de SAS of builtin:// URI) en wordt de status van het externe model bijgehouden. Wanneer het tijd is om het model te laden, wordt de LoadModel methode aangeroepen op RemoteRenderingCoordinator en wordt de entiteit met het model geretourneerd voor referentie en lossing.

Het testmodel laden

We gaan het nieuwe script testen door het testmodel opnieuw te laden. Voor deze test hebben we een Game-object nodig dat het script bevat en een bovenliggend element van het testmodel is, en we hebben ook een virtuele fase nodig die het model bevat. De fase blijft vast ten opzichte van de echte wereld met behulp van een WorldAnchor. We gebruiken een vaste fase, zodat het model zelf later nog steeds kan worden verplaatst.

  1. Maak een nieuw leeg gameobject in de scène en geef dit de naam ModelStage.

  2. Een World Anchor-onderdeel toevoegen aan ModelStage

    WorldAnchor-onderdeel toevoegen

  3. Maak een nieuw leeg gameobject als onderliggend element van ModelStage en noem dit TestModel.

  4. Voeg het script RemoteRenderedModel toe aan TestModel.

    Onderdeel RemoteRenderedModel toevoegen

  5. Voer bij Model Display Name en Model Path respectievelijk 'TestModel' en 'builtin://Engine' in.

    Modeldetails opgeven

  6. Plaats het object TestModel voor de camera op positie x = 0, y = 0, z = 3.

    Object position

  7. Zorg ervoor dat AutomaticallyLoad is ingeschakeld.

  8. Druk op Afspelen in de Unity Editor om de toepassing te testen.

  9. Ververleent autorisatie door op de knop Verbinding maken te klikken, zodat de app een sessie kan maken, hiermee verbinding kan maken en het model automatisch kan laden.

Bekijk de console terwijl de toepassing de statussen doorloopt. Houd er rekening mee dat het even kan duren voordat sommige statussen zijn voltooid en dat er een tijdje geen voortgangsupdates meer zijn. Uiteindelijk ziet u logboeken van het model dat wordt geladen en kort na het weergegeven testmodel in de scène.

Probeer het TestModel GameObject te verplaatsen en te draaien via de Transformatie in de inspector of in de weergave Scène en bekijk de transformaties in de gameweergave.

Unity-logboek

Blob-opslag inrichten in Azure en aangepaste modelopname

Nu kunnen we proberen uw eigen model te laden. Hiervoor moet u Blob Storage in Azure configureren, een model uploaden en converteren en vervolgens het model laden met behulp van het script RemoteRenderedModel . De aangepaste stappen voor het laden van een model kunnen veilig worden overgeslagen als u op dit moment geen eigen model hebt om te laden.

Volg de stappen die zijn opgegeven in de Snelstartgids: Een model converteren voor rendering. Sla de sectie Nieuw model invoegen in quickstart-voorbeeld-app over voor deze zelfstudie. Zodra u de SAS-URI (Shared Access Signature) van uw opgenomen model hebt, gaat u verder.

Een aangepast model laden en weergeven

  1. Maak een nieuw, leeg GameObject in de scène en geef deze een soortgelijke naam als uw aangepast model.

  2. Voeg het script RemoteRenderedModel toe aan het nieuw gemaakte GameObject.

    Onderdeel RemoteRenderedModel toevoegen

  3. Vul in de Model Display Name een passende naam in voor uw model.

  4. Vul de Model Path in met de SAS-URI (Shared Access Signature) van het model die u hebt gemaakt in de stap Blob Storage inrichten in Azure en aangepaste modelopname .

  5. Plaats het GameObject voor de camera op positie x = 0, y = 0, z = 3.

  6. Zorg ervoor dat AutomaticallyLoad is ingeschakeld.

  7. Druk op Afspelen in de Unity Editor om de toepassing te testen.

    De console toont de huidige sessiestatus en ook de voortgangsberichten van het laden van het model, zodra de sessie is verbonden.

  8. Verwijder uw aangepaste modelobject uit de scène. De beste ervaring voor deze zelfstudie is met het testmodel. Hoewel er meerdere modellen worden ondersteund in ARR, is deze zelfstudie geschreven om het beste één extern model tegelijk te ondersteunen.

Volgende stappen

U kunt nu uw eigen modellen in Azure Remote Rendering laden en ze in uw toepassing weergeven. Vervolgens begeleiden we u bij het bewerken van uw modellen.