Öğretici: uzaktan işlenmiş bir modeli görüntüleme

Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:

  • Azure uzaktan Işleme (ARR) örneği sağlama
  • İşleme oturumu oluşturma ve durdurma
  • Mevcut bir işleme oturumunu yeniden kullanma
  • Oturumlara bağlanma ve bağlantıyı kesme
  • Modelleri bir işleme oturumuna yükleme

Önkoşullar

Bu öğreticide şunlar gerekir:

  • Etkin bir Kullandıkça Öde Azure aboneliği Hesap oluşturma
  • Windows SDK 10.0.18362.0 (İndir)
  • Visual Studio 2019 ' un en son sürümü (indirme)
  • GIT (İndir)
  • Unity (desteklenen sürümler için sistem gereksinimlerine bakın)
  • Unity ve C# dilinin ara bilgisi (örneğin: komut dosyaları ve nesneler oluşturma, Prefabs kullanma, Unity olaylarını yapılandırma vb.)

Azure uzaktan Işleme (ARR) örneği sağlama

Azure uzaktan Işleme hizmetine erişim sağlamak için önce bir hesap oluşturmanızgerekir.

Yeni Unity projesi oluşturma

İpucu

ARR örnekleri deposu , tüm öğreticilerin tamamlandığı bir proje içerir, başvuru olarak kullanılabilir. Tüm Unity projesi için Unity\Tutorial-Complete bakın.

Unity hub 'ında yeni bir proje oluşturun. Bu örnekte, projenin RemoteRendering adlı bir klasörde oluşturulduğunu varsayacağız.

Yeni Unity projesi

Azure uzaktan Işleme paketini dahil et

Azure uzaktan Işleme paketini bir Unity projesine ekleme yönergelerini izleyin .

