Kurz: Rozhraní a vlastní modely

V tomto kurzu se naučíte:

  • Přidání Mixed Reality Toolkit 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 Mixed Reality Toolkit (MRTK)

Sada Mixed Reality Toolkit (MRTK) je sada nástrojů pro různé platformy pro vytváření prostředí hybridní reality. K interakci a vizualizaci použijeme MRTK 2.5.1.

Pokud chcete přidat MRTK, postupujte podle požadovaných kroků uvedených v průvodci instalací MRTK.

Jde o následující kroky:

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

Počínaje touto kapitolou implementujeme jednoduchý vzor model-view-controller pro velkou část zahrnutých materiálů. Součástí modelu je model, který Azure Remote Rendering kód a správu stavu související s Azure Remote Rendering. Části modelu zobrazení a kontroleru jsou implementovány pomocí prostředků MRTK a některých vlastních skriptů. Model v tomto kurzu je možné použít bez zde implementované kontroleru zobrazení. Toto oddělení umožňuje snadno integrovat kód z tohoto kurzu do vlastní aplikace, kde bude převzít část návrhu kontroleru zobrazení.

Se zavedením MRTK je teď možné do projektu přidat několik skriptů, předfád a prostředků, které podporují interakce a vizuální zpětnou vazbu. Tyto prostředky, označované jako prostředky kurzu, jsou součástí balíčku prostředků Unity,který je součástí gitHubu Azure Remote Rendering ve složce \Unity\TutorialAssets\TutorialAssets\TutorialAssets.unitypackage.

  1. Pokud stáhnete soubor zip do Azure Remote Rendering,naklonujte nebo stáhněte úložiště Git Azure Remote Rendering .
  2. V projektu Unity zvolte Assets -> Import Package -> Custom Package (Prostředky -> Import balíčku -> Vlastní balíček).
  3. V Průzkumníku souborů přejděte do adresáře, do něj který jste naklonovali nebo rozbalili úložiště Azure Remote Rendering, a pak vyberte soubor .unitypackage v Unity -> TutorialAssets -> TutorialAssets.unitypackage.
  4. Výběrem tlačítka Importovat naimportujte obsah balíčku do projektu.
  5. V Editoru Unity vyberte v horním řádku nabídek Mixed Reality Toolkit -> Utilities -> Upgrade MRTK Standard Shader for Lightweight Render Pipeline (Upgrade MRTK Standard Shader for Lightweight Render Pipeline) a postupujte podle pokynů k upgradu shaderu.

Jakmile do projektu zahrnete MRTK a prostředky kurzu, přepnete profil MRTK na jeden vhodnější pro tento kurz.

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

Tím se konfiguruje MRTK primárně s výchozími profily HoloLens 2. Zadané profily jsou předem nakonfigurované následujícími způsoby:

  • Vypněte profiler (stisknutím klávesy 9 ho zapněte nebo vypněte, nebo na zařízení řekněte "Show/Hide Profiler" (Zobrazit/skrýt profiler).)
  • Vypněte kurzor pohledu oka.
  • Povolte kliknutí myší v Unity, abyste místo simulované ruky mohli kliknout na prvky uživatelského rozhraní MRTK pomocí myši.

Přidání nabídky aplikace

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

Teď můžete do scény přidat předfab AppMenu pro vizuální zpětnou vazbu k aktuálnímu stavu relace. Tento kontroler zobrazení "odemkne" další kontrolery zobrazení podnabídky při implementaci a integraci dalších funkcí ARR do scény. AppMenu teď bude mít vizuální indikaci stavu ARR a zobrazí modální panel, který uživatel používá k autorizaci aplikace pro připojení k ARR.

  1. Vyhledejte předfab AppMenu v části Assets/RemoteRenderingTutorial/Prefabs/AppMenu.

  2. Přetáhněte předběžné nastavení AppMenu do scény.

  3. Pravděpodobně se zobrazí dialogové okno pro TMP Importer, protože do scény poprvé zasažujeme prostředky Text Mesh Pro. Podle pokynů naimportujte základy TMP. Pak zavřete dialogové okno importu, příklady a doplňky nejsou potřeba.

  4. AppMenu je nakonfigurovaná tak, aby se automaticky připojoval a poskytoval modální stav pro souhlas s připojením k relaci, takže můžeme obcházení, které jsme umístili dříve, odebrat. V objektu GameObject RemoteRenderingCoordinator odeberte obcházení pro autorizaci, kterou jsme implementovali dříve, stisknutím tlačítka -u události On Requesting Authorization (Při žádosti o autorizaci).

    Odebrání obcházení.

  5. Kontroler zobrazení otestujte stisknutím tlačítka Přehrát v Editoru Unity.

  6. Teď, když je v editoru nakonfigurovaná funkce MRTK, můžete pomocí kláves WASD změnit umístění zobrazení a podržením pravého tlačítka myši a pohybem myši změnit směr zobrazení. Zkuste ovládací prvky trochu "řídit" po scéně.

  7. Na zařízení můžete zvýšit úroveň appmenu, v Editoru Unity použijte klávesovou zkratku M.

  8. Pokud jste nabídku ztratili, stisknutím klávesy M nabídku vyvolejte. Nabídka se kvůli snadné interakci umístí do blízkosti fotoaparátu.

  9. Autorizace se teď bude zobrazovat jako požadavek napravo od appmenu. Od této části ji použijete 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, aby nepřehrává.

