Kurz: Rozhraní a vlastní modely

V tomto kurzu se naučíte:

  • Přidání sady nástrojů Mixed Reality do projektu
  • Správa stavu modelu
  • Konfigurace Azure Blob Storage pro příjem dat modelů
  • Nahrávání a zpracování modelů pro vykreslování

Požadavky

Začínáme se sadou nástrojů Mixed Reality (MRTK)

MRTK (Mixed Reality Toolkit) je multiplatformní sada nástrojů pro vytváření prostředí hybridní reality. MRTK 2.8.3 používáme pro interakce a vizualizační funkce.

Oficiální průvodce importem MRTK obsahuje několik kroků, které nemusíme dělat. Jsou nutné pouze tyto tři kroky:

  • Import Mixed Reality Toolkit/Mixed Reality Toolkit Foundation verze 2.8.3 do projektu prostřednictvím nástroje Mixed Reality Feature Tool (Import MRTK).
  • Spusťte průvodce konfigurací MRTK (Konfigurace MRTK).
  • Přidání MRTK do aktuální scény (Přidat do scény) Místo profilu navrhovaného v tomto kurzu použijte soubor ARRMixedRealityToolkitConfigurationProfile .

Import prostředků používaných v tomto kurzu

Počínaje touto kapitolou budeme implementovat základní vzor model-zobrazení-kontroler pro většinu probíraného materiálu. Součástí modelu je kód specifický pro Azure Remote Rendering a správa stavu související s Azure Remote Rendering. Části modelu zobrazení a kontroleru se implementují pomocí prostředků MRTK a některých vlastních skriptů. V tomto kurzu je možné použít model bez implementace kontroleru zobrazení . Toto oddělení umožňuje snadno integrovat kód, který najdete v tomto kurzu, do vaší vlastní aplikace, kde převezme část vzoru návrhu kontroleru zobrazení .

Se zavedením MRTK je k dispozici několik skriptů, předfab a prostředků, které se teď dají přidat do projektu pro podporu interakcí a vizuální zpětné vazby. Tyto prostředky označované jako prostředky kurzu jsou seskupené do balíčku prostředků Unity, který je součástí Azure Remote Rendering GitHubu v \Unity\TutorialAssets\TutorialAssets.unitypackage.

  1. Naklonujte nebo stáhněte úložiště Git Azure Remote Rendering, pokud stahování extrahujete soubor ZIP do známého umístění.
  2. V projektu Unity zvolte Prostředky –> Import balíčku –> Vlastní balíček.
  3. V Průzkumníkovi souborů přejděte do adresáře, do kterého jste naklonovali nebo rozbalili úložiště Azure Remote Rendering, a pak vyberte .unitypackage soubor nalezený v Unity –> TutorialAssets –> TutorialAssets.unitypackage.
  4. Výběrem tlačítka Importovat naimportujte obsah balíčku do projektu.
  5. V Unity Editoru v horním řádku nabídek vyberte Mixed Reality Toolkit –> Utilities –> Upgrade MRTK Standard Shader for Lightweight Render Pipeline a podle pokynů upgradujte shader.

Po nastavení MRTK a prostředků kurzu pečlivě zkontrolujte, jestli je vybraný správný profil.

  1. V hierarchii scény vyberte Objekt GameObject MixedRealityToolkit .
  2. V inspektoru v komponentě MixedRealityToolkit přepněte konfigurační profil na ARRMixedRealityToolkitConfigurationProfile.
  3. Stisknutím kombinace kláves Ctrl+S uložte změny.

Tento krok konfiguruje MRTK primárně s výchozími profily HoloLens 2. Zadané profily jsou předkonfigurované následujícími způsoby:

  • Vypněte profiler (Stisknutím tlačítka 9 ho zapněte nebo vypněte nebo na zařízení řekněte "Zobrazit nebo skrýt profiler").
  • Vypněte kurzor pohledu.
  • Povolte kliknutí myší Unity, abyste mohli místo simulované ruky kliknout na prvky uživatelského rozhraní MRTK myší.

Přidání nabídky aplikace

