Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Tutorial Mixed Reality Academy dirancang dengan HoloLens (generasi ke-1) dan Mixed Reality Immersive Headsets dalam pikiran. Dengan demikian, kami merasa penting untuk meninggalkan tutorial ini di tempat bagi pengembang yang masih mencari panduan dalam mengembangkan untuk perangkat tersebut. Tutorial ini tidak akan diperbarui dengan toolset atau interaksi terbaru yang digunakan untuk HoloLens 2. Mereka akan dipertahankan untuk terus bekerja pada perangkat yang didukung. Akan ada serangkaian tutorial baru yang akan diposting di masa depan yang akan menunjukkan cara mengembangkan untuk HoloLens 2. Pemberitahuan ini akan diperbarui dengan tautan ke tutorial tersebut ketika diposting.

Dalam kursus ini, Anda akan mempelajari cara membuat dan menggunakan Azure Functions dan menyimpan data dengan sumber daya Azure Storage, dalam aplikasi realitas campuran.
Azure Functions adalah layanan Microsoft, yang memungkinkan pengembang menjalankan bagian kecil kode, 'fungsi', di Azure. Ini menyediakan cara untuk mendelegasikan pekerjaan ke cloud, daripada aplikasi lokal Anda, yang dapat memiliki banyak manfaat. Azure Functions mendukung beberapa bahasa pengembangan, termasuk C#, F#, Node.js, Java, dan PHP. Untuk informasi selengkapnya, kunjungi artikel Azure Functions.
Azure Storage adalah layanan cloud Microsoft, yang memungkinkan pengembang untuk menyimpan data, dengan asuransi yang akan sangat tersedia, aman, tahan lama, dapat diskalakan, dan berlebihan. Ini berarti Microsoft akan menangani semua pemeliharaan, dan masalah penting untuk Anda. Untuk informasi selengkapnya, kunjungi artikel Azure Storage.
Setelah menyelesaikan kursus ini, Anda akan memiliki aplikasi headset imersif realitas campuran yang akan dapat melakukan hal berikut:
- Izinkan pengguna untuk menatap di sekitar adegan.
- Picu pemicu pemicu objek saat pengguna menatap 'tombol' 3D.
- Objek yang ditelurkan akan dipilih oleh Azure Function.
- Saat setiap objek ditelurkan, aplikasi akan menyimpan jenis objek dalam File Azure, yang terletak di Azure Storage.
- Setelah memuat untuk kedua kalinya , data File Azure akan diambil, dan digunakan untuk memutar ulang tindakan pemijahan dari instans aplikasi sebelumnya.
Dalam aplikasi Anda, terserah Anda tentang bagaimana Anda akan mengintegrasikan hasilnya dengan desain Anda. Kursus ini dirancang untuk mengajari Anda cara mengintegrasikan Layanan Azure dengan Proyek Unity Anda. Adalah tugas Anda untuk menggunakan pengetahuan yang Anda peroleh dari kursus ini untuk meningkatkan Aplikasi realitas campuran Anda.
Dukungan perangkat
| Kursus | HoloLens | Headset imersif |
|---|---|---|
| MR dan Azure 305: Fungsi dan penyimpanan | ✔️ | ✔️ |
Catatan
Meskipun kursus ini terutama berfokus pada headset imersif Windows Mixed Reality (VR), Anda juga dapat menerapkan apa yang Anda pelajari dalam kursus ini ke Microsoft HoloLens. Saat mengikuti kursus, Anda akan melihat catatan tentang perubahan apa pun yang mungkin perlu Anda gunakan untuk mendukung HoloLens.
Prasyarat
Catatan
Tutorial ini dirancang untuk pengembang yang memiliki pengalaman dasar dengan Unity dan C#. Perlu diketahui juga bahwa prasyarat dan instruksi tertulis dalam dokumen ini mewakili apa yang telah diuji dan diverifikasi pada saat penulisan (Mei 2018). Anda bebas menggunakan perangkat lunak terbaru, seperti yang tercantum dalam artikel instal alat , meskipun tidak boleh diasumsikan bahwa informasi dalam kursus ini akan sangat cocok dengan apa yang akan Anda temukan di perangkat lunak yang lebih baru daripada apa yang tercantum di bawah ini.
Kami merekomendasikan perangkat keras dan perangkat lunak berikut untuk kursus ini:
- PC pengembangan, kompatibel dengan Windows Mixed Reality untuk pengembangan headset imersif (VR)
- Pembaruan Windows 10 Fall Creators (atau yang lebih baru) dengan mode Pengembang diaktifkan
- Windows 10 SDK terbaru
- Unity 2017.4
- Visual Studio 2017
- Headset Windows Mixed Reality immersive (VR) atau Microsoft HoloLens dengan mode Pengembang diaktifkan
- Langganan ke akun Azure untuk membuat sumber daya Azure
- Akses internet untuk penyiapan Azure dan pengambilan data
Sebelum memulai
Untuk menghindari masalah saat membangun proyek ini, sangat disarankan agar Anda membuat proyek yang disebutkan dalam tutorial ini di folder root atau near-root (jalur folder panjang dapat menyebabkan masalah pada build-time).
Bab 1 - Portal Microsoft Azure
Untuk menggunakan Azure Storage Service, Anda harus membuat dan mengonfigurasi Akun Penyimpanan di portal Azure.
Masuk ke Portal Microsoft Azure.
Catatan
Jika Anda belum memiliki akun Azure, Anda harus membuatnya. Jika Anda mengikuti tutorial ini dalam situasi ruang kelas atau lab, mintalah instruktur atau salah satu proktor untuk membantu menyiapkan akun baru Anda.
Setelah Anda masuk, klik Baru di sudut kiri atas, dan cari akun Penyimpanan, dan klik Enter.

