Självstudie: Visa en fjärrre renderad modell
I den här guiden får du lära dig att:
- Etablera en Azure Remote Rendering (ARR)-instans
- Skapa och stoppa en renderingssession
- Återanvända en befintlig renderingssession
- Ansluta och koppla från sessioner
- Läsa in modeller i en renderingssession
Förutsättningar
För den här självstudien behöver du:
- En aktiv Azure-prenumeration med användningsbaserade betalning Skapa ett konto
- Windows SDK 10.0.18362.0 (ladda ned)
- Den senaste versionen av Visual Studio 2019 (ladda ned)
- GIT (ladda ned)
- Unity (se systemkrav för versioner som stöds)
- Kunskap på medelnivå om Unity och C#-språket (till exempel att skapa skript och objekt, använda prefabs, konfigurera Unity-händelser osv.)
Etablera en Azure Remote Rendering (ARR)-instans
För att få åtkomst Azure Remote Rendering-tjänsten måste du först skapa ett konto.
Skapa ett nytt Unity-projekt
Tips
Lagringsplatsen FÖR ARR-exempel innehåller ett projekt där alla självstudier har slutförts. Den kan användas som referens. Titta i Unity\Tutorial-Complete för det fullständiga Unity-projektet.
Skapa ett nytt projekt från Unity Hub. I det här exemplet antar vi att projektet skapas i en mapp med namnet RemoteRendering.
Inkludera Azure Remote Rendering paket
Följ instruktionerna för hur du lägger till Azure Remote Rendering-paketet i ett Unity-projekt.
Konfigurera kameran
Välj noden Huvudkamera.
Öppna snabbmenyn genom att högerklicka på komponenten Transformera och välja alternativet Återställ:

Ange Rensa flaggor till Solid Color
Ange Bakgrund till Svart (#000000), med helt transparent (0) alfa (A)

Ange Cklippningsplan till Nära = 0,3 och Långt = 20. Det innebär att återgivningen kommer att fästa geometri som är närmare än 30 cm eller längre än 20 meter.

Justera projektinställningarna
Öppna Redigera > projektinställningar...
Välj Kvalitet på den vänstra listmenyn
Ändra Standardkvalitetsnivå för alla plattformar till Låg. Den här inställningen aktiverar effektivare återgivning av lokalt innehåll och påverkar inte kvaliteten på fjärrre renderat innehåll.

Välj Grafik på den vänstra listmenyn
Ändra inställningen Skriptbar renderingspipeline till HybridRenderingPipeline.

Ibland fyller inte användargränssnittet i listan över tillgängliga pipelinetyper från paketen. Om detta inträffar måste tillgången HybridRenderingPipeline dras till fältet manuellt:

Anteckning
Om du inte kan dra och släppa HybridRenderingPipeline-tillgången till fältet Render Pipeline Asset (eventuellt eftersom fältet inte finns!) ser du till att paketkonfigurationen innehåller
com.unity.render-pipelines.universalpaketet.Välj Player på den vänstra listmenyn
Välj fliken Universell Windows-plattform inställningar, som visas som en Windows-ikon.
Ändra XR-inställningarna så att de Windows Mixed Reality som visas nedan:
- Aktivera virtuell verklighet som stöds
- Tryck på knappen "+" och lägg till Windows Mixed Reality
- Ange djupformat till 16-bitars djup
- Se till att djupbuffertdelning är aktiverat
- Ställ in Stereorenderingsläge på Enkelinstans

I samma fönster, ovanför XR-inställningar, expanderar du Publiceringsinställningar
Rulla ned till Funktioner och välj:
- InternetClient
- InternetClientServer
- SpatialPerception
- PrivateNetworkClientServer (valfritt). Välj det här alternativet om du vill ansluta Unity-fjärrfelsökaren till din enhet.
Under Enhetsfamiljer som stöds aktiverar du Holographic och Desktop
Stäng eller docka panelen Projektinställningar
Öppna inställningar för >-version
Välj Universell Windows-plattform
Konfigurera inställningarna så att de matchar dem som finns nedan
Tryck på knappen Växla plattform.

När Unity har byter plattform stänger du byggpanelen.
Verifiera projektkonfigurationen
Utför följande steg för att verifiera att projektinställningarna är korrekta.
Välj posten ValidateProject på menyn RemoteRendering i verktygsfältet i Unity-redigeraren.
Granska fönstret ValidateProject för att se om det finns fel och åtgärda projektinställningarna vid behov.

Anteckning
Om du använder MRTK i projektet och aktiverar kameraundersystemet åsidosätter MRTK manuella ändringar som du tillämpar på kameran. Detta inkluderar korrigeringar från verktyget ValidateProject.
Skapa ett skript för att samordna Azure Remote Rendering anslutning och tillstånd
Det finns fyra grundläggande steg för att visa fjärrre renderade modeller, som beskrivs i flödesschemat nedan. Varje fas måste utföras i ordning. Nästa steg är att skapa ett skript som hanterar programtillståndet och fortsätter genom varje obligatorisk fas.

I fönstret Projekt, under Tillgångar, skapar du en ny mapp med namnet RemoteRenderingCore. I RemoteRenderingCore skapar du sedan en annan mapp med namnet Skript.
Skapa ett nytt C#-skript med namnet RemoteRenderingCoordinator. Projektet bör se ut så här:

Det här koordinatorskriptet spårar och hanterar fjärrrenderingstillståndet. Observera att en del av den här koden används för att upprätthålla tillstånd, exponera funktioner för andra komponenter, utlösa händelser och lagra programspecifika data som inte är direkt relaterade till Azure Remote Rendering. Använd koden nedan som utgångspunkt så tar vi upp och implementerar den specifika Azure Remote Rendering kod senare i självstudien.
Öppna RemoteRenderingCoordinator i kodredigeraren och ersätt hela innehållet med koden nedan:
// 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 accountId = "<enter your account id here>";
public string AccountId {
get => accountId.Trim();
set => accountId = value;
}
[SerializeField]
private string accountDomain = "<enter your account domain here>";
public string AccountDomain
{
get => accountDomain.Trim();
set => accountDomain = 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 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 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, 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;
}
}
}
Skapa Azure Remote Rendering GameObject
Koordinatorn för fjärråtergivning och dess nödvändiga skript (ARRServiceUnity) är båda MonoBehaviours som måste kopplas till ett GameObject i scenen. ARRServiceUnity-skriptet tillhandahålls av ARR för att exponera en stor del av ARR:s funktioner för att ansluta till och hantera fjärrsessioner.
- Skapa ett nytt GameObject i scenen (Ctrl + Skift + N eller GameObject->Skapa tom) och ge den namnet RemoteRenderingCoordinator.
- Lägg till skriptet RemoteRenderingCoordinator i RemoteRenderingCoordinator GameObject.

