HoloLens (第 1 世代) 基本 101E: エミュレーターを使用したプロジェクトの完了
重要
Mixed Reality Academy のチュートリアルは、HoloLens (第 1 世代)、Unity 2017、Mixed Realityイマーシブ ヘッドセットを念頭に置いて設計されました。 そのため、これらのデバイスの開発に関するガイダンスをまだ探している開発者には、これらのチュートリアルを配置しておくことが重要であると考えます。 これらのチュートリアルは、HoloLens 2に使用されている最新のツールセットや相互作用では更新されず、新しいバージョンのUnityと互換性がない可能性があります。 これらは、サポートされているデバイスでの作業を継続するために維持されます。 HoloLens 2用の新しい一連のチュートリアルが投稿されました。
このチュートリアルでは、視線入力、ジェスチャ、音声入力、空間サウンド、空間マッピングなど、HoloLens のコア Windows Mixed Reality機能を示す、Unityに組み込まれた完全なプロジェクトについて説明します。 チュートリアルの完了には約 1 時間かかります。
デバイスのサポート
コース | HoloLens | イマーシブ ヘッドセット |
---|---|---|
MR の基本 101E: エミュレーターを使用したプロジェクトの完了 | ✔️ |
始める前に
前提条件
- 正しいツールをインストールして構成されたWindows 10 PC。
プロジェクト ファイル
- プロジェクトに必要な ファイル をダウンロードします。 2017.2 以降Unity必要です。
- デスクトップまたはその他の簡単にアクセスできる場所にファイルをアーカイブ解除します。 フォルダー名は Origami のままにします。
注:
ダウンロードする前にソース コードを確認する場合は、 GitHub で入手できます。
第 1 章 - "Holo" の世界
この章では、最初のUnity プロジェクトをセットアップし、ビルドとデプロイのプロセスをステップ実行します。
目標
- ホログラフィック開発用のUnityを設定します。
- ホログラムを作成します。
- 作成したホログラムを表示します。
手順
- Unityを開始します。
- [開く]を選択します。
- 以前にアーカイブを解除した Origami フォルダーとして、場所を入力します。
- [ 折り紙 ] を選択し、[ フォルダーの選択] をクリックします。
- 新しいシーンを保存します: ファイル / 名前を付けてシーンを保存します。
- シーンに 「Origami」 という名前を付け、[ 保存 ] ボタンを押します。
メイン カメラをセットアップする
- [階層] パネルで、[メイン カメラ] を選択します。
- インスペクターで、変換位置を 0,0,0 に設定します。
- Clear Flags プロパティを見つけて、ドロップダウンを [Skybox] から [純色] に変更します。
- [ 背景 ] フィールドをクリックして、カラー ピッカーを開きます。
- R、G、B、A を 0 に設定します。
シーンを設定する
- [階層] パネルで、[作成] と [空の作成] をクリックします。
- 新しい GameObject を右クリックし、[名前の変更] を選択します。 GameObject の名前を OrigamiCollection に変更します。
- プロジェクト パネルの [ホログラム ] フォルダーから次の 操作を行います。
- Stage を Hierarchy にドラッグして、OrigamiCollection の子にします。
- Sphere1 を Hierarchy にドラッグして、OrigamiCollection の子にします。
- Sphere2 を Hierarchy にドラッグして、OrigamiCollection の子にします。
- 階層パネルで[方向ライト]オブジェクトを右クリックし、[削除]を選択します。
- [ホログラム] フォルダーから、[階層] パネルのルートに [ライト] をドラッグします。
- [階層] で、OrigamiCollection を選択します。
- インスペクターで、変換位置を 0、-0.5、2.0 に設定します。
- ホログラムをプレビューするには、Unityの [再生] ボタンを押します。
- プレビュー ウィンドウに Origami オブジェクトが表示されます。
- [再生] をもう一度押してプレビュー モードを停止します。
プロジェクトをUnityから Visual Studio にエクスポートする
- [Unityファイル>ビルド設定] を選択します。
- [プラットフォーム] の一覧で [Windows ストア] を選択し、[プラットフォームの切り替え] をクリックします。
- [SDK] を [ユニバーサル 10] に設定し、[ビルドの種類] を [D3D] に設定します。
- [Unity C# プロジェクト] を確認します。
- [ 開いているシーンの追加] をクリックしてシーンを追加します。
- [ プレイヤー設定]をクリックします。...
- [インスペクター] パネルで、 Windows ストアのロゴを選択します。 次に、[ 発行設定] を選択します。
- [ 機能 ] セクションで、[ マイク ] 機能と [SpatialPerception ] 機能を選択します。
- [ビルド設定] ウィンドウに戻り、[ ビルド] をクリックします。
- "App" という名前の 新しいフォルダー を作成します。
- [App Folder]\(アプリ フォルダー\) をクリックします。
- [フォルダーの選択] を押します。
- Unityが完了すると、エクスプローラー ウィンドウが表示されます。
- App フォルダーを開きます。
- Origami Visual Studio ソリューションを開きます。
- Visual Studio の上部のツール バーを使用して、ターゲットを [デバッグ] から [ リリース] に、ARM から X86 に変更します。
- [デバイス] ボタンの横にある矢印をクリックし、[ HoloLens Emulator] を選択します。
- [ デバッグ] -> [デバッグなしで開始] をクリックするか、 Ctrl + F5 キーを押します。
- しばらくすると、エミュレーターは Origami プロジェクトから開始されます。 エミュレーターを最初に起動するときに、 エミュレーターの起動に 15 分かかる場合があります。 起動したら、閉じないでください。
第 2 章 - 視線入力
この章では、ホログラムと対話する最初の 3 つの方法 ( 視線入力) について説明します。
目標
- ワールド ロックカーソルを使用して視線入力を視覚化します。
手順
- Unity プロジェクトに戻るし、まだ開いている場合は [ビルド設定] ウィンドウを閉じます。
- [プロジェクト] パネルで [ホログラム] フォルダーを選択します。
- Cursor オブジェクトをルート レベルの [階層] パネルにドラッグします。
- Cursor オブジェクトをダブルクリックして、詳細を確認します。
- [プロジェクト] パネルの [スクリプト ] フォルダーを右クリックします。
- [ 作成 ] サブメニューをクリックします。
- [ C# スクリプト] を選択します。
- スクリプトに WorldCursor という名前を付けます。 注: 名前では大文字と小文字が区別されます。 .cs拡張機能を追加する必要はありません。
- [階層] パネルで Cursor オブジェクトを選択します。
- WorldCursor スクリプトをインスペクター パネルにドラッグ アンド ドロップします。
- Visual Studio で WorldCursor スクリプトをダブルクリックして開きます。
- このコードをコピーして WorldCursor.cs に貼り付け、 すべて保存します。
using UnityEngine;
public class WorldCursor : MonoBehaviour
{
private MeshRenderer meshRenderer;
// Use this for initialization
void Start()
{
// Grab the mesh renderer that's on the same object as this script.
meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>();
}
// Update is called once per frame
void Update()
{
// Do a raycast into the world based on the user's
// head position and orientation.
var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;
RaycastHit hitInfo;
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
{
// If the raycast hit a hologram...
// Display the cursor mesh.
meshRenderer.enabled = true;
// Move thecursor to the point where the raycast hit.
this.transform.position = hitInfo.point;
// Rotate the cursor to hug the surface of the hologram.
this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
}
else
{
// If the raycast did not hit a hologram, hide the cursor mesh.
meshRenderer.enabled = false;
}
}
}
- [ファイル] > [ビルド設定] からアプリをリビルドします。
- エミュレーターへのデプロイに使用した Visual Studio ソリューションに戻ります。
- プロンプトが表示されたら、[すべて再読み込み] を選択します。
- [ デバッグ] -> [デバッグなしで開始] をクリックするか、 Ctrl + F5 キーを押します。
- Xbox コントローラーを使用してシーンを見回します。 カーソルがオブジェクトの形状とどのように相互作用するかに注目してください。
第 3 章 - ジェスチャ
この章では、ジェスチャのサポートを追加 します。 ユーザーが紙の球体を選択すると、Unityの物理エンジンを使用して重力をオンにして球体が落下します。
目標
- [選択] ジェスチャを使用してホログラムを制御します。
手順
まず、Select ジェスチャを検出できるスクリプトを作成します。
- [スクリプト] フォルダー で 、 GazeGestureManager という名前のスクリプトを作成します。
- GazeGestureManager スクリプトを Hierarchy 内の OrigamiCollection オブジェクトにドラッグします。
- Visual Studio で GazeGestureManager スクリプトを開き、次のコードを追加します。
using UnityEngine;
using UnityEngine.XR.WSA.Input;
public class GazeGestureManager : MonoBehaviour
{
public static GazeGestureManager Instance { get; private set; }
// Represents the hologram that is currently being gazed at.
public GameObject FocusedObject { get; private set; }
GestureRecognizer recognizer;
// Use this for initialization
void Start()
{
Instance = this;
// Set up a GestureRecognizer to detect Select gestures.
recognizer = new GestureRecognizer();
recognizer.Tapped += (args) =>
{
// Send an OnSelect message to the focused object and its ancestors.
if (FocusedObject != null)
{
FocusedObject.SendMessageUpwards("OnSelect", SendMessageOptions.DontRequireReceiver);
}
};
recognizer.StartCapturingGestures();
}
// Update is called once per frame
void Update()
{
// Figure out which hologram is focused this frame.
GameObject oldFocusObject = FocusedObject;
// Do a raycast into the world based on the user's
// head position and orientation.
var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;
RaycastHit hitInfo;
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
{
// If the raycast hit a hologram, use that as the focused object.
FocusedObject = hitInfo.collider.gameObject;
}
else
{
// If the raycast did not hit a hologram, clear the focused object.
FocusedObject = null;
}
// If the focused object changed this frame,
// start detecting fresh gestures again.
if (FocusedObject != oldFocusObject)
{
recognizer.CancelGestures();
recognizer.StartCapturingGestures();
}
}
}
- Scripts フォルダーに別のスクリプトを作成します。今回は SphereCommands という名前です。
- Hierarchy ビューで OrigamiCollection オブジェクトを展開します。
- SphereCommands スクリプトを階層パネルの Sphere1 オブジェクトにドラッグします。
- SphereCommands スクリプトを階層パネルの Sphere2 オブジェクトにドラッグします。
- 編集のために Visual Studio でスクリプトを開き、既定のコードを次のように置き換えます。
using UnityEngine;
public class SphereCommands : MonoBehaviour
{
// Called by GazeGestureManager when the user performs a Select gesture
void OnSelect()
{
// If the sphere has no Rigidbody component, add one to enable physics.
if (!this.GetComponent<Rigidbody>())
{
var rigidbody = this.gameObject.AddComponent<Rigidbody>();
rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
}
}
}
- HoloLens エミュレーターにアプリをエクスポート、ビルド、デプロイします。
- シーンを見回し、いずれかの球体を中央に配置します。
- Xbox コントローラーの A ボタンを押すか、Space キーを押して Select ジェスチャをシミュレートします。
第 4 章 - 音声
この章では、ドロップした球体を元の場所に戻す "世界のリセット" コマンドと、球体を落下させる "球体のドロップ" という 2 つの 音声コマンドのサポートを追加します。
目標
- 常にバックグラウンドでリッスンする音声コマンドを追加します。
- 音声コマンドに反応するホログラムを作成します。
手順
- [スクリプト] フォルダー で 、 SpeechManager という名前のスクリプトを作成します。
- SpeechManager スクリプトを Hierarchy 内の OrigamiCollection オブジェクトにドラッグします
- Visual Studio で SpeechManager スクリプトを開きます。
- このコードをコピーして SpeechManager.cs に貼り付け、 すべて保存します。
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Windows.Speech;
public class SpeechManager : MonoBehaviour
{
KeywordRecognizer keywordRecognizer = null;
Dictionary<string, System.Action> keywords = new Dictionary<string, System.Action>();
// Use this for initialization
void Start()
{
keywords.Add("Reset world", () =>
{
// Call the OnReset method on every descendant object.
this.BroadcastMessage("OnReset");
});
keywords.Add("Drop Sphere", () =>
{
var focusObject = GazeGestureManager.Instance.FocusedObject;
if (focusObject != null)
{
// Call the OnDrop method on just the focused object.
focusObject.SendMessage("OnDrop", SendMessageOptions.DontRequireReceiver);
}
});
// Tell the KeywordRecognizer about our keywords.
keywordRecognizer = new KeywordRecognizer(keywords.Keys.ToArray());
// Register a callback for the KeywordRecognizer and start recognizing!
keywordRecognizer.OnPhraseRecognized += KeywordRecognizer_OnPhraseRecognized;
keywordRecognizer.Start();
}
private void KeywordRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
{
System.Action keywordAction;
if (keywords.TryGetValue(args.text, out keywordAction))
{
keywordAction.Invoke();
}
}
}
- Visual Studio で SphereCommands スクリプトを開きます。
- 次のように読み取るようにスクリプトを更新します。
using UnityEngine;
public class SphereCommands : MonoBehaviour
{
Vector3 originalPosition;
// Use this for initialization
void Start()
{
// Grab the original local position of the sphere when the app starts.
originalPosition = this.transform.localPosition;
}
// Called by GazeGestureManager when the user performs a Select gesture
void OnSelect()
{
// If the sphere has no Rigidbody component, add one to enable physics.
if (!this.GetComponent<Rigidbody>())
{
var rigidbody = this.gameObject.AddComponent<Rigidbody>();
rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
}
}
// Called by SpeechManager when the user says the "Reset world" command
void OnReset()
{
// If the sphere has a Rigidbody component, remove it to disable physics.
var rigidbody = this.GetComponent<Rigidbody>();
if (rigidbody != null)
{
rigidbody.isKinematic = true;
Destroy(rigidbody);
}
// Put the sphere back into its original local position.
this.transform.localPosition = originalPosition;
}
// Called by SpeechManager when the user says the "Drop sphere" command
void OnDrop()
{
// Just do the same logic as a Select gesture.
OnSelect();
}
}
- HoloLens エミュレーターにアプリをエクスポート、ビルド、デプロイします。
- エミュレーターは、PC のマイクをサポートし、音声に応答します。ビューを調整して、カーソルが球体の 1 つになるように調整し、"球体をドロップ" と言います。
- 「世界をリセット」と言って、最初の位置に戻します。
第 5 章 - 空間サウンド
この章では、アプリに音楽を追加し、特定のアクションでサウンド エフェクトをトリガーします。 空間サウンドを使用して、3D 空間内の特定の場所にサウンドを与えます。
目標
- 世界のホログラムを読み上げる。
手順
- Unity上部のメニューから [プロジェクトの設定] > [オーディオ>編集] を選択します
- Spatializer プラグインの設定を見つけて、[MS HRTF Spatializer] を選択します。
- [ホログラム] フォルダーから、アンビエンス オブジェクトを階層パネルの OrigamiCollection オブジェクトにドラッグします。
- [ OrigamiCollection] を 選択し、 オーディオ ソース コンポーネントを見つけます。 次のプロパティを変更します。
- Spatialize プロパティを確認します。
- [Play On Awake]\(プレイ オン アウェイク\) を確認します。
- スライダーを右にドラッグして 、空間ブレンド を 3D に変更します。
- Loop プロパティを確認します。
- [3D サウンド設定] を展開し、[ドップラー レベル] に「0.1」と入力します。
- [ボリューム ロールオフ] を [対数ロールオフ] に設定します。
- [最大距離] を 20 に設定します。
- [ Scripts ] フォルダーに SphereSounds という名前のスクリプトを作成します。
- SphereSounds を階層内の Sphere1 オブジェクトと Sphere2 オブジェクトにドラッグします。
- Visual Studio で SphereSounds を開き、次のコードを更新し 、[すべて保存] を選択します。
using UnityEngine;
public class SphereSounds : MonoBehaviour
{
AudioSource impactAudioSource = null;
AudioSource rollingAudioSource = null;
bool rolling = false;
void Start()
{
// Add an AudioSource component and set up some defaults
impactAudioSource = gameObject.AddComponent<AudioSource>();
impactAudioSource.playOnAwake = false;
impactAudioSource.spatialize = true;
impactAudioSource.spatialBlend = 1.0f;
impactAudioSource.dopplerLevel = 0.0f;
impactAudioSource.rolloffMode = AudioRolloffMode.Logarithmic;
impactAudioSource.maxDistance = 20f;
rollingAudioSource = gameObject.AddComponent<AudioSource>();
rollingAudioSource.playOnAwake = false;
rollingAudioSource.spatialize = true;
rollingAudioSource.spatialBlend = 1.0f;
rollingAudioSource.dopplerLevel = 0.0f;
rollingAudioSource.rolloffMode = AudioRolloffMode.Logarithmic;
rollingAudioSource.maxDistance = 20f;
rollingAudioSource.loop = true;
// Load the Sphere sounds from the Resources folder
impactAudioSource.clip = Resources.Load<AudioClip>("Impact");
rollingAudioSource.clip = Resources.Load<AudioClip>("Rolling");
}
// Occurs when this object starts colliding with another object
void OnCollisionEnter(Collision collision)
{
// Play an impact sound if the sphere impacts strongly enough.
if (collision.relativeVelocity.magnitude >= 0.1f)
{
impactAudioSource.Play();
}
}
// Occurs each frame that this object continues to collide with another object
void OnCollisionStay(Collision collision)
{
Rigidbody rigid = gameObject.GetComponent<Rigidbody>();
// Play a rolling sound if the sphere is rolling fast enough.
if (!rolling && rigid.velocity.magnitude >= 0.01f)
{
rolling = true;
rollingAudioSource.Play();
}
// Stop the rolling sound if rolling slows down.
else if (rolling && rigid.velocity.magnitude < 0.01f)
{
rolling = false;
rollingAudioSource.Stop();
}
}
// Occurs when this object stops colliding with another object
void OnCollisionExit(Collision collision)
{
// Stop the rolling sound if the object falls off and stops colliding.
if (rolling)
{
rolling = false;
impactAudioSource.Stop();
rollingAudioSource.Stop();
}
}
}
- スクリプトを保存し、Unityに戻ります。
- HoloLens エミュレーターにアプリをエクスポート、ビルド、デプロイします。
- 完全な効果を得るためにヘッドフォンを着用し、音の変化を聞くためにステージの近くに遠くに移動します。
第 6 章 - 空間マッピング
ここでは、 空間マッピング を使用して、ゲーム ボードを現実世界の実際のオブジェクトに配置します。
目標
- 現実世界を仮想世界に持ち込む。
- ホログラムを最も重要な場所に配置します。
手順
- [プロジェクト] パネルの [ホログラム ] フォルダーをクリックします。
- 空間マッピング アセットを階層のルートにドラッグします。
- 階層内の 空間マッピング オブジェクトをクリックします。
-
[インスペクター] パネルで、次のプロパティを変更します。
- [ Visual Meshes の描画 ] ボックスをオンにします。
- [ マテリアルの描画] を見つけて、右側の円をクリックします。 上部の検索フィールドに「wireframe」と入力します。 結果をクリックし、ウィンドウを閉じます。
- HoloLens エミュレーターにアプリをエクスポート、ビルド、デプロイします。
- アプリを実行すると、以前にスキャンされた現実世界のリビングルームのメッシュがワイヤーフレームでレンダリングされます。
- ローリング球体がステージから落下し、床に落ちる方法を見てください!
ここで、OrigamiCollection を新しい場所に移動する方法について説明します。
- [スクリプト] フォルダー で 、 TapToPlaceParent という名前のスクリプトを作成します。
- 階層で、OrigamiCollection を展開し、Stage オブジェクトを選択します。
- TapToPlaceParent スクリプトを Stage オブジェクトにドラッグします。
- Visual Studio で TapToPlaceParent スクリプトを開き、次のように更新します。
using UnityEngine;
public class TapToPlaceParent : MonoBehaviour
{
bool placing = false;
// Called by GazeGestureManager when the user performs a Select gesture
void OnSelect()
{
// On each Select gesture, toggle whether the user is in placing mode.
placing = !placing;
// If the user is in placing mode, display the spatial mapping mesh.
if (placing)
{
SpatialMapping.Instance.DrawVisualMeshes = true;
}
// If the user is not in placing mode, hide the spatial mapping mesh.
else
{
SpatialMapping.Instance.DrawVisualMeshes = false;
}
}
// Update is called once per frame
void Update()
{
// If the user is in placing mode,
// update the placement to match the user's gaze.
if (placing)
{
// Do a raycast into the world that will only hit the Spatial Mapping mesh.
var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;
RaycastHit hitInfo;
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo,
30.0f, SpatialMapping.PhysicsRaycastMask))
{
// Move this object's parent object to
// where the raycast hit the Spatial Mapping mesh.
this.transform.parent.position = hitInfo.point;
// Rotate this object's parent object to face the user.
Quaternion toQuat = Camera.main.transform.localRotation;
toQuat.x = 0;
toQuat.z = 0;
this.transform.parent.rotation = toQuat;
}
}
}
}
- アプリをエクスポート、ビルド、デプロイします。
- これで、Select ジェスチャ (A または Space バー) を使用して特定の場所にゲームを配置し、次に新しい場所に移動し、もう一度 Select ジェスチャを使用してゲームを配置できるようになりました。
最後です
このチュートリアルはこれで終わりです。
学習した内容:
- Unityでホログラフィック アプリを作成する方法。
- 視線入力、ジェスチャ、音声、サウンド、空間マッピングを利用する方法。
- Visual Studio を使用してアプリをビルドしてデプロイする方法。
これで、独自のホログラフィック アプリの作成を開始する準備ができました。