Kamerayı yapılandırma

  1. Ana kamera düğümünü seçin.

  2. Dönüştür bileşenine sağ tıklayarak bağlam menüsünü açın ve sıfırlama seçeneğini belirleyin:

    Kamera dönüşümünü Sıfırla

  3. Clear bayraklarını düz renge ayarla

  4. Tamamen saydam (0) Alfa (A) ile arka planı siyaha (#000000) ayarlayın

    Renk tekerleği

  5. Kırpma düzlemleri Near = 0,3 ve Far = 20 olarak ayarlayın. Bu, işlemenin 30 cm 'den daha yakın veya 20 ölçümden daha büyük olan bir geometriyi kırpmak anlamına gelir.

    Unity kamera özellikleri

Proje ayarlarını ayarla

  1. > proje ayarlarını Düzenle 'yi aç...

  2. Sol taraftaki liste menüsünden kalite ' yi seçin

  3. Tüm platformların Varsayılan kalite düzeyini düşük olarak değiştirin. Bu ayar, yerel içeriğin daha verimli işlemesini etkinleştirir ve uzaktan işlenmiş içeriğin kalitesini etkilemez.

    Proje kalitesi ayarlarını değiştir

  4. Sol liste menüsünden grafik seçin

  5. Komut dosyası oluşturma Işlem hattı ayarını Hybridrenderingpipeline. \ olarak değiştirin Komut dosyası oluşturma işlem hattı ayarını HybridRenderingPipeline olarak değiştirdiğiniz yere işaret eden ekran görüntüsü.
    Bazen kullanıcı arabirimi kullanılabilir işlem hattı türleri listesini paketlerden doldurmaz. Bu durum oluşursa Hybridrenderingpipeline varlığı alana el ile sürüklenmesi gerekir:
    Proje grafik ayarlarını değiştirme

    Not

    Hybridrenderingpipeline varlığını, Işleme ardışık düzen varlık alanına sürükleyip bırakamazsınız (Belki de alan mevcut olmadığından), paket yapılandırmanızın paketi içerdiğinden emin olun com.unity.render-pipelines.universal .

  6. Sol taraftaki liste menüsünden oynatıcı ' yı seçin

  7. Windows simgesi olarak temsil edilen Evrensel Windows platformu ayarları sekmesini seçin.

  8. XR ayarlarını aşağıda gösterildiği gibi Windows Mixed Reality 'yi destekleyecek şekilde değiştirin:

    1. Sanal Reality 'Yi etkinleştirme destekleniyor
    2. ' + ' Düğmesine basın ve Windows Mixed Reality 'yi ekleyin
    3. Derinlik biçimini 16 bit derinliğe ayarla
    4. Derinlik arabelleği paylaşımının etkinleştirildiğinden emin olun
    5. Stereo Işleme modunu tek bir geçiş için ayarla

    Oynatıcı ayarları

  9. Aynı pencerede, XR ayarları' nda, Yayımlama ayarları ' nı genişletin.

  10. Özellikleri aşağı kaydırın ve şunları seçin:

    • InternetClient
    • InternetClientServer
    • SpatialPerception
    • PrivateNetworkClientServer (isteğe bağlı). Unity uzaktan hata ayıklayıcısını cihazınıza bağlamak istiyorsanız bu seçeneği belirleyin.
  11. Desteklenen cihaz aileleri altında holographic ve Desktop 'ı etkinleştirin

  12. Proje ayarları panelini kapatma veya yerleştirme

  13. Dosya >derleme ayarlarını

  14. Evrensel Windows platformu seçin

  15. Ayarlarınızı aşağıda bulunanlarla eşleşecek şekilde yapılandırın

  16. Platformu Değiştir düğmesine basın.
    derleme ayarları

  17. Unity değişikliklerinden sonra, yapı panelini kapatın.

Proje kurulumunu doğrula

Proje ayarlarının doğru olduğunu doğrulamak için aşağıdaki adımları gerçekleştirin.

  1. Unity Düzenleyicisi araç çubuğundaki RemoteRendering menüsünden validateproject girişini seçin.

  2. Hatalar için Validateproject penceresini gözden geçirin ve gerektiğinde proje ayarlarını onarın.

    Unity Düzenleyicisi proje doğrulaması

Not

Projenizde MRTK kullanıyorsanız ve kamera alt sistemini etkinleştirirseniz, MRTK, kameraya uyguladığınız el ile yapılan değişiklikleri geçersiz kılar. Bu, ValidateProject aracından düzeltmeleri içerir.

Azure uzaktan Işleme bağlantısını ve durumunu koordine etmek için bir betik oluşturun

Aşağıdaki akış çizelgesinde özetlenen, uzaktan işlenmiş modelleri göstermek için dört temel aşama vardır. Her aşama sırasıyla gerçekleştirilmelidir. Sonraki adım, uygulama durumunu yönetecek ve gereken her aşamada devam edecek bir komut dosyası oluşturmaktır.

ARR yığını 0

  1. Proje bölmesinde, varlıklar altında, remoterenderingcore adlı yeni bir klasör oluşturun. Ardından, Remoterenderingcore içinde betikler adlı başka bir klasör oluşturun.

  2. Remoterenderingcoordinator adlı Yeni bir C# betiği oluşturun. Projeniz şuna benzemelidir:

    Proje hiyerarşisi

    Bu düzenleyici betiği uzaktan işleme durumunu izleyip yönetecektir. Not, bu kodun bir kısmı durumu korumak, diğer bileşenlere işlevsellik göstermek, olayları tetiklemek ve doğrudan Azure uzaktan işleme ile ilişkili olmayan uygulamaya özgü verileri depolamak için kullanılır. Aşağıdaki kodu bir başlangıç noktası olarak kullanın ve öğreticide daha sonra belirli Azure uzaktan Işleme kodunu adresleyeceğiz ve uygulayacağız.

  3. Kod Düzenleyicinizde Remoterenderingcoordinator ' yı açın ve tüm içeriğini aşağıdaki kodla değiştirin:

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

Azure uzaktan Işleme Oyunnesnesi oluşturma

Uzaktan işleme Düzenleyicisi ve gerekli betiği (ARRServiceUnity), sahnedeki bir gameobject 'e eklenmesi gereken MonoBehaviours. ARRServiceUnity betiği ARR tarafından, uzak oturumlara bağlanmak ve bunları yönetmek için ARR 'nin işlevselliğinin çoğunu göstermek üzere sağlanır.

  1. Sahnede yeni bir Oyunobject oluşturun (CTRL + SHIFT + N veya gameobject->boş oluştur) ve bunu Remoterenderingcoordinator olarak adlandırın.
  2. Remoterenderingcoordinator oyunobject . \ dosyasına RemoteRenderingCoordinator bileşeni ekleme
  3. Denetçide Hizmet olarak görünen ARRServiceUnity betiğinin GameObject'e otomatik olarak eklendiği onaylayın. Merak ediyorsanız bu, [RequireComponent(typeof(ARRServiceUnity))] RemoteRenderingCoordinator betiğinde en üst sırada yer alan bir sonuçtur.
  4. Düzenleyici kimlik Azure Remote Rendering, Hesap Etki Alanınız ve Remote Rendering Etki Alanı'nızı düzenleyici betiğine ekleyin:
    Kimlik bilgilerinizi ekleme

Initialize Azure Remote Rendering

Artık koordinatörümüz için çerçevemiz olduğundan, Initialize Remote Rendering ile başlayan dört aşamanın her Remote Rendering.

ARR yığını 1

Başlat, Azure Remote Rendering için hangi kamera nesnesinin kullanılamadı lı olduğunu söyler ve durum makinesini NotAuthorized durumuna ilerler. Bu, başlatılmış ancak henüz oturuma bağlanmak için yetkilendirilmedi anlamına gelir. Bir ARR oturumu başlatmanın bir maliyeti olduğu için, kullanıcının devam etmek istediğini onaylamamız gerekir.

NotAuthorized durumunu girerken RequestingAuthorization olayını çağıran ve hangi hesap kimlik bilgilerinin (AccountInfo sınıfının üst kısmında tanımlandığı ve yukarıdaki adımda Unity Inspector ile tanımlandığı kimlik bilgilerini kullandığı) belirleyen CheckAuthorization çağrılır.

Not

Çalışma zamanı yeniden derlemesi ARR tarafından desteklenmiyor. Betiği değiştirmek ve oynatma modu etkinken kaydetme, Unity'nin donmasıyla ve görev yöneticisi aracılığıyla kapanmaya zorlanmayla sonuçlanabilirsiniz. Betiklerinizi düzenlemeden önce her zaman oynatma modunu durdurmuş olduğundan emin olun.

  1. InitializeARR ve InitializeSessionService içeriğini aşağıdaki tamamlanmış kodla değiştirin:
/// <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;
}