- Bekräfta att ARRServiceUnity-skriptet, som visas som Tjänst i kontroll, läggs automatiskt till i GameObject. Om du undrar är det här ett resultat som
[RequireComponent(typeof(ARRServiceUnity))]finns överst i skriptet RemoteRenderingCoordinator. - Lägg till Azure Remote Rendering autentiseringsuppgifter, din kontodomän och Remote Rendering domän i koordinatorskriptet:

Initiera Azure Remote Rendering
Nu när vi har ramverket för vår koordinator implementerar vi var och en av de fyra stegen som börjar med Remote Rendering.

Initiera talar Azure Remote Rendering vilket kameraobjekt som ska användas för rendering och förlopp för tillståndsdatorn till NotAuthorized. Det innebär att den har initierats men ännu inte har behörighet att ansluta till en session. Eftersom det medför en kostnad att starta en ARR-session måste vi bekräfta att användaren vill fortsätta.
När du anger tillståndet NotAuthorized anropas CheckAuthorization, som anropar händelsen RequestingAuthorization och avgör vilka kontoautentiseringsuppgifter som ska användas (AccountInfo definieras längst upp i klassen och använder de autentiseringsuppgifter som du definierade via Unity Inspector i steget ovan).
Anteckning
Omkompilering av körning stöds inte av ARR. Om du ändrar skriptet och sparar det medan uppspelningsläget är aktivt kan det leda till att Unity fryser och att aktivitetshanteraren måste stängas av. Se alltid till att du har stoppat uppspelningsläget innan du redigerar skripten.
- Ersätt innehållet i InitializeARR och InitializeSessionService med den färdiga koden nedan:
/// <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)
{
NotificationBar.Message("InitializeSessionService failed: SessionConfiguration is invalid.");
Debug.LogError(argumentException.Message);
CurrentCoordinatorState = RemoteRenderingState.NotAuthorized;
return;
}
CurrentCoordinatorState = RemoteRenderingState.NoSession;
}
För att kunna gå från NotAuthorized till NoSession presenterar vi vanligtvis en modal dialogruta för användaren så att de kan välja (och vi gör just det i ett annat kapitel). För tillfället kringgår vi automatiskt auktoriseringskontrollen genom att anropa ByPassAuthentication så snart händelsen RequestingAuthorization utlöses.
Välj RemoteRenderingCoordinator GameObject och leta upp Unity-händelsen OnRequestingAuthorization som visas i Kontroll för komponenten RemoteRenderingCoordinator.
Lägg till en ny händelse genom att trycka på "+" i det nedre högra högra.
Dra komponenten till en egen händelse så att den refererar till sig själv.
\I listrutan väljer du RemoteRenderingCoordinator -> BypassAuthorization.