Většina kontrolerů zobrazení v tomto kurzu pracuje s abstraktními základními třídami místo s konkrétními třídami. Tento model poskytuje větší flexibilitu a umožňuje nám poskytovat kontrolery zobrazení za vás a zároveň vám pomáhá naučit se kód azure Remote Rendering. Pro jednoduchost RemoteRenderingCoordinator třída nemá k dispozici abstraktní třídu a její kontroler zobrazení pracuje přímo s konkrétní třídou.

Teď můžete na scénu přidat předběžnou appMenu , abyste mohli vizuálně vyjádřit stav aktuální relace. AppMenu také zobrazí modální panel, který uživatel používá k autorizaci aplikace pro připojení k ARR.

  1. Vyhledejte prefab AppMenu v části Assets/RemoteRenderingTutorial/Prefabs/AppMenu.

  2. Přetáhněte prefab AppMenu na scénu.

  3. Pokud se zobrazí dialogové okno pro nástroj TMP Importer, postupujte podle pokynů k importu základy TMP. Potom dialogové okno pro import zavřete, protože příklady a doplňky nejsou potřeba.

  4. AppMenu je nakonfigurovaná tak, aby se automaticky připojila a poskytla modální vyjádření souhlasu s připojením k relaci, abychom mohli dříve umístěné obcházení odebrat. Na RemoteRenderingCoordinator GameObject odeberte obejití pro autorizaci, kterou jsme implementovali dříve, stisknutím tlačítka "-" u události Při žádosti o autorizaci .

    Odebrat obejití.

  5. Otestujte kontroler zobrazení stisknutím play v Unity Editoru.

  6. Když je teď v Editoru nakonfigurovaný MRTK, můžete pomocí kláves WASD změnit pozici zobrazení a podržením pravého tlačítka myši + přesunutím myši změnit směr zobrazení. Zkuste trochu "projet" po scéně, abyste získali cit pro ovládání.

  7. Na zařízení můžete zvednutím dlaně vyvolat AppMenu. V Unity Editoru použijte klávesovou zkratku "M".

  8. Pokud jste nabídku ztratili z dohledu, stiskněte klávesu "M", aby se menu vyvolalo. Menu je umístěno v blízkosti kamery pro snadnou interakci.

  9. AppMenu představuje prvek uživatelského rozhraní pro autorizaci napravo od AppMenu. Od této chvíle byste měli tento prvek uživatelského rozhraní používat k autorizaci aplikace ke správě relací vzdáleného vykreslování.

    Autorizace uživatelského rozhraní

  10. Pokud chcete pokračovat v kurzu, zastavte Unity v hraní.

Správa stavu modelu

Potřebujeme nový skript s názvem RemoteRenderedModel , který slouží ke sledování stavu, reagování na události, spouštění událostí a konfiguraci. RemoteRenderedModel v podstatě ukládá vzdálenou cestu k datům modelu v modelPathsouboru . Naslouchá změnám stavu v remoteRenderingCoordinatoru a zjistí, jestli by se měl model, který definuje, automaticky načíst nebo uvolnit. Objekt GameObject, který má připojený objekt RemoteRenderedModel , je místním nadřazeným objektem pro vzdálený obsah.

Všimněte si, že skript RemoteRenderedModel implementuje BaseRemoteRenderedModel, který je součástí tutorial assets. Toto připojení umožňuje vzdálenému kontroleru zobrazení modelu vytvořit vazbu s vaším skriptem.

  1. Vytvořte nový skript s názvem RemoteRenderedModel ve stejné složce jako RemoteRenderingCoordinator. Celý obsah nahraďte následujícím kódem:

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