Catatan
Kata Baru mungkin telah diganti dengan Buat sumber daya, di portal yang lebih baru.
Halaman baru akan memberikan deskripsi layanan akun Azure Storage. Di kiri bawah prompt ini, pilih tombol Buat , untuk membuat asosiasi dengan layanan ini.

Setelah Anda mengklik Buat:
Sisipkan Nama untuk akun Anda, ketahuilah bidang ini hanya menerima angka, dan huruf kecil.
Untuk Model penyebaran, pilih Resource manager.
Untuk Jenis akun, pilih Penyimpanan (tujuan umum v1).
Tentukan Lokasi untuk grup sumber daya Anda (jika Anda membuat Grup Sumber Daya baru). Lokasi idealnya akan berada di wilayah tempat aplikasi akan berjalan. Beberapa aset Azure hanya tersedia di wilayah tertentu.
Untuk Replikasi pilih Penyimpanan baca-akses-geo-redundan (RA-GRS).
Dalam Performa, pilih Standar.
Biarkan Transfer aman diperlukan sebagai Dinonaktifkan.
Pilih Langganan.
Pilih Grup Sumber Daya atau buat yang baru. Grup sumber daya menyediakan cara untuk memantau, mengontrol akses, menyediakan, dan mengelola penagihan untuk kumpulan aset Azure. Disarankan untuk menyimpan semua layanan Azure yang terkait dengan satu proyek (misalnya seperti lab ini) di bawah grup sumber daya umum).
Jika Anda ingin membaca selengkapnya tentang Grup Sumber Daya Azure, silakan kunjungi artikel grup sumber daya.
Anda juga perlu mengonfirmasi bahwa Anda telah memahami Syarat dan Ketentuan yang diterapkan pada Layanan ini.
Pilih Buat.

Setelah mengklik Buat, Anda harus menunggu layanan dibuat, ini mungkin memakan waktu satu menit.
Pemberitahuan akan muncul di portal setelah instans Layanan dibuat.

Klik pemberitahuan untuk menjelajahi instans Layanan baru Anda.

Klik tombol Buka sumber daya di pemberitahuan untuk menjelajahi instans Layanan baru Anda. Anda akan dibawa ke instans layanan akun Storage baru Anda.

Klik Kunci akses, untuk mengungkapkan titik akhir untuk layanan awan ini. Gunakan Notepad atau sejenisnya, untuk menyalin salah satu kunci Anda untuk digunakan nanti. Selain itu, perhatikan nilai String koneksi , karena akan digunakan di kelas AzureServices , yang akan Anda buat nanti.

Bab 2 - Menyiapkan Azure Function
Anda sekarang akan menulis Azure Function di Azure Service.
Anda dapat menggunakan Azure Function untuk melakukan hampir semua yang akan Anda lakukan dengan fungsi klasik dalam kode Anda, perbedaannya adalah fungsi ini dapat diakses oleh aplikasi apa pun yang memiliki kredensial untuk mengakses Akun Azure Anda.
Untuk membuat Azure Function:
Dari Portal Microsoft Azure Anda, klik Baru di sudut kiri atas, dan cari Aplikasi Fungsi, dan klik Enter.

Catatan
Kata Baru mungkin telah diganti dengan Buat sumber daya, di portal yang lebih baru.
Halaman baru akan memberikan deskripsi layanan Azure Function App . Di kiri bawah prompt ini, pilih tombol Buat , untuk membuat asosiasi dengan layanan ini.

Setelah Anda mengklik Buat:
Berikan Nama aplikasi. Hanya huruf dan angka yang dapat digunakan di sini (huruf besar atau kecil yang diizinkan).
Pilih Langganan pilihan Anda.
Pilih Grup Sumber Daya atau buat yang baru. Grup sumber daya menyediakan cara untuk memantau, mengontrol akses, menyediakan, dan mengelola penagihan untuk kumpulan aset Azure. Disarankan untuk menyimpan semua layanan Azure yang terkait dengan satu proyek (misalnya seperti lab ini) di bawah grup sumber daya umum).
Jika Anda ingin membaca selengkapnya tentang Grup Sumber Daya Azure, silakan kunjungi artikel grup sumber daya.
Untuk latihan ini, pilih Windows sebagai OS yang dipilih.
Pilih Paket Konsumsi untuk Paket Hosting.
Tentukan Lokasi untuk grup sumber daya Anda (jika Anda membuat Grup Sumber Daya baru). Lokasi idealnya akan berada di wilayah tempat aplikasi akan berjalan. Beberapa aset Azure hanya tersedia di wilayah tertentu. Untuk performa optimal, pilih wilayah yang sama dengan akun penyimpanan.
Untuk Penyimpanan, pilih Gunakan yang sudah ada, lalu gunakan menu dropdown, temukan penyimpanan yang anda buat sebelumnya.
Biarkan Application Insights nonaktif untuk latihan ini.

Klik tombol Buat.
Setelah mengklik Buat, Anda harus menunggu layanan dibuat, ini mungkin memakan waktu satu menit.
Pemberitahuan akan muncul di portal setelah instans Layanan dibuat.

Klik pemberitahuan untuk menjelajahi instans Layanan baru Anda.

