トレーニング
モジュール
Azure Remote Rendering を使用して 3D モデルをレンダリングする - Training
Azure Remote Rendering を使用して、Unity プロジェクトで 3D モデルをレンダリングします。 モデルを HoloLens 2 にデプロイすることも、MRTK で Mixed Reality の機能を使用することもできます。
このブラウザーはサポートされなくなりました。
Microsoft Edge にアップグレードすると、最新の機能、セキュリティ更新プログラム、およびテクニカル サポートを利用できます。
このチュートリアルでは、以下の内容を学習します。
Mixed Reality Toolkit (MRTK) は、Mixed Reality エクスペリエンスを構築するためのクロスプラットフォームのツールキットです。 ここでは、その操作と視覚化機能に MRTK 2.8.3 を使用します。
MRTK をインポートするための公式ガイドには、実行する必要のない手順がいくつか含まれています。 次の 3 つの手順のみ必要です。
この章からは、取り上げられる素材の多くに基本的な Model-View-Controller パターンを実装します。 このパターンの Model 部分は、Azure Remote Rendering 固有のコードと、Azure Remote Rendering に関連した状態管理です。 パターンの View 部分と Controller 部分は、MRTK アセットといくつかのカスタム スクリプトを使用して実装します。 このチュートリアルの Model は、ここで実装する View-Controller がなくても使用できます。 このように分離されているので、このチュートリアルにあるコードを独自のアプリケーションに容易に統合することができます。このアプリケーションは、設計パターンの View-Controller 部分を引き継ぐことになります。
MRTK の導入により、インタラクションとビジュアル フィードバックをサポートするためにプロジェクトに追加できるようになった複数のスクリプト、プレハブ、アセットが存在します。 これらのアセット (チュートリアル アセットといいます) は、Azure Remote Rendering GitHub の "\Unity\TutorialAssets\TutorialAssets.unitypackage" にある Unity アセット パッケージにバンドルされています。
.unitypackage
を選択します。MRTK とチュートリアル アセットが設定されていることをダブルチェックすると、正しいプロファイルが選択されます。
この手順で、主に既定の HoloLens 2 プロファイルで MRTK が構成されます。 提供されるプロファイルは、あらかじめ次のように構成されています。
このチュートリアルのほとんどのビュー コントローラーは、具象クラスではなく抽象基本クラスに対して動作します。 このパターンにより、柔軟性が向上し、ビュー コントローラーが与えられるだけでなく、自ら Azure Remote Rendering のコードを習得できます。 簡潔にするために、RemoteRenderingCoordinator クラスには抽象クラスは用意されておらず、そのビュー コントローラーは直接、具象クラスに対して動作します。
これで、プレハブの AppMenu をシーンに追加し、現在のセッション状態のビジュアル フィードバックを得ることができます。 AppMenu には、アプリケーションに ARR への接続を承認する際にユーザーが使用するモーダル パネルも表示されます。
Assets/RemoteRenderingTutorial/Prefabs/AppMenu で AppMenu プレハブを見つけます。
AppMenu プレハブをシーンにドラッグします。
TMP Importer のダイアログが表示された場合は、プロンプトに従って TMP Essentials をインポートします。 サンプルや追加パッケージは必要ないため、その後はインポーターのダイアログを閉じてください。
AppMenu は、セッションへの接続に同意するためのモーダルに自動的に接続して表示するよう構成されているため、前に設定しておいたバイパスは削除してかまいません。 RemoteRenderingCoordinator GameObject で、 [On Requesting Authorization](承認要求時) イベントの [-] ボタンをクリックして、以前に実装した承認のバイパスを削除してください。
.
Unity エディターの [Play](再生) を押して、ビュー コントローラーをテストします。
エディターで MRTK が構成されたら、WASD キーを使用してビューの位置を変更したり、マウスの右ボタンを押しながらマウスを移動することでビューの方向を変更したりすることができます。 シーン内を少し動き回ってみて、コントロールの感触を確かめてください。
デバイスで、手のひらを上げることで、AppMenu を呼び出すことができます。Unity エディターでは、ホットキーの "M" を使用します。
メニューが見えなくなった場合は、"M" キーを押してメニューを呼び出します。 操作しやすいよう、このメニューはカメラの近くに配置されます。
AppMenu は、承認用の UI 要素を AppMenu の右側に表示します。 今後は、この UI 要素を使用して、リモート レンダリング セッションを管理するアプリを承認する必要があります。
Unity の再生を停止して、チュートリアルを続行します。
状態の追跡、イベントへの応答、イベントの生成、構成を行うための RemoteRenderedModel という新しいスクリプトを実装する必要があります。 基本的に、RemoteRenderedModel はモデル データのリモート パスを modelPath
に格納します。
RemoteRenderingCoordinator で状態の変化をリッスンし、定義されているモデルを自動的に読み込む (またはアンロードする) 必要があるかどうかを判断します。
RemoteRenderedModel がアタッチされている GameObject が、リモート コンテンツのローカルにおける親になります。
RemoteRenderedModel スクリプトには、チュートリアル アセットにある BaseRemoteRenderedModel が実装されていることに注目してください。 この接続によって、リモート モデル ビュー コントローラーをスクリプトにバインドすることができます。
RemoteRenderingCoordinator と同じフォルダーに、RemoteRenderedModel という名前の新しいスクリプトを作成します。 内容全体を次のコードに置き換えます。
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using Microsoft.Azure.RemoteRendering;
using Microsoft.Azure.RemoteRendering.Unity;
using System;
using UnityEngine;
using UnityEngine.Events;
public class RemoteRenderedModel : BaseRemoteRenderedModel
{
public bool AutomaticallyLoad = true;
private ModelState currentModelState = ModelState.NotReady;
[SerializeField]
[Tooltip("The friendly name for this model")]
private string modelDisplayName;
public override string ModelDisplayName { get => modelDisplayName; set => modelDisplayName = value; }
[SerializeField]
[Tooltip("The URI for this model")]
private string modelPath;
public override string ModelPath
{
get => modelPath.Trim();
set => modelPath = value;
}
public override ModelState CurrentModelState
{
get => currentModelState;
protected set
{
if (currentModelState != value)
{
currentModelState = value;
ModelStateChange?.Invoke(value);
}
}
}
public override event Action<ModelState> ModelStateChange;
public override event Action<float> LoadProgress;
public override Entity ModelEntity { get; protected set; }
public UnityEvent OnModelNotReady = new UnityEvent();
public UnityEvent OnModelReady = new UnityEvent();
public UnityEvent OnStartLoading = new UnityEvent();
public UnityEvent OnModelLoaded = new UnityEvent();
public UnityEvent OnModelUnloading = new UnityEvent();
public UnityFloatEvent OnLoadProgress = new UnityFloatEvent();
public void Awake()
{
// Hook up the event to the Unity event
LoadProgress += (progress) => OnLoadProgress?.Invoke(progress);
ModelStateChange += HandleUnityStateEvents;
}
private void HandleUnityStateEvents(ModelState modelState)
{
switch (modelState)
{
case ModelState.NotReady: OnModelNotReady?.Invoke(); break;
case ModelState.Ready: OnModelReady?.Invoke(); break;
case ModelState.Loading: OnStartLoading?.Invoke(); break;
case ModelState.Loaded: OnModelLoaded?.Invoke(); break;
case ModelState.Unloading: OnModelUnloading?.Invoke(); break;
}
}
private void Start()
{
//Attach to and initialize current state (in case we're attaching late)
RemoteRenderingCoordinator.CoordinatorStateChange += Instance_CoordinatorStateChange;
Instance_CoordinatorStateChange(RemoteRenderingCoordinator.instance.CurrentCoordinatorState);
}
/// <summary>
/// Listen for state changes on the coordinator, clean up this model's remote objects if we're no longer connected.
/// Automatically load if required
/// </summary>
private void Instance_CoordinatorStateChange(RemoteRenderingCoordinator.RemoteRenderingState state)
{
switch (state)
{
case RemoteRenderingCoordinator.RemoteRenderingState.RuntimeConnected:
CurrentModelState = ModelState.Ready;
if (AutomaticallyLoad)
LoadModel();
break;
default:
UnloadModel();
break;
}
}
private void OnDestroy()
{
RemoteRenderingCoordinator.CoordinatorStateChange -= Instance_CoordinatorStateChange;
UnloadModel();
}
/// <summary>
/// Asks the coordinator to create a model entity and listens for coordinator state changes
/// </summary>
[ContextMenu("Load Model")]
public override async void LoadModel()
{
if (CurrentModelState != ModelState.Ready)
return; //We're already loaded, currently loading, or not ready to load
CurrentModelState = ModelState.Loading;
ModelEntity = await RemoteRenderingCoordinator.instance?.LoadModel(ModelPath, this.transform, SetLoadingProgress);
if (ModelEntity != null)
CurrentModelState = ModelState.Loaded;
else
CurrentModelState = ModelState.Error;
}
/// <summary>
/// Clean up the local model instances
/// </summary>
[ContextMenu("Unload Model")]
public override void UnloadModel()
{
CurrentModelState = ModelState.Unloading;
if (ModelEntity != null)
{
var modelGameObject = ModelEntity.GetOrCreateGameObject(UnityCreationMode.DoNotCreateUnityComponents);
Destroy(modelGameObject);
ModelEntity.Destroy();
ModelEntity = null;
}
if (RemoteRenderingCoordinator.instance.CurrentCoordinatorState == RemoteRenderingCoordinator.RemoteRenderingState.RuntimeConnected)
CurrentModelState = ModelState.Ready;
else
CurrentModelState = ModelState.NotReady;
}
/// <summary>
/// Update the Unity progress event
/// </summary>
/// <param name="progressValue"></param>
public override void SetLoadingProgress(float progressValue)
{
LoadProgress?.Invoke(progressValue);
}
}
RemoteRenderedModel の役割は、一言で言えば、モデルの読み込みに必要なデータ (この場合は、SAS または builtin:// URI) を保持し、リモート モデルの状態を追跡することです。 モデルの読み込み時に、RemoteRenderingCoordinator の LoadModel
メソッドが呼び出され、モデルを含むエンティティが参照とアンロード用に返されます。
もう一度テスト モデルを読み込んで、新しいスクリプトをテストしてみましょう。 このテストでは、スクリプトを含み、テスト モデルの親になる Game オブジェクトが必要です。また、モデルを含む仮想ステージも必要です。 モデル自体を後で動かせるように、固定ステージを使用します。
シーンに新しい空のゲーム オブジェクトを作成し、ModelStage という名前を付けます。
ModelStage に WorldAnchor コンポーネントを追加します。
ModelStage の子として新しい空のゲーム オブジェクトを作成し、TestModel という名前を付けます。
RemoteRenderedModel スクリプトを TestModel に追加します。
[Model Display Name
] と [Model Path
] に、それぞれ「TestModel」と「builtin://Engine」を入力します。
カメラの前の位置 x = 0、y = 0、z = 3 に、TestModel オブジェクトを配置します。
AutomaticallyLoad がオンになっていることを確認します。
Unity エディターで [Play](再生) を押してアプリケーションをテストします。
アプリがセッションを作成できるように [Connect](接続) ボタンをクリックして承認することで、セッションに接続し、自動的にモデルを読み込むようになります。
コンソールでアプリケーションの状態を監視します。 状態によっては完了までに時間がかかる場合があり、しばらくの間更新の進行状況が表示されないことに注意してください。 最終的には、モデルの読み込みからのログが表示され、すぐ後にシーンにレンダリングされたテスト モデルが表示されます。
インスペクターの [Transform](トランスフォーム)、または [Game] ビューで移動を観察する [Scene](シーン) ビューで、TestModel GameObject の移動や回転を試します。
ここで、自分のモデルを読み込んでみましょう。 そのためには、Blob Storage を構成し、Azure でモデルをアップロードして変換する必要があります。その後、RemoteRenderedModel スクリプトを使用してそのモデルを読み込みます。 この時点で読み込む独自のモデルがなければ、カスタム モデルの読み込みステップは省略してかまいません。
「クイックスタート: モデルをレンダリング用に変換する」に記載の手順に従います。 このチュートリアルでは、「クイック スタート サンプル アプリに新しいモデルを挿入する」セクションはスキップしてください。 取り込んだモデルの Shared Access Signature (SAS) URI が得られたら、続行します。
新しい空の GameObject をシーンに作成し、カスタム モデルと同様の名前を付けます。
新しく作成した GameObject に RemoteRenderedModel スクリプトを追加します。
Model Display Name
に、カスタム モデルの適切な名前を入力します。
Azure に Blob Storage をプロビジョニングしてカスタム モデルを取り込む手順で作成した、モデルの Shared Access Signature (SAS) URI を Model Path
に入力します。
カメラの前の x = 0, y = 0, z = 3 の位置に GameObject を配置します。
AutomaticallyLoad がオンになっていることを確認します。
Unity エディターで [Play](再生) を押してアプリケーションをテストします。
コンソールには、セッションが接続されると、現在のセッション状態と進行状況についてのメッセージを読み込むモデルも表示されます。
カスタム モデル オブジェクトをシーンから削除します。 このチュートリアルで最良のエクスペリエンスが得られるのは、テスト モデルを使用したときです。 ARR では複数のモデルがサポートされますが、このチュートリアルは、一度に 1 つのリモート モデルをサポートするよう最適化して作成されています。
これで、独自のモデルを Azure Remote Rendering に読み込んで、自分のアプリケーションで表示できるようになりました。 次に、モデルの操作方法について説明します。
トレーニング
モジュール
Azure Remote Rendering を使用して 3D モデルをレンダリングする - Training
Azure Remote Rendering を使用して、Unity プロジェクトで 3D モデルをレンダリングします。 モデルを HoloLens 2 にデプロイすることも、MRTK で Mixed Reality の機能を使用することもできます。
ドキュメント
Azure Remote Rendering チュートリアルのランディング ページ - Azure Remote Rendering
ARR チュートリアルの概要とナビゲーション
モデルを変換する - Azure Remote Rendering
カスタム モデルの変換手順を示すクイックスタートです。
リモートでレンダリングされたモデルの表示 - Azure Remote Rendering
Azure Remote Rendering の入門チュートリアルでは、Azure によってリモートでレンダリングされるモデルを表示する方法について説明します