Správa stavu modelu

Teď implementujeme nový skript RemoteRenderedModel, který je pro sledování stavu, reagování na události, aktivaci událostí a konfiguraci. RemoteRenderedModel v podstatě ukládá vzdálenou cestu k datům modelu v modelPath objektu . Bude naslouchat změnám stavu v remoteRenderingCoordinatoru, aby bylo vidět, jestli by měl automaticky načíst nebo uvolnit model, který definuje. Objekt GameObject, který má připojený model RemoteRenderedModel, bude 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. To umožní vzdálenému kontroleru zobrazení modelu vytvořit vazbu s vaším skriptem.

  1. Ve stejné složce jako RemoteRenderingCoordinator vytvořte nový skript s názvem RemoteRenderedModel. 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);
        }
    }
    

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

Načtení testovacího modelu

Pojďme nový skript otestovat tak, že znovu načítáme testovací model. Přidáme herní objekt, který bude obsahovat skript a bude nadřazeným objektem testovacího modelu. Vytvoříme také virtuální fázi, která obsahuje model. Fáze zůstane pevná vzhledem ke skutečnému světu pomocí WorldAnchor. Používáme pevnou fázi, aby bylo možné přesunout samotný model později.

  1. Ve scéně vytvořte nový prázdný herní objekt a pojmnte 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ý objekt modelu ModelStage a pojmnujte ho TestModel.

  4. Přidejte skript RemoteRenderedModel do třídy TestModel.

    Přidání komponenty RemoteRenderedModel

  5. Jako a Model Display Name zadejte Model Path "TestModel" a "builtin://Engine" ( v uvedeném pořadí).

    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. V editoru Unity stiskněte Přehrát a otestujte aplikaci.

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

Sledujte konzolu, když aplikace pokračuje prostřednictvím svých stavů. Pamatujte si, že některé stavy můžou nějakou dobu trvat a nebude se zobrazovat průběh. Nakonec se zobrazí protokoly z načítání modelu a potom se model testu vykreslí na scéně.

Zkuste přesunout a otočit TestModel GameObject přes transformaci v inspektoru nebo v zobrazení scény. Uvidíte, že se model přesune a otočí v zobrazení herních zařízení.

Protokol Unity

Zřizování Blob Storage v Azure a přijímání vlastních modelů

Teď můžeme zkusit načíst váš vlastní model. Abyste to mohli udělat, musíte nakonfigurovat Blob Storage a v Azure, nahrát a převést model a potom model nahrajeme pomocí skriptu RemoteRenderedModel . Pokud nemáte vlastní model, který se má v tuto chvíli načíst, můžete postup 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 oddíl vložení nového modelu do ukázkové aplikace pro rychlé zprovoznění. Až budete mít identifikátor URI sdíleného přístupového podpisu (SAS) pro ingestný model, pokračujte dalším krokem.

Načtení a vykreslení vlastního modelu

  1. Vytvořte ve scéně novou prázdnou GameObject a pojmenujte ji jako svůj vlastní model.

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

    Přidat komponentu RemoteRenderedModel

  3. Zadejte Model Display Name pro svůj model příslušný název.

  4. Zadejte Model Path identifikátor URI sdíleného přístupového podpisu (SAS) modelu, který jste vytvořili v krocích příjmu výše.

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

  6. Ujistěte se, že je zapnutá funkce AutomaticallyLoad .

  7. Kliknutím na tlačítko Přehrát v editoru Unity otestujete aplikaci.

    Uvidíte, že se konzola začne naplnit aktuálním stavem, a nakonec bude modelovat zprávy o průběhu. Váš vlastní model se pak nahraje do scény.

  8. Odeberte objekt vlastního modelu z scény. Nejlepší prostředí pro tento kurz bude používat model testování. I když je v ARR podporováno více modelů, byl tento kurz napsán tak, aby nejlépe podporoval jeden vzdálený model v jednom okamžiku.

Další kroky

Nyní můžete načíst vlastní modely do vzdáleného vykreslování Azure a zobrazit je ve vaší aplikaci. V dalším kroku Vás provedeme manipulací s vašimi modely.