Klik tombol Buka sumber daya di pemberitahuan untuk menjelajahi instans Layanan baru Anda. Anda akan dibawa ke instans layanan Aplikasi Fungsi baru Anda.
Pada dasbor Aplikasi Fungsi, arahkan mouse Anda ke Functions, yang ditemukan di dalam panel di sebelah kiri, lalu klik simbol + (plus).

Pada halaman berikutnya, pastikan Webhook + API dipilih, dan untuk Pilih bahasa, pilih CSharp, karena ini akan menjadi bahasa yang digunakan untuk tutorial ini. Terakhir, klik tombol Buat fungsi ini.

Anda harus dibawa ke halaman kode (run.csx), jika tidak, klik Fungsi yang baru dibuat di daftar Fungsi dalam panel di sebelah kiri.

Salin kode berikut ke fungsi Anda. Fungsi ini hanya akan mengembalikan bilangan bulat acak antara 0 dan 2 saat dipanggil. Jangan khawatir tentang kode yang ada, jangan ragu untuk menempel di atasnya.
using System.Net; using System.Threading.Tasks; public static int Run(CustomObject req, TraceWriter log) { Random rnd = new Random(); int randomInt = rnd.Next(0, 3); return randomInt; } public class CustomObject { public String name {get; set;} }Pilih Simpan.
Hasilnya akan terlihat seperti gambar di bawah ini.
Klik Dapatkan URL fungsi dan catat titik akhir yang ditampilkan. Anda harus memasukkannya ke kelas AzureServices yang akan Anda buat nanti dalam kursus ini.


Bab 3 - Menyiapkan proyek Unity
Berikut ini adalah pengaturan khas untuk mengembangkan dengan Mixed Reality, dan dengan demikian, adalah templat yang baik untuk proyek lain.
Siapkan dan uji headset imersif realitas campuran Anda.
Catatan
Anda tidak akan memerlukan Pengontrol Gerakan untuk kursus ini. Jika Anda memerlukan dukungan untuk menyiapkan headset imersif, silakan kunjungi artikel penyusunan realitas campuran.
Buka Unity dan klik Baru.

Anda sekarang perlu memberikan nama Proyek Unity. Sisipkan MR_Azure_Functions. Pastikan jenis proyek diatur ke 3D. Atur Lokasi ke tempat yang sesuai untuk Anda (ingat, lebih dekat ke direktori akar lebih baik). Lalu, klik Buat proyek.

Dengan Unity terbuka, ada baiknya memeriksa Editor Skrip default diatur ke Visual Studio. Buka Edit>Preferensi lalu dari jendela baru, navigasikan ke Alat Eksternal. Ubah Editor Skrip Eksternal ke Visual Studio 2017. Tutup jendela Preferensi .

Selanjutnya, buka Pengaturan Build File>dan alihkan platform ke Platform Windows Universal, dengan mengklik tombol Beralih Platform.

Buka Pengaturan Build File>dan pastikan bahwa:
Perangkat Target diatur ke Perangkat Apa Pun.
Untuk Microsoft HoloLens, atur Perangkat Target ke HoloLens.
Jenis Build diatur ke D3D
SDK diatur ke Terbaru diinstal
Versi Visual Studio diatur ke Terbaru diinstal
Build and Run diatur ke Komputer Lokal
Simpan adegan dan tambahkan ke build.
Lakukan ini dengan memilih Tambahkan Adegan Terbuka. Jendela penyimpanan akan muncul.

Buat folder baru untuk ini, dan adegan di masa mendatang, lalu pilih tombol Folder baru, untuk membuat folder baru, beri nama Adegan.

Buka folder Adegan yang baru dibuat, lalu di bidang Nama file: teks, ketik FunctionsScene, lalu tekan Simpan.

Pengaturan yang tersisa, di Pengaturan Build, harus dibiarkan sebagai default untuk saat ini.

Di jendela Pengaturan Build, klik tombol Pengaturan Pemutar, ini akan membuka panel terkait di ruang tempat Pemeriksa berada.

Di panel ini, beberapa pengaturan perlu diverifikasi:
Di tab Pengaturan Lainnya:
- Versi Runtime Pembuatan Skrip harus Eksperimental (Setara.NET 4.6), yang akan memicu kebutuhan untuk memulai ulang Editor.
- Scripting Backend harus .NET
- Tingkat Kompatibilitas API harus .NET 4.6
Dalam tab Pengaturan Penerbitan, di bawah Kemampuan, periksa:
InternetClient

Selanjutnya di bawah panel, di Pengaturan XR (ditemukan di bawah Pengaturan Penerbitan), centang Virtual Reality Didukung, pastikan Windows Mixed Reality SDK ditambahkan.

Kembali ke Pengaturan Build Proyek Unity C# tidak lagi berwarna abu-abu; centang kotak di samping ini.

Tutup jendela Pengaturan Build.
Simpan Adegan dan Proyek Anda (FILE>SAVE SCENE / FILE>SAVE PROJECT).
Bab 4 - Menyiapkan Kamera Utama
Penting
Jika Anda ingin melewati komponen Unity Siapkan kursus ini, dan lanjutkan langsung ke dalam kode, jangan ragu untuk mengunduh .unitypackage ini, dan mengimpornya ke proyek Anda sebagai Paket Kustom. Ini juga akan berisi DLL dari Bab berikutnya. Setelah impor, lanjutkan dari Bab 7.
Di Panel Hierarki, Anda akan menemukan objek yang disebut Kamera Utama, objek ini mewakili sudut pandang "kepala" Anda setelah Anda "berada di dalam" aplikasi Anda.
Dengan Dasbor Unity di depan Anda, pilih GameObject Kamera Utama. Anda akan melihat bahwa Panel Inspektur (umumnya ditemukan di sebelah kanan, di dalam Dasbor ) akan menampilkan berbagai komponen GameObject tersebut, dengan Transformasi di bagian atas, diikuti oleh Kamera, dan beberapa komponen lainnya. Anda harus mengatur ulang Transformasi Kamera Utama, sehingga diposisikan dengan benar.
Untuk melakukan ini, pilih ikon Gigi di samping komponen Transformasi Kamera, dan pilih Reset.

