Bagikan melalui


Tutorial: Antarmuka dan model kustom

Dalam tutorial ini, Anda mempelajari cara:

  • Menambahkan Mixed Reality Toolkit ke proyek
  • Mengelola status model
  • Mengonfigurasi Azure Blob Storage untuk penyerapan model
  • Mengunggah dan memproses model untuk penyajian

Prasyarat

Mulai menggunakan Mixed Reality Toolkit (MRTK)

Mixed Reality Toolkit (MRTK) adalah toolkit lintas platform untuk membangun pengalaman realitas campuran. Kami menggunakan MRTK 2.8.3 untuk fitur interaksi dan visualisasinya.

Panduan resmi untuk mengimpor MRTK berisi beberapa langkah yang tidak perlu kita lakukan. Hanya tiga langkah ini yang diperlukan:

  • Mengimpor 'Mixed Reality Toolkit/Mixed Reality Toolkit Foundation' versi 2.8.3 ke proyek Anda melalui Mixed Reality Feature Tool (Impor MRTK).
  • Jalankan wizard konfigurasi MRTK (Konfigurasi MRTK).
  • Tambahkan MRTK ke adegan saat ini (Tambahkan ke adegan). Gunakan ARRMixedRealityToolkitConfigurationProfile di sini alih-alih profil yang disarankan dalam tutorial.

Mengimpor aset yang digunakan oleh tutorial ini

Mulai dari bab ini, kami akan menerapkan pola pengontrol tampilan model dasar untuk sebagian besar materi yang tercakup. Bagian model dari pola tersebut adalah kode khusus Azure Remote Rendering dan manajemen status yang terkait dengan Azure Remote Rendering. Bagian tampilan dan pengontrol dari pola diterapkan menggunakan aset MRTK dan beberapa skrip kustom. Dimungkinkan untuk menggunakan model dalam tutorial ini tanpa view-controller yang diterapkan di sini. Pemisahan ini memungkinkan Anda untuk dengan mudah mengintegrasikan kode yang ditemukan dalam tutorial ini ke dalam aplikasi Anda sendiri di mana ia mengambil alih bagian view-controller dari pola desain.

Dengan pengenalan MRTK, ada beberapa skrip, prefab, dan aset yang sekarang dapat ditambahkan ke proyek untuk mendukung interaksi dan umpan balik visual. Aset ini disebut sebagai Aset Tutorial, dibundel ke dalam Paket Aset Unity, yang disertakan dalam Azure Remote Rendering GitHub di '\Unity\TutorialAssets\TutorialAssets.unitypackage'.

  1. Kloning atau unduh repositori git Azure Remote Rendering, jika mengunduh, ekstrak zip ke lokasi yang diketahui.
  2. Di proyek Unity Anda, pilih Aset -> Impor Paket -> Paket Kustom.
  3. Di penjelajah file, navigasikan ke direktori tempat Anda mengkloning atau membuka zip repositori Azure Remote Rendering, lalu pilih yang .unitypackage ditemukan di Unity -> TutorialAssets -> TutorialAssets.unitypackage
  4. Pilih tombol Impor untuk mengimpor konten paket ke dalam proyek Anda.
  5. Di Unity Editor, pilih Mixed Reality Toolkit -> Utilitas -> Upgrade MRTK Standard Shader untuk Lightweight Render Pipeline dari bilah menu atas dan ikuti perintah untuk meningkatkan shader.

Setelah MRTK dan Aset Tutorial disiapkan, periksa kembali, bahwa profil yang benar dipilih.

  1. Pilih MixedRealityToolkit GameObject dalam hierarki scene.
  2. Di Inspector, pada komponen MixedRealityToolkit, alihkan profil konfigurasi ke ARRMixedRealityToolkitConfigurationProfile.
  3. Tekan Ctrl+S untuk menyimpan perubahan Anda.

Langkah ini mengonfigurasi MRTK, terutama, dengan profil HoloLens 2 default. Profil yang disediakan telah dikonfigurasi sebelumnya dengan cara berikut:

  • Matikan profiler (Tekan 9 untuk mengaktifkan/menonaktifkannya, atau ucapkan "Tampilkan/Sembunyikan Profiler" di perangkat).
  • Matikan kursor tatapan mata.
  • Aktifkan klik mouse Unity, sehingga Anda dapat mengeklik elemen antarmuka pengguna MRTK dengan mouse, bukan dengan tangan yang disimulasikan.

