Tutorial: Menampilkan model yang dirender dari jarak jauh
Dalam tutorial ini, Anda akan mempelajari cara:
- Provisikan instans Azure Remote Rendering (ARR)
- Buat dan hentikan sesi penyajian
- Gunakan kembali sesi penyajian yang sudah ada
- Sambungkan dan putuskan sambungan dari sesi
- Muat model ke dalam sesi penyajian
Prasyarat
Untuk tutorial ini, Anda perlu:
- Langganan Azure berbayar sesuai waktu aktif Buat akun
- Windows SDK 10.0.18362.0 (unduh)
- Versi terbaru Visual Studio 2022 (unduh)
- Git (unduh)
- Plugin Git LFS (unduh)
- Unity (melihat persyaratan sistem untuk versi yang didukung)
- Pengetahuan menengah tentang Unity dan bahasa C# (misalnya: membuat skrip dan objek, menggunakan prefab, mengonfigurasi peristiwa Unity, dll.)
Provisikan instans Azure Remote Rendering (ARR)
Untuk mendapatkan akses ke layanan Azure Remote Rendering, Anda harus membuat akun terlebih dahulu.
Membuat proyek Unity baru
Tip
Repositori sampel ARR yang berisi proyek dengan semua tutorial sudah selesai, dapat digunakan sebagai referensi. Lihat di Unity\Tutorial-Complete untuk proyek Unity lengkap.
Dari Unity Hub, buat proyek baru. Dalam contoh ini, kami berasumsi proyek sedang dibuat dalam folder bernama RemoteRendering.
Sertakan paket Azure Remote Rendering dan OpenXR
Ikuti instruksi tentang cara menambahkan paket Azure Remote Rendering dan OpenXR ke Proyek Unity Anda.
Catatan
Jika Unity menampilkan dialog peringatan setelah mengimpor paket OpenXR yang menanyakan apakah akan mengaktifkan backend platform asli untuk sistem input baru, klik Tidak untuk saat ini. Anda akan mengaktifkannya di langkah selanjutnya.
Konfigurasikan kamera
Pilih simpul Kamera Utama.
Buka menu konteks dengan mengklik kanan komponen Transformasi dan pilih opsi Reset :
Atur Hapus bendera ke Warna Solid
Atur Latar Belakang ke Hitam (#000000), dengan alfa (A) transparan sepenuhnya (0)
Atur Clipping Planes ke Near = 0.1 dan Far = 20. Penyiapan ini berarti merender geometri klip yang lebih dekat dari 10 cm atau lebih jauh dari 20 meter.
Sesuaikan pengaturan proyek
Buka Edit > Pengaturan Proyek...
Pilih Kualitas dari menu daftar kiri
Ubah Tingkat Kualitas Default semua platform menjadi Rendah. Pengaturan ini memungkinkan penyajian konten lokal yang lebih efisien dan tidak memengaruhi kualitas konten yang dirender dari jarak jauh.
Catatan
Dalam cakupan tutorial ini, kita tetap dengan alur render bawaan Unity. Jika Anda ingin menggunakan Universal Render Pipeline, lihat Alur Render Unity untuk langkah-langkah penyiapan tambahan.
Pilih Manajemen Plugin XR dari menu daftar kiri
- Klik tombol Instal Manajemen Plugin XR.
- Pilih tab pengaturan Universal Windows Platform, yang dinyatakan sebagai ikon Windows.
- Pilih kotak centang Buka XR di bawah Penyedia Plug-In
- Jika dialog terbuka yang meminta Anda untuk mengaktifkan backend platform asli untuk sistem input baru, pilih Tidak.
Catatan
Jika grup fitur Microsoft HoloLens dinonaktifkan, Plugin Windows Mixed Reality OpenXR hilang dari proyek Anda. Ikuti instruksi tentang cara menambahkan paket Azure Remote Rendering dan OpenXR untuk menginstalnya.
Pilih OpenXR dari menu daftar kiri
- Atur Mode Pengiriman Kedalaman ke Kedalaman 16 Bit
- Tambahkan Profil Interaksi Tangan Microsoft ke Profil Interaksi.
- Aktifkan fitur OpenXR ini:
- Azure Remote Rendering
- Pelacakan Tangan
- Fitur Mixed Reality
- Model Pengontrol Gerak
Catatan
Jika Anda tidak melihat fitur OpenXR yang diperlukan yang tercantum Plugin OpenXR Windows Mixed Reality hilang dari proyek Anda. Ikuti instruksi tentang cara menambahkan paket Azure Remote Rendering dan OpenXR untuk menginstalnya.
Pilih Pemutar dari menu daftar kiri
- Pilih tab pengaturan Universal Windows Platform, yang dinyatakan sebagai ikon Windows.
- Perluas Pengaturan Lain
- Di bawah Penyajian ubah Ruang Warna menjadi Linier dan mulai ulang Unity saat meminta Anda.
- Di bawah Konfigurasi ubah Penanganan Input Aktif ke Unity dan mulai ulang Unity saat meminta Anda.
- Perluas Pengaturan Penerbitan
- Gulir ke bawah ke Kemampuan dan pilih:
- InternetClient
- InternetClientServer
- Persepsi Spasial
- PrivateNetworkClientServer(opsional). Pilih opsi ini jika Anda ingin menyambungkan Unity remote debugger ke perangkat Anda.
- Di bawah Keluarga Perangkat yang Didukung, aktifkanHolografik dan Desktop
Tutup atau tambatkan panel Pengaturan Proyek
Buka Pengaturan File-Build>
- Pilih Platform Windows Universal
- Konfigurasikan setelan Anda agar sesuai dengan yang ditemukan di bawah ini
- Tekan tombol Beralih Platform .
Setelah Unity mengubah platform, tutup panel build.
Validasi penyetelan proyek
Lakukan langkah-langkah berikut untuk memvalidasi bahwa pengaturan proyek sudah benar.
Pilih entri ValidateProject dari menu RemoteRendering di toolbar editor Unity.
Tinjau jendela Validator Proyek untuk kesalahan dan perbaiki pengaturan proyek jika perlu.
Catatan
Jika Anda menggunakan MRTK dalam proyek dan mengaktifkan subsistem kamera, MRTK akan mengambil alih perubahan manual yang Anda terapkan ke kamera. Ini termasuk perbaikan dari alat ValidateProject.
Buat skrip untuk mengoordinasikan koneksi dan status Azure Remote Rendering
Ada empat tahap dasar untuk menampilkan model yang dirender dari jarak jauh, yang diuraikan dalam bagan alur di bawah ini. Setiap tahap harus dilakukan secara berkinerja. Langkah selanjutnya adalah membuat skrip yang mengelola status aplikasi dan melanjutkan setiap tahap yang diperlukan.
Di panel Proyek, di bawah Aset, buat folder baru yang disebut RemoteRenderingCore. Kemudian di dalam RemoteRenderingCore, buat folder lain yang disebut Scripts.
Buat skrip C# baru yang disebut RemoteRenderingCoordinator. Proyek Anda akan terlihat seperti ini:
Skrip koordinator ini melacak dan mengelola status penyajian jarak jauh. Sebagai catatan, beberapa kode ini digunakan untuk mempertahankan status, mengekspos fungsionalitas ke komponen lain, memicu peristiwa, dan menyimpan data khusus aplikasi yang tidak terkait langsung dengan Azure Remote Rendering. Gunakan kode di bawah ini sebagai titik awal, dan kami akan membahas dan mengimplementasikan kode Azure Remote Rendering tertentu nanti dalam tutorial.
Buka RemoteRenderingCoordinator di editor kode Anda dan ganti seluruh kontennya dengan kode di bawah ini:
// 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 System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
#if UNITY_WSA
using UnityEngine.XR.WSA;
#endif
/// <summary>
/// Remote Rendering Coordinator is the controller for all Remote Rendering operations.
/// </summary>
// Require the GameObject with a RemoteRenderingCoordinator to also have the ARRServiceUnity component
[RequireComponent(typeof(ARRServiceUnity))]
public class RemoteRenderingCoordinator : MonoBehaviour
{
public enum RemoteRenderingState
{
NotSet,
NotInitialized,
NotAuthorized,
NoSession,
ConnectingToExistingRemoteSession,
ConnectingToNewRemoteSession,
RemoteSessionReady,
ConnectingToRuntime,
RuntimeConnected
}
public static RemoteRenderingCoordinator instance;
// Account
// RemoteRenderingDomain must be '<region>.mixedreality.azure.com' - if no '<region>' is specified, connections will fail
// For most people '<region>' is either 'westus2' or 'westeurope'
[SerializeField]
private string remoteRenderingDomain = "westus2.mixedreality.azure.com";
public string RemoteRenderingDomain
{
get => remoteRenderingDomain.Trim();
set => remoteRenderingDomain = value;
}
[Header("Development Account Credentials")]
[SerializeField]
private string accountDomain = "<enter your account domain here>";
public string AccountDomain
{
get => accountDomain.Trim();
set => accountDomain = value;
}
[SerializeField]
private string accountId = "<enter your account id here>";
public string AccountId {
get => accountId.Trim();
set => accountId = value;
}
[SerializeField]
private string accountKey = "<enter your account key here>";
public string AccountKey {
get => accountKey.Trim();
set => accountKey = value;
}
// These settings are important. All three should be set as low as possible, while maintaining a good user experience
// See the documentation around session management and the technical differences in session VM size
[Header("New Session Defaults")]
public RenderingSessionVmSize renderingSessionVmSize = RenderingSessionVmSize.Standard;
public uint maxLeaseHours = 0;
public uint maxLeaseMinutes = 20;
[Header("Other Configuration")]
[Tooltip("If you have a known active SessionID, you can fill it in here before connecting")]
[SerializeField]
private string sessionIDOverride;
public string SessionIDOverride {
get => sessionIDOverride.Trim();
set => sessionIDOverride = value;
}
// When Automatic Mode is true, the coordinator will attempt to automatically proceed through the process of connecting and loading a model
public bool automaticMode = true;
public event Action RequestingAuthorization;
public UnityEvent OnRequestingAuthorization = new UnityEvent();
public event Action AuthorizedChanged;
public UnityEvent OnAuthorizationChanged = new UnityEvent();
private bool authorized;
public bool Authorized
{
get => authorized;
set
{
if (value == true) //This is a one-way value, once we're authorized it lasts until the app is shutdown.
{
authorized = value;
AuthorizedChanged?.Invoke();
}
}
}
public delegate Task<SessionConfiguration> AccountInfoGetter();
public static AccountInfoGetter ARRCredentialGetter
{
private get;
set;
}
private RemoteRenderingState currentCoordinatorState = RemoteRenderingState.NotSet;
public RemoteRenderingState CurrentCoordinatorState
{
get => currentCoordinatorState;
private set
{
if (currentCoordinatorState != value)
{
currentCoordinatorState = value;
Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, "{0}", $"State changed to: {currentCoordinatorState}");
CoordinatorStateChange?.Invoke(currentCoordinatorState);
}
}
}
public static event Action<RemoteRenderingState> CoordinatorStateChange;
public static RenderingSession CurrentSession => instance?.ARRSessionService?.CurrentActiveSession;
private ARRServiceUnity arrSessionService;
private ARRServiceUnity ARRSessionService
{
get
{
if (arrSessionService == null)
arrSessionService = GetComponent<ARRServiceUnity>();
return arrSessionService;
}
}
private async Task<SessionConfiguration> GetDevelopmentCredentials()
{
Debug.LogWarning("Using development credentials! Not recommended for production.");
return await Task.FromResult(new SessionConfiguration(AccountDomain, RemoteRenderingDomain, AccountId, AccountKey));
}
/// <summary>
/// Keep the last used SessionID, when launching, connect to this session if its available
/// </summary>
private string LastUsedSessionID
{
get
{
if (!string.IsNullOrEmpty(SessionIDOverride))
return SessionIDOverride;
if (PlayerPrefs.HasKey("LastUsedSessionID"))
return PlayerPrefs.GetString("LastUsedSessionID");
else
return null;
}
set
{
PlayerPrefs.SetString("LastUsedSessionID", value);
}
}
public void Awake()
{
//Forward events to Unity events
RequestingAuthorization += () => OnRequestingAuthorization?.Invoke();
AuthorizedChanged += () => OnAuthorizationChanged?.Invoke();
//Attach to event
AuthorizedChanged += RemoteRenderingCoordinator_AuthorizedChanged;
if (instance == null)
instance = this;
else
Destroy(this);
CoordinatorStateChange += AutomaticMode;
CurrentCoordinatorState = RemoteRenderingState.NotInitialized;
}
private void RemoteRenderingCoordinator_AuthorizedChanged()
{
if (CurrentCoordinatorState != RemoteRenderingState.NotAuthorized)
return; //This isn't valid from any other state than NotAuthorized
//We just became authorized to connect to Azure
InitializeSessionService();
}
/// <summary>
/// Automatic mode attempts to automatically progress through the connection and loading steps. Doesn't handle error states.
/// </summary>
/// <param name="currentState">The current state</param>
private async void AutomaticMode(RemoteRenderingState currentState)
{
if (!automaticMode)
return;
//Add a small delay for visual effect
await Task.Delay(1500);
switch (currentState)
{
case RemoteRenderingState.NotInitialized:
InitializeARR();
break;
case RemoteRenderingState.NotAuthorized:
RequestAuthorization();
break;
case RemoteRenderingState.NoSession:
JoinRemoteSession();
break;
case RemoteRenderingState.RemoteSessionReady:
ConnectRuntimeToRemoteSession();
break;
}
}
/// <summary>
/// Initializes ARR, associating the main camera
/// Note: This must be called on the main Unity thread
/// </summary>
public void InitializeARR()
{
//Implement me
}
/// <summary>
/// Create a new remote session manager
/// If the ARRCredentialGetter is set, use it as it, otherwise use the development credentials
/// </summary>
public async void InitializeSessionService()
{
//Implement me
}
/// <summary>
/// Trigger the event for checking authorization, respond to this event by prompting the user for authentication
/// If authorized, set Authorized = true
/// </summary>
public void RequestAuthorization()
{
RequestingAuthorization?.Invoke();
}
public void BypassAuthorization()
{
Authorized = true;
}
/// <summary>
/// Attempts to join an existing session or start a new session
/// </summary>
public async void JoinRemoteSession()
{
//Implement me
}
public async void StopRemoteSession()
{
//Implement me
}
private async Task<bool> IsSessionAvailable(string sessionID)
{
bool sessionAvailable = false;
try
{
RenderingSessionPropertiesArrayResult result = await ARRSessionService.Client.GetCurrentRenderingSessionsAsync();
if (result.ErrorCode == Result.Success)
{
RenderingSessionProperties[] properties = result.SessionProperties;
if (properties != null)
{
sessionAvailable = properties.Any(x => x.Id == sessionID && (x.Status == RenderingSessionStatus.Ready || x.Status == RenderingSessionStatus.Starting));
}
}
else
{
Debug.LogError($"Failed to get current rendering sessions. Error: {result.Context.ErrorMessage}");
}
}
catch (RRException ex)
{
Debug.LogError($"Failed to get current rendering sessions. Error: {ex.Message}");
}
return sessionAvailable;
}
/// <summary>
/// Connects the local runtime to the current active session, if there's a session available
/// </summary>
public async void ConnectRuntimeToRemoteSession()
{
//Implement me
}
public void DisconnectRuntimeFromRemoteSession()
{
//Implement me
}
/// <summary>
/// The session must have its runtime pump updated.
/// The Connection.Update() will push messages to the server, receive messages, and update the frame-buffer with the remotely rendered content.
/// </summary>
private void LateUpdate()
{
ARRSessionService?.CurrentActiveSession?.Connection?.Update();
}
/// <summary>
/// Loads a model into the remote session for rendering
/// </summary>
/// <param name="modelPath">The model's path</param>
/// <param name="progress">A call back method that accepts a float progress value [0->1]</param>
/// <param name="parent">The parent Transform for this remote entity</param>
/// <returns>An awaitable Remote Rendering Entity</returns>
public async Task<Entity> LoadModel(string modelPath, UnityEngine.Transform parent = null, Action<float> progress = null)
{
//Implement me
return null;
}
private async void OnRemoteSessionStatusChanged(ARRServiceUnity caller, RenderingSession session)
{
var properties = await session.GetPropertiesAsync();
switch (properties.SessionProperties.Status)
{
case RenderingSessionStatus.Error:
case RenderingSessionStatus.Expired:
case RenderingSessionStatus.Stopped:
case RenderingSessionStatus.Unknown:
CurrentCoordinatorState = RemoteRenderingState.NoSession;
break;
case RenderingSessionStatus.Starting:
CurrentCoordinatorState = RemoteRenderingState.ConnectingToNewRemoteSession;
break;
case RenderingSessionStatus.Ready:
CurrentCoordinatorState = RemoteRenderingState.RemoteSessionReady;
break;
}
}
private void OnLocalRuntimeStatusChanged(ConnectionStatus status, Result error)
{
switch (status)
{
case ConnectionStatus.Connected:
CurrentCoordinatorState = RemoteRenderingState.RuntimeConnected;
break;
case ConnectionStatus.Connecting:
CurrentCoordinatorState = RemoteRenderingState.ConnectingToRuntime;
break;
case ConnectionStatus.Disconnected:
CurrentCoordinatorState = RemoteRenderingState.RemoteSessionReady;
break;
}
}
}
Buat Azure Remote Rendering GameObject
Koordinator penyajian jarak jauh dan skrip yang diperlukan (ARRServiceUnity) adalah MonoBehaviours yang harus dilampirkan ke GameObject di tempat kejadian. Skrip ARRServiceUnity disediakan oleh ARR untuk mengekspos banyak fungsi ARR untuk menghubungkan dan mengelola sesi jarak jauh.
- Buat GameObject baru di adegan (Ctrl+Shift+N atau GameObject-Create> Empty) dan beri nama RemoteRenderingCoordinator.
- Tambahkan skrip RemoteRenderingCoordinator ke RemoteRenderingCoordinator GameObject.
- Konfirmasi skrip ARRServiceUnity, yang muncul sebagai Layanan di inspektur, secara otomatis ditambahkan ke GameObject. Jika Anda bertanya-tanya, ini adalah hasil yang ada
[RequireComponent(typeof(ARRServiceUnity))]
di bagian atas skrip RemoteRenderingCoordinator. - Tambahkan kredensial Azure Remote Rendering, Domain Akun Anda, dan Domain Remote Rendering ke skrip koordinator:
Inisiasikan Penyajian Azure Remote Rendering
Sekarang setelah kita memiliki kerangka kerja untuk koordinator kita, kita akan mengimplementasikan masing-masing dari empat tahap yang dimulai dengan Inisialisasi Remote Rendering.
Inisiasi memberi tahu Azure Remote Rendering objek kamera mana yang digunakan untuk menyajikan dan mengembangkan mesin status menjadi NotAuthorized. Status ini berarti diinisialisasi tetapi belum berwenang untuk menyambungkan ke sesi. Karena memulai sesi ARR dikenakan biaya, kami perlu mengonfirmasi bahwa pengguna ingin melanjutkan.
Ketika memasuki status NotAuthorized, CheckAuthorization disebut, yang memanggil peristiwa RequestingAuthorization dan menentukan informasi masuk akun mana yang akan digunakan (AccountInfo didefinisikan di dekat bagian atas kelas dan menggunakan informasi masuk yang Anda tentukan melalui Unity Inspector pada langkah di atas).
Catatan
Kompilasi ulang runtime tidak didukung oleh ARR. Memodifikasi skrip dan menyimpannya saat mode pemutaran aktif dapat mengakibatkan Unity membeku dan harus mematikan paksa melalui task manager. Selalu pastikan Anda telah menghentikan mode putar sebelum mengedit skrip.
Ganti kontenInitializeARR dan InitializeSessionService dengan kode lengkap di bawah ini:
/// <summary> /// Initializes ARR, associating the main camera /// Note: This must be called on the main Unity thread /// </summary> public void InitializeARR() { RemoteManagerUnity.InitializeManager(new RemoteUnityClientInit (Camera.main)); CurrentCoordinatorState = RemoteRenderingState.NotAuthorized; } /// <summary> /// Create a new remote session manager /// If the ARRCredentialGetter is set, use it as it, otherwise use the development credentials /// </summary> public async void InitializeSessionService() { if (ARRCredentialGetter == null) ARRCredentialGetter = GetDevelopmentCredentials; var sessionConfiguration = await ARRCredentialGetter.Invoke(); ARRSessionService.OnSessionStatusChanged += OnRemoteSessionStatusChanged; try { ARRSessionService.Initialize(sessionConfiguration); } catch (ArgumentException argumentException) { Debug.LogError(argumentException.Message); CurrentCoordinatorState = RemoteRenderingState. NotAuthorized; return; } CurrentCoordinatorState = RemoteRenderingState.NoSession; }
Untuk maju dari NotAuthorized ke NoSession, kami biasanya akan menyajikan dialog modal kepada pengguna sehingga mereka dapat memilih (dan kami melakukan hal itu di bab lain). Untuk saat ini, kami secara otomatis melewati pemeriksaan otorisasi dengan memanggil ByPassAuthentication segera setelah peristiwa RequestingAuthorization dipicu.
Pilih RemoteRenderingCoordinator GameObject dan temukan OnRequestingAuthorization Unity Event yang terekspos di inspektur komponen RemoteRenderingCoordinator.
Tambahkan peristiwa baru dengan menekan '+' di kanan bawah.
Seret komponen ke peristiwanya sendiri, untuk mereferensikan dirinya sendiri.
Di menu drop-down, pilih RemoteRenderingCoordinator -> BypassAuthorization.
Buat atau gabung dengan sesi jarak jauh
Tahap kedua adalah Membuat atau Menggabungkan Sesi Penyajian Jarak Jauh (untuk informasi selengkapnya tentang sesi penyajian, lihat Sesi Penyajian Jarak Jauh).
Sesi jarak jauh adalah lokasi penyajian model. Metode JoinRemoteSession( ) mencoba bergabung dengan sesi yang ada, dilacak dengan properti LastUsedSessionID atau jika ada ID sesi aktif yang ditetapkan pada SessionIDOverride. SessionIDOverride hanya ditujukan untuk debugging, itu hanya boleh digunakan ketika Anda tahu sesi itu ada dan ingin secara eksplisit terhubung ke sana.
Jika tidak ada sesi yang tersedia, sesi baru akan dibuat. Namun, membuat sesi baru adalah operasi yang memakan waktu. Oleh karena itu, Anda harus mencoba membuat sesi hanya jika diperlukan dan menggunakannya kembali jika memungkinkan (lihat Siap Komersial: Kumpulan sesi, penjadwalan, dan praktik terbaik untuk informasi lebih lanjut tentang mengelola sesi).
Tip
StopRemoteSession() akan mengakhiri sesi aktif. Untuk mencegah biaya yang tidak perlu, Anda harus selalu menghentikan sesi ketika mereka tidak lagi diperlukan.
Mesin status sekarang akan maju ke ConnectingToNewRemoteSession atau ConnectingToExistingRemoteSession, tergantung pada sesi yang tersedia. Keduanya membuka sesi yang ada atau membuat sesi baru memicu peristiwa ARRSessionService.OnSessionStatusChanged, menjalankan metode OnRemoteSessionStatusChanged kami. Idealnya, ini menghasilkan memajukan komputer status ke RemoteSessionReady.
- Untuk bergabung dengan sesi baru, ubah kode untuk mengganti metode JoinRemoteSession( ) dan StopRemoteSession( ) dengan contoh yang diselesaikan di bawah ini:
/// <summary>
/// Attempts to join an existing session or start a new session
/// </summary>
public async void JoinRemoteSession()
{
//If there's a session available that previously belonged to us, and it's ready, use it. Otherwise start a new session.
RenderingSessionProperties joinResult;
if (await IsSessionAvailable(LastUsedSessionID))
{
CurrentCoordinatorState = RemoteRenderingState.ConnectingToExistingRemoteSession;
joinResult = await ARRSessionService.OpenSession(LastUsedSessionID);
}
else
{
CurrentCoordinatorState = RemoteRenderingState.ConnectingToNewRemoteSession;
joinResult = await ARRSessionService.StartSession(new RenderingSessionCreationOptions(renderingSessionVmSize, (int)maxLeaseHours, (int)maxLeaseMinutes));
}
if (joinResult.Status == RenderingSessionStatus.Ready || joinResult.Status == RenderingSessionStatus.Starting)
{
LastUsedSessionID = joinResult.Id;
}
else
{
//The session should be ready or starting, if it's not, something went wrong
await ARRSessionService.StopSession();
if(LastUsedSessionID == SessionIDOverride)
SessionIDOverride = "";
CurrentCoordinatorState = RemoteRenderingState.NoSession;
}
}
public async void StopRemoteSession()
{
if (ARRSessionService.CurrentActiveSession != null)
{
await ARRSessionService.CurrentActiveSession.StopAsync();
}
}
Jika Anda ingin menghemat waktu dengan menggunakan kembali sesi, pastikan untuk menonaktifkan opsi Hentikan Otomatis Sesi di komponen ARRServiceUnity. Perlu diingat bahwa ini akan membuat sesi berjalan, bahkan ketika tidak ada yang terhubung dengan mereka. Sesi Anda dapat berjalan selama MaxLeaseTime belum dimatikan oleh server (Nilai untuk MaxLeaseTime dapat dimodifikasi di Koordinator Azure Remote Rendering, di bawah Default Sesi Baru). Di sisi lain, jika Anda secara otomatis mematikan setiap sesi saat memutuskan sambungan, Anda harus menunggu sesi baru dimulai setiap saat, yang bisa menjadi proses yang panjang.
Catatan
Menghentikan sesi akan berlaku segera dan tidak dapat dibatalkan. Setelah berhenti, Anda harus membuat sesi baru, dengan overhead startup yang sama.
Sambungkan runtime bahasa umum lokal ke sesi jarak jauh
Selanjutnya, aplikasi perlu menghubungkan runtime bahasa umum lokalnya ke sesi jarak jauh.
Aplikasi ini juga perlu mendengarkan acara tentang koneksi antara runtime bahasa umum dan sesi saat ini; perubahan status tersebut ditangani dalam OnLocalRuntimeStatusChanged. Kode ini memajukan status kita ke Koneksi ingToRuntime. Setelah tersambung di OnLocalRuntimeStatusChanged, status maju ke Runtime Koneksi ed. Menghubungkan ke runtime bahasa umum adalah status terakhir yang menjadi perhatian koordinator itu sendiri, yang berarti aplikasi dilakukan dengan semua konfigurasi umum dan siap untuk memulai pekerjaan spesifik sesi memuat dan merender model.
- Ganti metode ConnectRuntimeToRemoteSession( ) dan DisconnectRuntimeFromRemoteSession() dengan versi lengkap di bawah ini.
- Penting untuk mencatat metode Unity LateUpdate dan memperbarui sesi aktif saat ini. Ini memungkinkan sesi saat ini untuk mengirim/menerima pesan dan memperbarui buffer bingkai dengan bingkai yang diterima dari sesi jarak jauh. Sangat penting bagi ARR berfungsi dengan benar.
/// <summary>
/// Connects the local runtime to the current active session, if there's a session available
/// </summary>
public async void ConnectRuntimeToRemoteSession()
{
if (ARRSessionService == null || ARRSessionService.CurrentActiveSession == null)
{
Debug.LogError("Not ready to connect runtime");
return;
}
// Connect the local runtime to the currently connected session
// This session is set when connecting to a new or existing session
ARRSessionService.CurrentActiveSession.ConnectionStatusChanged += OnLocalRuntimeStatusChanged;
await ARRSessionService.CurrentActiveSession.ConnectAsync(new RendererInitOptions());
}
public void DisconnectRuntimeFromRemoteSession()
{
if (ARRSessionService == null || ARRSessionService.CurrentActiveSession == null || ARRSessionService.CurrentActiveSession.ConnectionStatus != ConnectionStatus.Connected)
{
Debug.LogError("Runtime not connected!");
return;
}
ARRSessionService.CurrentActiveSession.Disconnect();
ARRSessionService.CurrentActiveSession.ConnectionStatusChanged -= OnLocalRuntimeStatusChanged;
CurrentCoordinatorState = RemoteRenderingState.RemoteSessionReady;
}
Catatan
Menyambungkan runtime bahasa umum lokal ke sesi jarak jauh bergantung pada Pembaruan yang dipanggil pada sesi yang saat ini aktif. Jika merasa aplikasi Anda tidak pernah mengalami kemajuan melewati status ConnectingToRuntime, pastikan Anda memanggil Pembaruan secara teratur pada sesi aktif.
Memuat model
Dengan fondasi yang diperlukan, Anda siap untuk memuat model ke dalam sesi jarak jauh dan mulai menerima bingkai.
Metode LoadModel dirancang untuk menerima jalur model, progress handler, dan transformasi induk. Argumen ini digunakan untuk memuat model ke sesi jarak jauh, memperbarui pengguna pada kemajuan pemuatan, dan mengorientasikan model yang dirender dari jarak jauh berdasarkan transformasi induk.
Ganti metode LoadModel sepenuhnya dengan kode di bawah ini:
/// <summary> /// Loads a model into the remote session for rendering /// </summary> /// <param name="modelName">The model's path</param> /// <param name="parent">The parent Transform for this remote entity</param> /// <param name="progress">A call back method that accepts a float progress value [0->1]</param> /// <returns>An awaitable Remote Rendering Entity</returns> public async Task<Entity> LoadModel(string modelPath, UnityEngine.Transform parent = null, Action<float> progress = null) { //Create a root object to parent a loaded model to var modelEntity = ARRSessionService.CurrentActiveSession.Connection.CreateEntity(); //Get the game object representation of this entity var modelGameObject = modelEntity.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents); //Ensure the entity will sync its transform with the server var sync = modelGameObject.GetComponent<RemoteEntitySyncObject>(); sync.SyncEveryFrame = true; //Parent the new object under the defined parent if (parent != null) { modelGameObject.transform.SetParent(parent, false); modelGameObject.name = parent.name + "_Entity"; } //Load a model that will be parented to the entity var loadModelParams = new LoadModelFromSasOptions(modelPath, modelEntity); var loadModelAsync = ARRSessionService.CurrentActiveSession.Connection.LoadModelFromSasAsync(loadModelParams, progress); var result = await loadModelAsync; return modelEntity; }
Kode di atas melakukan langkah-langkah berikut:
- Buat Entitas Jarak Jauh.
- Buat GameObject lokal untuk mewakili entitas jarak jauh.
- Konfigurasikan GameObject lokal untuk menyinkronkan statusnya (yaitu Transformasi) ke entitas jarak jauh setiap bingkai.
- Muat data model dari Azure Blob Storage ke entitas jarak jauh.
- Kembalikan Entitas induk untuk referensi nanti.
Tampilkan model pengujian
Kami sekarang memiliki semua kode yang diperlukan untuk melihat model yang dirender dari jarak jauh, keempat tahap yang diperlukan untuk penyajian jarak jauh selesai. Sekarang kita perlu menambahkan sedikit kode untuk memulai proses beban model.
Menambahkan kode berikut ke kelas RemoteRenderingCoordinator, tepat di bawah metode LoadModel tidak masalah:
private bool loadingTestModel = false; [ContextMenu("Load Test Model")] public async void LoadTestModel() { if(CurrentCoordinatorState != RemoteRenderingState.RuntimeConnected) { Debug.LogError("Please wait for the runtime to connect before loading the test model. Try again later."); return; } if(loadingTestModel) { Debug.Log("Test model already loading or loaded!"); return; } loadingTestModel = true; // Create a parent object to use for positioning GameObject testParent = new GameObject("TestModelParent"); testParent.transform.position = new Vector3(0f, 0f, 3f); // The 'built in engine path' is a special path that references a test model built into Azure Remote Rendering. await LoadModel("builtin://Engine", testParent.transform, (progressValue) => Debug.Log($"Loading Test Model progress: {Math.Round(progressValue * 100, 2)}%")); }
Kode ini membuat GameObject untuk bertindak sebagai induk model pengujian. Kemudian memanggil metode LoadModel untuk memuat model "builtin://Engine", yang merupakan aset yang dibangun ke dalam Azure Remote Rendering untuk tujuan pengujian penyajian.
Simpan kode Anda.
Tekan tombol Putar di Editor Unity untuk memulai proses menyambungkan ke Azure Remote Rendering dan membuat sesi baru.
Namun, Anda tidak akan melihat banyak dalam tampilan Game, Konsol menunjukkan status perubahan aplikasi. Kemungkinan akan maju ke
ConnectingToNewRemoteSession
, dan tetap di sana, mungkin hingga lima menit.Pilih RemoteRenderingCoordinator GameObject untuk melihat skrip terlampirnya di inspektur. Tonton pembaruan komponenLayanan karena pembaruannya berlangsung melalui langkah-langkah inisiasi dan koneksinya.
Pantau output Konsol - menunggu status berubah menjadi RuntimeConnected.
Setelah runtime terhubung, klik kanan pada RemoteRenderingCoordinator di inspektur untuk mengekspos menu konteks. Kemudian, pilih opsi Muat Model Uji di menu konteks, ditambahkan oleh
[ContextMenu("Load Test Model")]
bagian dari kode kami di atas.Tonton Konsol untuk output ProgressHandler yang kami lewati ke metode LoadModel.
Lihat model yang dirender dari jarak jauh!
Catatan
Model jarak jauh tidak akan pernah terlihat dalam tampilan Scene, hanya dalam tampilan game. Ini karena ARR menyajikan bingkai dari jarak jauh khusus untuk perspektif kamera tampilan Game dan tidak mengetahui kamera Editor (digunakan untuk menyajikan tampilan Scene).
Langkah berikutnya
Selamat! Anda telah membuat aplikasi dasar yang mampu menampilkan model yang dirender dari jarak jauh menggunakan Azure Remote Rendering. Dalam tutorial berikutnya, kita akan mengintegrasikan MRTK dan mengimpor model kita sendiri.