Kemudian perbarui komponen Transformasi agar terlihat seperti:
Transformasi - Posisi
| X | Y | Z |
|---|---|---|
| 0 | 1 | 0 |
Transformasi - Rotasi
| X | Y | Z |
|---|---|---|
| 0 | 0 | 0 |
Transformasi - Skala
| X | Y | Z |
|---|---|---|
| 1 | 1 | 1 |

Bab 5 - Menyiapkan adegan Unity
Klik kanan di area kosong Panel Hierarki, di bawah Objek 3D, tambahkan Bidang.

Dengan objek Bidang dipilih, ubah parameter berikut di Panel Inspektur:
Transformasi - Posisi
| X | Y | Z |
|---|---|---|
| 0 | 0 | 4 |
Transformasi - Skala
| X | Y | Z |
|---|---|---|
| 10 | 1 | 10 |


Klik kanan di area kosong Panel Hierarki, di bawah Objek 3D, tambahkan Kubus.
Ganti nama Kubus menjadi GazeButton (dengan Kubus dipilih, tekan 'F2').
Ubah parameter berikut untuk Posisi Transformasi di Panel Inspektur:
X Y Z 0 3 5 

Klik tombol drop-down Tag dan klik Tambahkan Tag untuk membuka Panel Tag & Lapisan.


Pilih tombol + (plus), dan di bidang Nama Tag Baru, masukkan GazeButton, dan tekan Simpan.

Klik objek GazeButton di Panel Hierarki, dan di Panel Inspektur, tetapkan tag GazeButton yang baru dibuat.

Klik kanan pada objek GazeButton, di Panel Hierarki, dan tambahkan GameObject Kosong (yang akan ditambahkan sebagai objek turunan).
Pilih objek baru dan ganti namanya menjadi ShapeSpawnPoint.
Ubah parameter berikut untuk Posisi Transformasi di Panel Inspektur:
X Y Z 0 -1 0 

Selanjutnya Anda akan membuat objek Teks 3D untuk memberikan umpan balik tentang status layanan Azure.
Klik kanan pada GazeButton di Panel Hierarki lagi dan tambahkan objek Teks 3D Objek>3D sebagai anak.

Ganti nama objek Teks 3D menjadi AzureStatusText.
Ubah objek AzureStatusText Transform Position sebagai berikut:
X Y Z 0 0 -0.6 Ubah objek AzureStatusText Transform Scale sebagai berikut: | X | Y | Z | :---: | :---: | :---: | | 0.1 | 0.1 | 0.1 |
Catatan
Jangan khawatir jika tampaknya di luar pusat, karena ini akan diperbaiki ketika komponen Text Mesh di bawah ini diperbarui.
Ubah komponen Text Mesh agar sesuai dengan di bawah ini:

Tip
Warna yang dipilih di sini adalah warna Hex: 000000FF, meskipun jangan ragu untuk memilih sendiri, cukup pastikan itu dapat dibaca.
Struktur Panel Hierarki Anda sekarang akan terlihat seperti ini:

Adegan Anda sekarang akan terlihat seperti ini:

Bab 6 - Impor Azure Storage untuk Unity
Anda akan menggunakan Azure Storage for Unity (yang memanfaatkan .Net SDK untuk Azure). Anda dapat membaca selengkapnya tentang ini di artikel Azure Storage for Unity.
Saat ini ada masalah yang diketahui di Unity yang mengharuskan plugin dikonfigurasi ulang setelah impor. Langkah-langkah ini (4 - 7 di bagian ini) tidak akan lagi diperlukan setelah bug diselesaikan.
Untuk mengimpor SDK ke dalam proyek Anda sendiri, pastikan Anda telah mengunduh '.unitypackage' terbaru dari GitHub. Kemudian, lakukan hal berikut:
Tambahkan file .unitypackage ke Unity dengan menggunakan opsi menu Paket Kustom Paket>Impor Aset.>
Dalam kotak Impor Paket Unity yang muncul, Anda dapat memilih semuanya di bawah Penyimpanan Plugin>. Hapus centang yang lain, karena tidak diperlukan untuk kursus ini.

Klik tombol Impor untuk menambahkan item ke proyek Anda.
Buka folder Penyimpanan di bawah Plugin, dalam tampilan Proyek, dan pilih plugin berikut saja:
Microsoft.Data.Edm
Microsoft.Data.OData
Microsoft.WindowsAzure.Storage
Newtonsoft.Json
System.Spatial

Dengan plugin khusus ini dipilih, hapus centang Platform Apa pun dan hapus centang WSAPlayer lalu klik Terapkan.

Catatan
Kami menandai plugin khusus ini untuk hanya digunakan di Editor Unity. Ini karena ada berbagai versi plugin yang sama di folder WSA yang akan digunakan setelah proyek diekspor dari Unity.
Di folder Plugin penyimpanan, pilih saja:
Microsoft.Data.Services.Client

Centang kotak Jangan Proses di bawah Pengaturan Platform dan klik Terapkan.