Menambahkan Menu Aplikasi

Sebagian besar pengontrol tampilan dalam tutorial ini beroperasi melawan kelas dasar abstrak sebagai ganti dari melawan kelas konkret. Pola ini memberikan lebih banyak fleksibilitas dan memungkinkan kami menyediakan pengontrol tampilan untuk Anda, sambil tetap membantu Anda mempelajari kode Azure Remote Rendering. Untuk kesederhanaan, kelas RemoteRenderingCoordinator tidak memiliki kelas abstrak yang disediakan dan pengontrol tampilannya beroperasi langsung terhadap kelas konkret.

Anda sekarang dapat menambahkan AppMenu prefab ke scene, untuk umpan balik visual dari status sesi saat ini. AppMenu juga menyajikan panel modal yang digunakan pengguna untuk mengotorisasi aplikasi untuk terhubung ke ARR.

  1. Temukan prefab AppMenu di Assets/RemoteRenderingTutorial/Prefabs/AppMenu

  2. Seret prefab AppMenu ke dalam scene.

  3. Jika Anda melihat dialog untuk Pengimpor TMP, ikuti perintah untuk Mengimpor TMP Essentials. Kemudian tutup dialog pengimpor, karena contoh dan tambahan tidak diperlukan.

  4. AppMenu dikonfigurasi untuk menyambungkan secara otomatis dan menyediakan modal untuk menyetujui sambungan ke Sesi, sehingga bypass yang ditempatkan sebelumnya dapat dihapus. Pada RemoteRenderingCoordinator GameObject, hapus bypass untuk otorisasi yang diterapkan sebelumnya, dengan menekan tombol '-' pada peristiwa Saat Meminta Otorisasi.

    Hapus bypass .

  5. Uji pengontrol tampilan dengan menekan Putar di Editor Unity.

  6. Di Editor, sekarang MRTK dikonfigurasi, Anda dapat menggunakan tombol WASD untuk mengubah posisi tampilan Anda dan menahan tombol kanan mouse + menggerakkan mouse untuk mengubah arah tampilan Anda. Cobalah "berkeliling" di sekitar scene sedikit untuk merasakan kontrolnya.

  7. Pada perangkat, Anda dapat menaikkan telapak tangan untuk memanggil AppMenu, di Editor Unity, gunakan tombol pintas 'M'.

  8. Jika Anda tidak melihat menu, tekan tombol 'M' untuk memanggil menu. Menu ditempatkan di dekat kamera untuk interaksi yang mudah.

  9. AppMenu menyajikan elemen UI untuk otorisasi di sebelah kanan AppMenu. Mulai sekarang, Anda harus menggunakan elemen UI ini untuk mengotorisasi aplikasi guna mengelola sesi penyajian jarak jauh.

    Mengotorisasi antarmuka pengguna

  10. Hentikan Unity dari pemutaran untuk melanjutkan tutorial.

Mengelola status model

Kami memerlukan skrip baru yang disebut RemoteRenderedModel yang untuk melacak status, menanggapi peristiwa, menembakkan peristiwa, dan konfigurasi. Pada dasarnya, RemoteRenderedModel menyimpan jalur jarak jauh untuk data model di modelPath. Ini mendengarkan perubahan status di RemoteRenderingCoordinator untuk melihat apakah itu harus secara otomatis memuat atau membongkar model yang ditentukannya. GameObject yang memiliki RemoteRenderedModel yang melekat padanya adalah induk lokal untuk konten jarak jauh.

Perhatikan bahwa skrip RemoteRenderedModel menerapkan BaseRemoteRenderedModel, yang disertakan dari Tutorial Assets. Koneksi ini memungkinkan pengontrol tampilan model jarak jauh untuk mengikat dengan skrip Anda.

  1. Buat skrip baru bernama RemoteRenderedModel di folder yang sama dengan RemoteRenderingCoordinator. Ganti seluruh konten dengan kode berikut:

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