NotAuthorized'tan NoSession'a ilerlemek için, kullanıcıya seçebiliyorları bir kalıcı iletişim kutusu sunacağız (ve bunu başka bir bölümde yapacağız). Şimdilik RequestingAuthorization olayı tetiklenir tetiklenmez ByPassAuthentication çağrısıyla yetkilendirme denetimi otomatik olarak atlanır.

  1. RemoteRenderingCoordinator GameObject öğesini seçin ve RemoteRenderingCoordinator bileşeninin Denetçisinde açık olan OnRequestingAuthorization Unity Olay'ı bulun.

  2. Sağ altta '+' tuşuna basarak yeni bir olay ekleyin.

  3. Bileşeni kendisine başvurarak kendi olayına sürükleyin.
    Kimlik Doğrulamasını Atlama\

  4. Açılan listeden RemoteRenderingCoordinator -> BypassAuthorization.\ öğesini seçin. Seçilen RemoteRenderingCoordinator.BypassAuthorization seçeneğini gösteren ekran görüntüsü.

Uzak oturum oluşturma veya oturuma katılma

İkinci aşama, Remote Rendering Oturumu Oluşturmak veya Katılmaktır (daha fazla bilgi için Remote Rendering Oturumlar'a bakın).

ARR yığını 2

Modellerin işlenecek olduğu uzak oturum. JoinRemoteSession( ) yöntemi LastUsedSessionID özelliğiyle izlenilen mevcut bir oturuma katılmayı veya SessionIDOverride üzerinde atanmış bir etkin oturum kimliği olup oalr. SessionIDOverride yalnızca hata ayıklama amacıyla tasarlanmıştır, yalnızca oturumun mevcut olduğunu biliyor ve ona açıkça bağlanmak istiyorken kullanılmalıdır.

Kullanılabilir oturum yoksa yeni bir oturum oluşturulur. Ancak yeni bir oturum oluşturmak zaman alan bir işlemdir. Bu nedenle, oturumları yalnızca gerektiğinde oluşturmanız ve mümkün olduğunda yeniden kullanmanız gerekir (oturumları yönetme hakkında daha fazla bilgi için bkz. Ticari Kullanıma Hazır: Oturum havuzu oluşturma, zamanlama ve en iyi yöntemler).

İpucu

StopRemoteSession() etkin oturumu sona erer. Gereksiz ücretleri önlemek için, artık gerekli olmayan oturumları her zaman durdurmanız gerekir.

Durum makinesi artık kullanılabilir oturumlara bağlı olarak ConnectingToNewRemoteSession veya ConnectingToExistingRemoteSession'a ilerleyecek. Hem mevcut oturum açma hem de yeni oturum oluşturma, ARRSessionService.OnSessionStatusChanged olayını tetikler ve OnRemoteSessionStatusChanged yöntemimizi yürütür. İdeal olarak, bu durum makinesinin RemoteSessionReady olarak ilerlemesiyle sonuçlandır.

  1. Yeni bir oturuma katılmak için kodu değiştirerek JoinRemoteSession( ) ve StopRemoteSession( ) yöntemlerini aşağıdaki tamamlanmış örneklerle değiştirin:
/// <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();
    }
}