Z nejzákladnějšího hlediska remoteRenderedModel uchovává data potřebná k načtení modelu (v tomto případě SAS nebo identifikátor URI builtin:// ) a sleduje stav vzdáleného modelu. Když je čas načíst model, LoadModel volá se metoda v RemoteRenderingCoordinator a entita obsahující model se vrátí pro referenci a uvolnění.

Načtení testovacího modelu

Pojďme nový skript otestovat opětovným načtením testovacího modelu. Pro tento test potřebujeme herní objekt, který bude obsahovat skript a být nadřazený testovacímu modelu, a potřebujeme také virtuální fázi, která obsahuje model. Fáze zůstává pevně daná vzhledem k reálnému světu pomocí funkce WorldAnchor. Používáme pevnou fázi, aby bylo možné později přesunout samotný model.

  1. Ve scéně vytvořte nový prázdný herní objekt a pojmenujte ho ModelStage.

  2. Přidání komponenty World Anchor do ModelStage

    Přidání komponenty WorldAnchor

  3. Vytvořte nový prázdný herní objekt jako podřízený objektu ModelStage a pojmenujte ho TestModel.

  4. Přidejte skript RemoteRenderedModel do modelu TestModel.

    Přidání komponenty RemoteRenderedModel

  5. Vyplňte Model Display Name hodnoty a Model Path "TestModel" a "builtin://Engine".

    Zadání podrobností o modelu

  6. Umístěte objekt TestModel před kameru na pozici x = 0, y = 0, z = 3.

    Umístění objektu

  7. Ujistěte se, že je zapnuté automatické načítání .

  8. Stisknutím tlačítka Přehrát v Editoru Unity aplikaci otestujte.

  9. Udělte autorizaci kliknutím na tlačítko Připojit , aby aplikace mohla vytvořit relaci, připojit se k ní a automaticky načíst model.

Sledujte konzolu, jak aplikace prochází svými stavy. Mějte na paměti, že dokončení některých stavů může nějakou dobu trvat a chvíli nemusí být k dispozici žádné aktualizace průběhu. Nakonec se na scéně zobrazí protokoly z načítání modelu a krátce po vykreslení testovacího modelu.

Zkuste objekt TestModel GameObject přesouvat a otáčet pomocí transformace v inspektoru nebo v zobrazení scény a sledujte transformace v zobrazení Hry.

Protokol Unity

Zřízení služby Blob Storage v Azure a příjem vlastních modelů

Teď můžeme zkusit načíst vlastní model. K tomu je potřeba nakonfigurovat službu Blob Storage v Azure, nahrát a převést model a pak model načíst pomocí skriptu RemoteRenderedModel . Pokud v tuto chvíli nemáte vlastní model k načtení, můžete kroky načítání vlastního modelu bezpečně přeskočit.

Postupujte podle kroků uvedených v rychlém startu: Převod modelu pro vykreslování. Pro účely tohoto kurzu přeskočte část Vložení nového modelu do ukázkové aplikace pro rychlý start . Jakmile budete mít identifikátor sdíleného přístupového podpisu (SAS) ingestované modelu, pokračujte.

Načtení a vykreslení vlastního modelu

  1. Ve scéně vytvořte nový prázdný objekt GameObject a pojmenujte ho podobně jako váš vlastní model.

  2. Přidejte skript RemoteRenderedModel do nově vytvořeného objektu GameObject.

    Přidání komponenty RemoteRenderedModel

  3. Model Display Name Zadejte odpovídající název pro váš model.

  4. Model Path Vyplňte identifikátor URI sdíleného přístupového podpisu (SAS) modelu, který jste vytvořili v kroku Zřízení úložiště objektů blob v Azure a příjem dat vlastního modelu.

  5. Umístěte GameObject před kameru na pozici x = 0, y = 0, z = 3.

  6. Ujistěte se, že je zapnuté automatické načítání .

  7. Stisknutím tlačítka Přehrát v Editoru Unity aplikaci otestujte.

    Po připojení relace konzola zobrazí aktuální stav relace a také zprávy o průběhu načítání modelu.

  8. Odeberte objekt vlastního modelu ze scény. Nejlepší prostředí pro tento kurz je s testovacím modelem. I když se v ARR podporuje více modelů, tento kurz byl napsán tak, aby co nejlépe podporoval jeden vzdálený model najednou.

Další kroky

Teď můžete do Azure Remote Rendering načíst vlastní modely a zobrazit je ve své aplikaci. Dále vás provedeme manipulací s vašimi modely.