Catatan
Kami menandai plugin ini "Jangan proses" karena patcher rakitan Unity mengalami kesulitan memproses plugin ini. Plugin akan tetap berfungsi meskipun tidak diproses.
Bab 7 - Membuat kelas AzureServices
Kelas pertama yang akan Anda buat adalah kelas AzureServices .
Kelas AzureServices akan bertanggung jawab untuk:
Menyimpan kredensial Akun Azure.
Memanggil Azure App Function Anda.
Unggah dan unduh file data di Azure Cloud Storage Anda.
Untuk membuat Kelas ini:
Klik kanan di Folder Aset, yang terletak di Panel Proyek, Buat>Folder. Beri nama folder Skrip.


Klik dua kali pada folder yang baru saja dibuat, untuk membukanya.
Klik kanan di dalam folder, Buat>Skrip C#. Panggil skrip AzureServices.
Klik dua kali pada kelas AzureServices baru untuk membukanya dengan Visual Studio.
Tambahkan namespace berikut ke bagian atas AzureServices:
using System; using System.Threading.Tasks; using UnityEngine; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.File; using System.IO; using System.Net;Tambahkan Bidang Inspektur berikut di dalam kelas AzureServices :
/// <summary> /// Provides Singleton-like behavior to this class. /// </summary> public static AzureServices instance; /// <summary> /// Reference Target for AzureStatusText Text Mesh object /// </summary> public TextMesh azureStatusText;Kemudian tambahkan variabel anggota berikut di dalam kelas AzureServices :
/// <summary> /// Holds the Azure Function endpoint - Insert your Azure Function /// Connection String here. /// </summary> private readonly string azureFunctionEndpoint = "--Insert here you AzureFunction Endpoint--"; /// <summary> /// Holds the Storage Connection String - Insert your Azure Storage /// Connection String here. /// </summary> private readonly string storageConnectionString = "--Insert here you AzureStorage Connection String--"; /// <summary> /// Name of the Cloud Share - Hosts directories. /// </summary> private const string fileShare = "fileshare"; /// <summary> /// Name of a Directory within the Share /// </summary> private const string storageDirectory = "storagedirectory"; /// <summary> /// The Cloud File /// </summary> private CloudFile shapeIndexCloudFile; /// <summary> /// The Linked Storage Account /// </summary> private CloudStorageAccount storageAccount; /// <summary> /// The Cloud Client /// </summary> private CloudFileClient fileClient; /// <summary> /// The Cloud Share - Hosts Directories /// </summary> private CloudFileShare share; /// <summary> /// The Directory in the share that will host the Cloud file /// </summary> private CloudFileDirectory dir;Penting
Pastikan Anda mengganti titik akhir dan nilai string koneksi dengan nilai dari penyimpanan Azure Anda, yang ditemukan di Portal Microsoft Azure
Kode untuk metode Awake() dan Start() sekarang perlu ditambahkan. Metode ini akan dipanggil ketika kelas menginisialisasi:
private void Awake() { instance = this; } // Use this for initialization private void Start() { // Set the Status text to loading, whilst attempting connection to Azure. azureStatusText.text = "Loading..."; } /// <summary> /// Call to the Azure Function App to request a Shape. /// </summary> public async void CallAzureFunctionForNextShape() { }Hapus metode Update() karena kelas ini tidak akan menggunakannya.
Simpan perubahan Anda di Visual Studio, lalu kembali ke Unity.
Klik dan seret kelas AzureServices dari folder Skrip ke objek Kamera Utama di Panel Hierarki.
Pilih Kamera Utama, lalu ambil objek anak AzureStatusText dari bawah objek GazeButton , dan letakkan di dalam bidang target referensi AzureStatusText , di Inspektur, untuk memberikan referensi ke skrip AzureServices .

Bab 8 - Buat kelas ShapeFactory
Skrip berikutnya yang akan dibuat, adalah kelas ShapeFactory . Peran kelas ini adalah membuat bentuk baru, ketika diminta, dan menyimpan riwayat bentuk yang dibuat dalam Daftar Riwayat Bentuk. Setiap kali bentuk dibuat, daftar Riwayat Bentuk diperbarui di kelas AzureService, lalu disimpan di Azure Storage Anda. Saat aplikasi dimulai, jika file tersimpan ditemukan di Azure Storage Anda, daftar Riwayat Bentuk diambil dan diputar ulang, dengan objek Teks 3D yang menyediakan apakah bentuk yang dihasilkan berasal dari penyimpanan, atau baru.
Untuk membuat kelas ini:
Buka folder Skrip yang Anda buat sebelumnya.
Klik kanan di dalam folder, Buat>Skrip C#. Panggil skrip ShapeFactory.
Klik dua kali pada skrip ShapeFactory baru untuk membukanya dengan Visual Studio.
Pastikan kelas ShapeFactory menyertakan namespace berikut:
using System.Collections.Generic; using UnityEngine;Tambahkan variabel yang ditunjukkan di bawah ini ke kelas ShapeFactory , dan ganti fungsi Start() dan Awake() dengan yang di bawah ini:
/// <summary> /// Provide this class Singleton-like behaviour /// </summary> [HideInInspector] public static ShapeFactory instance; /// <summary> /// Provides an Inspector exposed reference to ShapeSpawnPoint /// </summary> [SerializeField] public Transform spawnPoint; /// <summary> /// Shape History Index /// </summary> [HideInInspector] public List<int> shapeHistoryList; /// <summary> /// Shapes Enum for selecting required shape /// </summary> private enum Shapes { Cube, Sphere, Cylinder } private void Awake() { instance = this; } private void Start() { shapeHistoryList = new List<int>(); }Metode CreateShape() menghasilkan bentuk primitif, berdasarkan parameter bilangan bulat yang disediakan. Parameter Boolean digunakan untuk menentukan apakah bentuk yang saat ini dibuat berasal dari penyimpanan, atau baru. Tempatkan kode berikut di kelas ShapeFactory Anda, di bawah metode sebelumnya:
/// <summary> /// Use the Shape Enum to spawn a new Primitive object in the scene /// </summary> /// <param name="shape">Enumerator Number for Shape</param> /// <param name="storageShape">Provides whether this is new or old</param> internal void CreateShape(int shape, bool storageSpace) { Shapes primitive = (Shapes)shape; GameObject newObject = null; string shapeText = storageSpace == true ? "Storage: " : "New: "; AzureServices.instance.azureStatusText.text = string.Format("{0}{1}", shapeText, primitive.ToString()); switch (primitive) { case Shapes.Cube: newObject = GameObject.CreatePrimitive(PrimitiveType.Cube); break; case Shapes.Sphere: newObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); break; case Shapes.Cylinder: newObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder); break; } if (newObject != null) { newObject.transform.position = spawnPoint.position; newObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); newObject.AddComponent<Rigidbody>().useGravity = true; newObject.GetComponent<Renderer>().material.color = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f); } }Pastikan untuk menyimpan perubahan Anda di Visual Studio sebelum kembali ke Unity.
Kembali ke Editor Unity, klik dan seret kelas ShapeFactory dari folder Skrip ke objek Kamera Utama di Panel Hierarki.
Dengan Kamera Utama yang dipilih, Anda akan melihat komponen skrip ShapeFactory tidak memiliki referensi Spawn Point . Untuk memperbaikinya, seret objek ShapeSpawnPoint dari Panel Hierarki ke target referensi Spawn Point .