Oturumları yeniden kullanarak zaman kazanmak için ARRServiceUnity bileşeninde Oturumu Otomatik Durdur seçeneğini devre dışı bırakarak emin olun. Bunun, hiç kimse bağlı değilken bile oturumları açık bırakmayacaklarını unutmayın. Oturumunuz, MaxLeaseTime süreniz sunucu tarafından kapatılamadan önce değiştirilebilir (MaxLeaseTime değeri Yeni Oturum Varsayılanları altında Remote Rendering Koordinatör'de değiştirilebilir). Öte yandan, bağlantıyı keserken her oturumu otomatik olarak kapatırsanız, her zaman yeni bir oturumun başlamasını beklemelisiniz ve bu biraz uzun bir işlem olabilir.

Not

Oturumun durdurulması hemen etkili olur ve geri alınamaz. Durdurulduktan sonra, aynı başlangıç yüküyle yeni bir oturum oluşturmanız gerekir.

Yerel çalışma zamanının uzak oturuma bağlanma

Ardından uygulamanın yerel çalışma zamanını uzak oturuma bağlaması gerekir.

ARR yığını 3

Uygulamanın ayrıca çalışma zamanı ile geçerli oturum arasındaki bağlantıyla ilgili olayları dinlemesi gerekir; Bu durum değişiklikleri OnLocalRuntimeStatusChanged içinde değiştirilebilir. Bu kod durumumuz için ConnectingToRuntime olarak ilerler. OnLocalRuntimeStatusChanged'e bağlandıktan sonra, durum RuntimeConnected'e ilerler. Çalışma zamanının bağlanması koordinatör tarafından endişelanan son durumdur. Bu durum, uygulamanın tüm ortak yapılandırmalarla tamamlansa da modelleri yükleme ve işleme için oturuma özgü çalışmaya başlamaya hazır olduğu anlamına gelir.

  1. ConnectRuntimeToRemoteSession( ) ve DisconnectRuntimeFromRemoteSession( ) yöntemlerini aşağıdaki tamamlanmış sürümlerle değiştirin.
  2. Unity lateUpdate yöntemini ve geçerli etkin oturumu güncelleştiriyor not almak önemlidir. Bu, geçerli oturumun ileti göndermesini/alasını ve çerçeve arabelleğini uzak oturumdan alınan çerçevelerle güncelleştirmesini sağlar. ARR'nin düzgün çalışması kritik öneme sahiptir.
/// <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();
}

Not

Yerel çalışma zamanının uzak bir oturuma bağlanması, o anda etkin olan oturumda Güncelleştirme'nin çağrılma durumuna bağlıdır. Uygulamanın ConnectingToRuntime durumunu hiçbir zaman geçe çalıştığını bulursanız etkin oturumda düzenli olarak Güncelleştir'i çağırsanız emin olun.