Skapa eller ansluta till en fjärrsession
Det andra steget är att skapa eller ansluta till en Remote Rendering-session (se Remote Rendering sessioner för mer information).

Fjärrsessionen är den plats där modellerna återges. Metoden JoinRemoteSession( ) försöker ansluta till en befintlig session, spåras med egenskapen LastUsedSessionID eller om det finns ett tilldelat aktivt sessions-ID på SessionIDOverride. SessionIDOverride är endast avsett för felsökning. Det bör endast användas när du vet att sessionen finns och vill ansluta till den explicit.
Om inga sessioner är tillgängliga skapas en ny session. Att skapa en ny session är dock en tidskrävande åtgärd. Därför bör du försöka skapa sessioner endast när det behövs och återanvända dem när det är möjligt (mer information om hur du hanterar sessioner finns i Commercial Ready: Sessionspooling, schemaläggning och metodtips).
Tips
StopRemoteSession() avslutar den aktiva sessionen. För att undvika onödiga avgifter bör du alltid stoppa sessioner när de inte längre behövs.
Tillståndsdatorn fortsätter nu till antingen ConnectingToNewRemoteSession eller ConnectingToExistingRemoteSession, beroende på tillgängliga sessioner. Om du öppnar en befintlig session eller skapar en ny session utlöses händelsen ARRSessionService.OnSessionStatusChanged, vilket kör vår OnRemoteSessionStatusChanged-metod. Vi rekommenderar att detta leder till att tillståndsdatorn avancerar till RemoteSessionReady.
- Om du vill ansluta till en ny session ändrar du koden för att ersätta metoderna JoinRemoteSession( ) och StopRemoteSession( ) med de ifyllda exemplen nedan:
/// <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 void StopRemoteSession()
{
if (ARRSessionService.CurrentActiveSession != null)
{
ARRSessionService.CurrentActiveSession.StopAsync();
}
}
Om du vill spara tid genom att återanvända sessioner ska du inaktivera alternativet Stoppa session automatiskt i ARRServiceUnity-komponenten. Tänk på att detta gör att sessioner körs även när ingen är ansluten till dem. Sessionen kan köras så länge som MaxLeaseTime innan den stängs av av servern (värdet för MaxLeaseTime kan ändras i Remote Rendering Coordinator under New Session Defaults(Standard för ny session). Å andra sidan, om du automatiskt stänger av varje session när du kopplar från, måste du vänta tills en ny session startas varje gång, vilket kan vara en något längre process.
Anteckning
Att stoppa en session börjar gälla omedelbart och kan inte ångras. När den har stoppats måste du skapa en ny session med samma startkostnader.
Ansluta den lokala körningen till fjärrsessionen
Därefter måste programmet ansluta sin lokala körning till fjärrsessionen.

Programmet måste också lyssna efter händelser om anslutningen mellan körningen och den aktuella sessionen. dessa tillståndsändringar hanteras i OnLocalRuntimeStatusChanged. Den här koden förs vidare till ConnectingToRuntime. När du har anslutit i OnLocalRuntimeStatusChanged fortsätter tillståndet till RuntimeConnected. Att ansluta till körningen är det sista tillstånd som koordinatorn är bekymrad över, vilket innebär att programmet är gjort med all gemensam konfiguration och är redo att påbörja sessionsspecifikt arbete med att läsa in och återge modeller.
- Ersätt metoderna ConnectRuntimeToRemoteSession( ) och DisconnectRuntimeFromRemoteSession( ) med de slutförda versionerna nedan.
- Det är viktigt att notera Unity-metoden LateUpdate och att den uppdaterar den aktuella aktiva sessionen. På så sätt kan den aktuella sessionen skicka/ta emot meddelanden och uppdatera rambufferten med bildrutorna som tagits emot från fjärrsessionen. Det är viktigt att ARR fungerar korrekt.
/// <summary>
/// Connects the local runtime to the current active session, if there's a session available
/// </summary>
public 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;
ARRSessionService.CurrentActiveSession.ConnectAsync(new RendererInitOptions());
CurrentCoordinatorState = RemoteRenderingState.ConnectingToRuntime;
}
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;
}
/// <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();
}
Anteckning
Anslutningen av den lokala körningen till en fjärrsession beror på att Uppdateringen anropas på den aktiva sessionen. Om du upptäcker att programmet aldrig går förbi tillståndet ConnectingToRuntime kontrollerar du att du anropar Uppdatera regelbundet på den aktiva sessionen.
Läsa in en modell
Med den nödvändiga grunden på plats är du redo att läsa in en modell i fjärrsessionen och börja ta emot bildrutor.