Dalam istilah yang paling dasar, RemoteRenderedModel menyimpan data yang diperlukan untuk memuat model (dalam hal ini SAS atau builtin:// URI) dan melacak status model jarak jauh. Ketika saatnya untuk memuat model, LoadModel metode dipanggil pada RemoteRenderingCoordinator, dan Entitas yang berisi model dikembalikan untuk referensi dan pembongkaran.

Memuat Model Pengujian

Mari kita uji skrip baru dengan memuat kembali model pengujian. Untuk pengujian ini, kita memerlukan Objek Game untuk berisi skrip dan menjadi induk model pengujian, dan kita juga memerlukan tahap virtual yang berisi model. Panggung tetap relatif terhadap dunia nyata menggunakan WorldAnchor. Kita menggunakan panggung tetap sehingga model itu sendiri masih dapat dipindahkan nanti.

  1. Buat Objek Game kosong baru di scene dan beri nama ModelStage.

  2. Tambahkan komponen Jangkar Dunia ke ModelStage

    Menambahkan komponen WorldAnchor

  3. Buat Objek Game kosong baru sebagai anak dari ModelStage dan beri nama TestModel.

  4. Tambahkan skrip RemoteRenderedModel ke TestModel.

    Menambahkan komponen RemoteRenderedModel

  5. Isi Model Display Name dan Model Path dengan masing-masing "TestModel" dan "builtin://Engine".

    Menentukan detail model

  6. Posisikan objek TestModel di depan kamera, pada posisi x = 0, y = 0, z = 3.

    Memosisikan objek

  7. Pastikan AutomaticallyLoad diaktifkan.

  8. Tekan Putar di Editor Unity untuk menguji aplikasi.

  9. Berikan otorisasi dengan mengklik tombol Sambungkan untuk memungkinkan aplikasi membuat sesi, menyambungkannya, dan memuat model secara otomatis.

Tonton Konsol saat aplikasi berlangsung melalui statusnya. Perlu diingat, beberapa status mungkin membutuhkan waktu untuk diselesaikan, dan mungkin tidak ada pembaruan kemajuan untuk sementara waktu. Akhirnya, Anda melihat log dari pemuatan model dan kemudian tak lama setelah model pengujian yang dirender di adegan.

Coba pindahkan dan putar TestModel GameObject melalui Transformasi di Inspektur, atau dalam tampilan Adegan dan amati transformasi dalam tampilan Game.

Log Unity

Memprovisikan Blob Storage di Azure dan penyerapan model kustom

Sekarang kita dapat mencoba memuat model Anda sendiri. Untuk melakukannya, Anda perlu mengonfigurasi Blob Storage di Azure, mengunggah dan mengonversi model, lalu memuat model menggunakan skrip RemoteRenderedModel . Langkah-langkah pemuatan model kustom dapat dilompati dengan aman jika Anda tidak memiliki model sendiri untuk dimuat saat ini.

Ikuti langkah-langkah yang ditentukan dalam Mulai cepat: Mengonversi model untuk penyajian. Lewati bagian Sisipkan model baru ke dalam Aplikasi Sampel Mulai Cepat untuk tutorial ini. Setelah Anda memiliki URI Tanda Tangan Akses Bersama (SAS) model yang diserap, lanjutkan.

Muatan dan penyajian model kustom

  1. Buat GameObject kosong baru di scene dan beri nama yang mirip dengan model kustom Anda.

  2. Tambahkan skrip RemoteRenderedModel ke GameObject yang baru dibuat.

    Menambahkan komponen RemoteRenderedModel

  3. Isi Model Display Name dengan nama yang sesuai untuk model Anda.

  4. Model Path Isi dengan URI Tanda Tangan Akses Bersama (SAS) model yang Anda buat di Provision Blob Storage di Azure dan langkah penyerapan model kustom.

  5. Posisikan GameObject di depan kamera, pada posisi x = 0, y = 0, z = 3.

  6. Pastikan AutomaticallyLoad diaktifkan.

  7. Tekan Putar di Editor Unity untuk menguji aplikasi.

    Konsol menunjukkan status sesi saat ini dan juga pesan kemajuan pemuatan model, setelah sesi tersambung.

  8. Hapus objek model kustom Anda dari scene. Pengalaman terbaik untuk tutorial ini adalah dengan model pengujian. Meskipun beberapa model didukung di ARR, tutorial ini ditulis untuk mendukung model jarak jauh tunggal pada satu waktu.

Langkah berikutnya

Sekarang Anda dapat memuat model Anda sendiri ke Azure Remote Rendering dan menampilkannya di aplikasi Anda! Selanjutnya, kami memandu Anda memanipulasi model Anda.