Model yükleme

Gerekli temel hazır olduğunda, modeli uzak oturuma yüklemek ve çerçeveleri almaya başlamak için hazır olur.

Modeli yüklemek ve görüntülemek için hazırlanmaya hazır olan işlem akışını gösteren diyagram.

LoadModel yöntemi bir model yolunu, ilerleme işleyicisini ve üst dönüştürmeyi kabul etmek için tasarlanmıştır. Bu bağımsız değişkenler modeli uzak oturuma yüklemek, yükleme ilerleme durumuyla ilgili kullanıcı güncelleştirmek ve uzaktan işlenmiş modeli üst dönüştürmeye göre yönlendirmek için kullanılır.

  1. LoadModel yöntemini tamamen aşağıdaki kodla değiştirin:

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

Yukarıdaki kod aşağıdaki adımları gerçekleştirmektedir:

  1. Uzak Varlık oluşturun.
  2. Uzak varlığı temsil etmek için yerel bir GameObject oluşturun.
  3. Yerel GameObject'i, durumunu her karede uzak varlıkla eşitlemek (başka bir ifadeyle Dönüşüm) için yapılandırabilirsiniz.
  4. Blob Depolama'dan uzak varlığa model verilerini yükleme.
  5. Daha sonra başvuru için üst Varlığı iade eder.

Test modelini görüntüleme

Artık uzaktan işlenen bir modeli görüntülemek için gereken tüm kodlara sahipsiniz. Uzaktan işleme için gereken dört aşamanın da hepsi tamamlandı. Şimdi model yükleme işlemini başlatmak için biraz kod eklememiz gerekiyor.

ARR yığını 4

  1. Aşağıdaki kodu RemoteRenderingCoordinator sınıfına ekleyin, LoadModel yönteminin hemen altına bakın:

    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)}%"));
    }
    

    Bu kod, test modelinin üst öğesi olarak hareket etmek için bir GameObject oluşturur. Ardından, işlemeyi test etmek amacıyla Azure Remote Rendering yerleşik bir varlık olan "builtin://Engine" modelini yüklemek için LoadModel yöntemini arar.

  2. Kodunuzu kaydedin.

  3. Unity Düzenleyicisi'nde Oynat düğmesine basarak yeni bir oturum Azure Remote Rendering bağlanma işlemini başlatabilirsiniz.

  4. Oyun görünümünde çok fazla şey görmeyebilirsiniz ancak Konsolda uygulamanın durumu değişir. Büyük olasılıkla , ile ConnectingToNewRemoteSession ilerler ve muhtemelen beş dakika boyunca orada kalır.

  5. Ekli betiklerini denetçide görmek için RemoteRenderingCoordinator GameObject öğesini seçin. Başlatma ve bağlantı adımları boyunca ilerleken Hizmet bileşeni güncelleştirmesini izleyin.

  6. Konsol çıkışını izleme - durumunun RuntimeConnected olarak değişmesini bekliyor.

  7. Çalışma zamanı bağlandıktan sonra, bağlam menüsünü göstermek için denetçide RemoteRenderingCoordinator'a sağ tıklayın. Ardından yukarıdaki kodumuz tarafından eklenen bağlam menüsünde Test Modelini [ContextMenu("Load Test Model")] Yükle seçeneğine tıklayın.

    Bağlam menüsünden yükleme

  8. LoadModel yöntemine geçirilen ProgressHandler çıkışı için Konsol'a göz atabilirsiniz.

  9. Uzaktan işlenmiş modeli görme!

Not

Uzak model sahne görünümünde hiçbir zaman görünmez, yalnızca oyun görünümünde görünür. Bunun nedeni ARR'nin kareleri Oyun görünümü kamerasının perspektifi için uzaktan işlemesi ve Düzenleyici kamerasını (Sahne görünümünü işlemek için kullanılır) farkında olmayan bir durumdur.

Sonraki adımlar

Model yüklendi

Tebrikler! İşleyi kullanarak uzaktan işlenmiş modelleri görüntüleme özelliğine sahip temel bir Azure Remote Rendering. Sonraki öğreticide MRTK'ı tümleştirecek ve kendi modellerimizi içeri aktaracak.