Bab 9 - Buat kelas Tatap
Skrip terakhir yang perlu Anda buat adalah kelas Tatap.
Kelas ini bertanggung jawab untuk membuat Raycast yang akan diproyeksikan ke depan dari Kamera Utama, untuk mendeteksi objek mana yang dilihat pengguna. Dalam hal ini, Raycast perlu mengidentifikasi apakah pengguna melihat objek GazeButton di adegan dan memicu perilaku.
Untuk membuat Kelas ini:
Buka folder Skrip yang Anda buat sebelumnya.
Klik kanan di Panel Proyek, Buat>Skrip C#. Panggil tatap naskah.
Klik dua kali pada skrip Tatap baru untuk membukanya dengan Visual Studio.
Pastikan namespace berikut disertakan di bagian atas skrip:
using UnityEngine;Kemudian tambahkan variabel berikut di dalam kelas Tatap:
/// <summary> /// Provides Singleton-like behavior to this class. /// </summary> public static Gaze instance; /// <summary> /// The Tag which the Gaze will use to interact with objects. Can also be set in editor. /// </summary> public string InteractibleTag = "GazeButton"; /// <summary> /// The layer which will be detected by the Gaze ('~0' equals everything). /// </summary> public LayerMask LayerMask = ~0; /// <summary> /// The Max Distance the gaze should travel, if it has not hit anything. /// </summary> public float GazeMaxDistance = 300; /// <summary> /// The size of the cursor, which will be created. /// </summary> public Vector3 CursorSize = new Vector3(0.05f, 0.05f, 0.05f); /// <summary> /// The color of the cursor - can be set in editor. /// </summary> public Color CursorColour = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f); /// <summary> /// Provides when the gaze is ready to start working (based upon whether /// Azure connects successfully). /// </summary> internal bool GazeEnabled = false; /// <summary> /// The currently focused object. /// </summary> internal GameObject FocusedObject { get; private set; } /// <summary> /// The object which was last focused on. /// </summary> internal GameObject _oldFocusedObject { get; private set; } /// <summary> /// The info taken from the last hit. /// </summary> internal RaycastHit HitInfo { get; private set; } /// <summary> /// The cursor object. /// </summary> internal GameObject Cursor { get; private set; } /// <summary> /// Provides whether the raycast has hit something. /// </summary> internal bool Hit { get; private set; } /// <summary> /// This will store the position which the ray last hit. /// </summary> internal Vector3 Position { get; private set; } /// <summary> /// This will store the normal, of the ray from its last hit. /// </summary> internal Vector3 Normal { get; private set; } /// <summary> /// The start point of the gaze ray cast. /// </summary> private Vector3 _gazeOrigin; /// <summary> /// The direction in which the gaze should be. /// </summary> private Vector3 _gazeDirection;
Penting
Beberapa variabel ini akan dapat diedit di Editor.
Kode untuk metode Awake() dan Start() sekarang perlu ditambahkan.
/// <summary> /// The method used after initialization of the scene, though before Start(). /// </summary> private void Awake() { // Set this class to behave similar to singleton instance = this; } /// <summary> /// Start method used upon initialization. /// </summary> private void Start() { FocusedObject = null; Cursor = CreateCursor(); }Tambahkan kode berikut, yang akan membuat objek kursor pada awalnya, bersama dengan metode Update(), yang akan menjalankan metode Raycast, bersama dengan tempat boolean GazeEnabled dialihkan:
/// <summary> /// Method to create a cursor object. /// </summary> /// <returns></returns> private GameObject CreateCursor() { GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere); newCursor.SetActive(false); // Remove the collider, so it doesn't block raycast. Destroy(newCursor.GetComponent<SphereCollider>()); newCursor.transform.localScale = CursorSize; newCursor.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse")) { color = CursorColour }; newCursor.name = "Cursor"; newCursor.SetActive(true); return newCursor; } /// <summary> /// Called every frame /// </summary> private void Update() { if(GazeEnabled == true) { _gazeOrigin = Camera.main.transform.position; _gazeDirection = Camera.main.transform.forward; UpdateRaycast(); } }Selanjutnya tambahkan metode UpdateRaycast(), yang akan memproyeksikan Raycast dan mendeteksi target hit.
private void UpdateRaycast() { // Set the old focused gameobject. _oldFocusedObject = FocusedObject; RaycastHit hitInfo; // Initialise Raycasting. Hit = Physics.Raycast(_gazeOrigin, _gazeDirection, out hitInfo, GazeMaxDistance, LayerMask); HitInfo = hitInfo; // Check whether raycast has hit. if (Hit == true) { Position = hitInfo.point; Normal = hitInfo.normal; // Check whether the hit has a collider. if (hitInfo.collider != null) { // Set the focused object with what the user just looked at. FocusedObject = hitInfo.collider.gameObject; } else { // Object looked on is not valid, set focused gameobject to null. FocusedObject = null; } } else { // No object looked upon, set focused gameobject to null. FocusedObject = null; // Provide default position for cursor. Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance); // Provide a default normal. Normal = _gazeDirection; } // Lerp the cursor to the given position, which helps to stabilize the gaze. Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f); // Check whether the previous focused object is this same // object. If so, reset the focused object. if (FocusedObject != _oldFocusedObject) { ResetFocusedObject(); if (FocusedObject != null) { if (FocusedObject.CompareTag(InteractibleTag.ToString())) { // Set the Focused object to green - success! FocusedObject.GetComponent<Renderer>().material.color = Color.green; // Start the Azure Function, to provide the next shape! AzureServices.instance.CallAzureFunctionForNextShape(); } } } }Terakhir, tambahkan metode ResetFocusedObject(), yang akan mengalihkan warna objek GazeButton saat ini, yang menunjukkan apakah itu membuat bentuk baru atau tidak.
/// <summary> /// Reset the old focused object, stop the gaze timer, and send data if it /// is greater than one. /// </summary> private void ResetFocusedObject() { // Ensure the old focused object is not null. if (_oldFocusedObject != null) { if (_oldFocusedObject.CompareTag(InteractibleTag.ToString())) { // Set the old focused object to red - its original state. _oldFocusedObject.GetComponent<Renderer>().material.color = Color.red; } } }Simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.
Klik dan seret kelas Tatap dari folder Skrip ke objek Kamera Utama di Panel Hierarki.
Bab 10 - Menyelesaikan kelas AzureServices
Dengan skrip lain di tempat, sekarang dimungkinkan untuk menyelesaikan kelas AzureServices. Ini akan dicapai melalui:
Menambahkan metode baru bernama CreateCloudIdentityAsync(), untuk menyiapkan variabel autentikasi yang diperlukan untuk berkomunikasi dengan Azure.
Metode ini juga akan memeriksa keberadaan File yang disimpan sebelumnya yang berisi Daftar Bentuk.
Jika file ditemukan, file akan menonaktifkan tatapan pengguna, dan memicu Pembuatan bentuk, sesuai dengan pola bentuk, seperti yang disimpan dalam file Azure Storage. Pengguna dapat melihat ini, karena Text Mesh akan menyediakan tampilan 'Storage' atau 'New', tergantung pada asal bentuk.
Jika tidak ada file yang ditemukan, itu akan mengaktifkan Tatapan, memungkinkan pengguna untuk membuat bentuk saat melihat objek GazeButton di adegan.
/// <summary> /// Create the references necessary to log into Azure /// </summary> private async void CreateCloudIdentityAsync() { // Retrieve storage account information from connection string storageAccount = CloudStorageAccount.Parse(storageConnectionString); // Create a file client for interacting with the file service. fileClient = storageAccount.CreateCloudFileClient(); // Create a share for organizing files and directories within the storage account. share = fileClient.GetShareReference(fileShare); await share.CreateIfNotExistsAsync(); // Get a reference to the root directory of the share. CloudFileDirectory root = share.GetRootDirectoryReference(); // Create a directory under the root directory dir = root.GetDirectoryReference(storageDirectory); await dir.CreateIfNotExistsAsync(); //Check if the there is a stored text file containing the list shapeIndexCloudFile = dir.GetFileReference("TextShapeFile"); if (!await shapeIndexCloudFile.ExistsAsync()) { // File not found, enable gaze for shapes creation Gaze.instance.GazeEnabled = true; azureStatusText.text = "No Shape\nFile!"; } else { // The file has been found, disable gaze and get the list from the file Gaze.instance.GazeEnabled = false; azureStatusText.text = "Shape File\nFound!"; await ReplicateListFromAzureAsync(); } }Cuplikan kode berikutnya berasal dari dalam metode Start() ; di mana panggilan akan dilakukan ke metode CreateCloudIdentityAsync(). Jangan ragu untuk menyalin metode Start() Anda saat ini, dengan yang di bawah ini:
private void Start() { // Disable TLS cert checks only while in Unity Editor (until Unity adds support for TLS) #if UNITY_EDITOR ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; #endif // Set the Status text to loading, whilst attempting connection to Azure. azureStatusText.text = "Loading..."; //Creating the references necessary to log into Azure and check if the Storage Directory is empty CreateCloudIdentityAsync(); }Isi kode untuk metode CallAzureFunctionForNextShape(). Anda akan menggunakan Azure Function App yang dibuat sebelumnya untuk meminta indeks bentuk. Setelah bentuk baru diterima, metode ini akan mengirim bentuk ke kelas ShapeFactory untuk membuat bentuk baru di adegan. Gunakan kode di bawah ini untuk menyelesaikan isi CallAzureFunctionForNextShape().
/// <summary> /// Call to the Azure Function App to request a Shape. /// </summary> public async void CallAzureFunctionForNextShape() { int azureRandomInt = 0; // Call Azure function HttpWebRequest webRequest = WebRequest.CreateHttp(azureFunctionEndpoint); WebResponse response = await webRequest.GetResponseAsync(); // Read response as string using (Stream stream = response.GetResponseStream()) { StreamReader reader = new StreamReader(stream); String responseString = reader.ReadToEnd(); //parse result as integer Int32.TryParse(responseString, out azureRandomInt); } //add random int from Azure to the ShapeIndexList ShapeFactory.instance.shapeHistoryList.Add(azureRandomInt); ShapeFactory.instance.CreateShape(azureRandomInt, false); //Save to Azure storage await UploadListToAzureAsync(); }Tambahkan metode untuk membuat string, dengan menggabungkan bilangan bulat yang disimpan dalam daftar riwayat bentuk, dan menyimpannya di File Azure Storage Anda.
/// <summary> /// Upload the locally stored List to Azure /// </summary> private async Task UploadListToAzureAsync() { // Uploading a local file to the directory created above string listToString = string.Join(",", ShapeFactory.instance.shapeHistoryList.ToArray()); await shapeIndexCloudFile.UploadTextAsync(listToString); }Tambahkan metode untuk mengambil teks yang disimpan dalam file yang terletak di File Azure Storage Anda dan deserialisasi ke dalam daftar.
Setelah proses ini selesai, metode mengaktifkan kembali pandangan sehingga pengguna dapat menambahkan lebih banyak bentuk ke adegan.
///<summary> /// Get the List stored in Azure and use the data retrieved to replicate /// a Shape creation pattern ///</summary> private async Task ReplicateListFromAzureAsync() { string azureTextFileContent = await shapeIndexCloudFile.DownloadTextAsync(); string[] shapes = azureTextFileContent.Split(new char[] { ',' }); foreach (string shape in shapes) { int i; Int32.TryParse(shape.ToString(), out i); ShapeFactory.instance.shapeHistoryList.Add(i); ShapeFactory.instance.CreateShape(i, true); await Task.Delay(500); } Gaze.instance.GazeEnabled = true; azureStatusText.text = "Load Complete!"; }Simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.
Bab 11 - Bangun Solusi UWP
Untuk memulai proses Build:
Buka Pengaturan Penyusunan File>.

Klik Bangun. Unity akan meluncurkan jendela File Explorer , tempat Anda perlu membuat lalu memilih folder untuk membangun aplikasi. Buat folder tersebut sekarang, dan beri nama Aplikasi. Kemudian dengan folder Aplikasi dipilih, tekan Pilih Folder.
Unity akan mulai membangun proyek Anda ke folder Aplikasi .
Setelah Unity selesai membangun (mungkin perlu waktu), Unity akan membuka jendela File Explorer di lokasi build Anda (periksa bilah tugas Anda, karena mungkin tidak selalu muncul di atas jendela Anda, tetapi akan memberi tahu Anda tentang penambahan jendela baru).
Bab 12 - Menyebarkan aplikasi Anda
Untuk menyebarkan aplikasi Anda:
Navigasikan ke folder Aplikasi yang dibuat di Bab terakhir. Anda akan melihat file dengan nama aplikasi Anda, dengan ekstensi '.sln', yang harus Anda klik dua kali, jadi untuk membukanya dalam Visual Studio.
Di Platform Solusi, pilih x86, Komputer Lokal.
Di Konfigurasi Solusi pilih Debug.
Untuk Microsoft HoloLens, Anda mungkin merasa lebih mudah untuk mengatur ini ke Komputer Jarak Jauh, sehingga Anda tidak tertambat ke komputer Anda. Meskipun, Anda juga harus melakukan hal berikut:
- Ketahui Alamat IP HoloLens Anda, yang dapat ditemukan dalam Jaringan Pengaturan>& Opsi Tingkat Lanjut Wi-Fi>Internet>; IPv4 adalah alamat yang harus Anda gunakan.
- Pastikan Mode Pengembang Aktif; ditemukan di Pengaturan>Pembaruan & Keamanan>Untuk pengembang.

Buka menu Build dan klik Sebarkan Solusi untuk memuat samping aplikasi ke komputer Anda.
Aplikasi Anda sekarang akan muncul dalam daftar aplikasi yang diinstal, siap untuk diluncurkan dan diuji!
Aplikasi Azure Functions dan Storage Anda yang sudah selesai
Selamat, Anda membangun aplikasi realitas campuran yang memanfaatkan layanan Azure Functions dan Azure Storage. Aplikasi Anda akan dapat menggambar data yang disimpan, dan memberikan tindakan berdasarkan data tersebut.

Latihan bonus
Latihan 1
Buat titik spawn kedua dan rekam dari titik spawn mana objek dibuat. Saat Anda memuat file data, putar ulang bentuk yang dihasilkan dari lokasi awalnya dibuat.
Latihan 2
Buat cara untuk menghidupkan ulang aplikasi, daripada harus membukanya kembali setiap kali. Memuat Adegan adalah tempat yang bagus untuk memulai. Setelah melakukannya, buat cara untuk menghapus daftar tersimpan di Azure Storage, sehingga dapat dengan mudah diatur ulang dari aplikasi Anda.