Metoden LoadModel är utformad för att acceptera en modellsökväg, förloppshanterare och överordnad transformering. Dessa argument används för att läsa in en modell i fjärrsessionen, uppdatera användaren om inläsningsförloppet och orientera den fjärrregivna modellen baserat på den överordnade transformeringen.
Ersätt metoden LoadModel helt med koden nedan:
/// <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, 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; }
Koden ovan utför följande steg:
- Skapa en fjärrentitet.
- Skapa ett lokalt GameObject som representerar fjärrentiteten.
- Konfigurera det lokala GameObject att synkronisera dess tillstånd (dvs. Transformera) till fjärrentiteten varje bildruta.
- Läs in modelldata från Blob Storage till fjärrentiteten.
- Returnera den överordnade entiteten för senare referens.
Visa testmodellen
Nu har vi all kod som krävs för att visa en fjärrre renderad modell. Alla fyra av de nödvändiga stegen för fjärrrendering är klara. Nu måste vi lägga till lite kod för att starta modellbelastningsprocessen.

Lägg till följande kod i klassen RemoteRenderingCoordinator, precis under metoden LoadModel:
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)}%")); }Den här koden skapar ett GameObject som fungerar som överordnat till testmodellen. Sedan anropas metoden LoadModel för att läsa in modellen "builtin://Engine", vilket är en tillgång som är inbyggd i Azure Remote Rendering för att testa renderingen.
Spara koden.
Tryck på knappen Spela upp i Unity Editor för att starta processen med att ansluta Azure Remote Rendering skapa en ny session.
Du kommer inte att se så mycket i spelvyn, men konsolen visar programmets status som ändras. Den kommer troligen att
ConnectingToNewRemoteSessiongå vidare till och stanna kvar där, möjligen i upp till fem minuter.Välj RemoteRenderingCoordinator GameObject för att se dess anslutna skript i kontrollanten. Se hur tjänstkomponenten uppdateras allt eftersom den går igenom stegen för initiering och anslutning.
Övervaka konsolens utdata – väntar på att tillståndet ska ändras till RuntimeAnsluten.
När körningen är ansluten högerklickar du på RemoteRenderingCoordinator i kontrollanten för att visa snabbmenyn. Klicka sedan på alternativet Load Test Model (Belastningstestmodell) på snabbmenyn, som lagts till av delen i koden
[ContextMenu("Load Test Model")]ovan.
Titta på konsolen för utdata från ProgressHandler som vi skickade till metoden LoadModel.
Se den fjärrre renderade modellen!
Anteckning
Fjärrmodellen visas aldrig i scenvyn, endast i spelvyn. Det beror på att ARR fjärrreenderar bildrutorna specifikt för kameran i spelvyn och inte känner till redigerarens kamera (används för att återge scenvyn).
Nästa steg

Grattis! Du har skapat ett grundläggande program som kan visa fjärrregivna modeller med hjälp av Azure Remote Rendering. I nästa självstudie integrerar vi MRTK och importerar våra egna modeller.