Bagikan melalui


HoloLens (generasi ke-1) dan Azure 311 - Microsoft Graph

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 menggunakan Microsoft Graph untuk masuk ke akun Microsoft Anda menggunakan autentikasi aman dalam aplikasi realitas campuran. Anda kemudian akan mengambil dan menampilkan rapat terjadwal Anda di antarmuka aplikasi.

Cuplikan layar yang memperlihatkan rapat terjadwal di antarmuka aplikasi.

Microsoft Graph adalah sekumpulan API yang dirancang untuk memungkinkan akses ke banyak layanan Microsoft. Microsoft menjelaskan Microsoft Graph sebagai matriks sumber daya yang terhubung oleh hubungan, yang berarti memungkinkan aplikasi untuk mengakses semua jenis data pengguna yang terhubung. Untuk informasi selengkapnya, kunjungi halaman Microsoft Graph.

Pengembangan akan mencakup pembuatan aplikasi tempat pengguna akan diinstruksikan untuk menatap dan kemudian mengetuk bola, yang akan meminta pengguna untuk masuk dengan aman ke akun Microsoft. Setelah masuk ke akun mereka, pengguna akan dapat melihat daftar rapat yang dijadwalkan untuk hari itu.

Setelah menyelesaikan kursus ini, Anda akan memiliki aplikasi HoloLens realitas campuran, yang akan dapat melakukan hal berikut:

  1. Menggunakan gerakan Ketuk, ketuk objek, yang akan meminta pengguna untuk masuk ke Akun Microsoft (keluar dari aplikasi untuk masuk, lalu kembali ke aplikasi lagi).
  2. Menampilkan daftar rapat yang dijadwalkan untuk hari itu.

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. Ini 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 311: Microsoft Graph ✔️

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 (Juli 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:

Sebelum memulai

  1. 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).
  2. Siapkan dan uji HoloLens Anda. Jika Anda memerlukan dukungan untuk menyiapkan HoloLens Anda, pastikan untuk mengunjungi artikel penyiapan HoloLens.
  3. Sebaiknya lakukan Kalibrasi dan Penyetelan Sensor saat mulai mengembangkan Aplikasi HoloLens baru (terkadang dapat membantu melakukan tugas tersebut untuk setiap pengguna).

Untuk bantuan tentang Kalibrasi, silakan ikuti tautan ini ke artikel Kalibrasi HoloLens.

Untuk bantuan tentang Penyetelan Sensor, silakan ikuti tautan ini ke artikel Penyetelan Sensor HoloLens.

Bab 1 - Buat aplikasi Anda di Portal Pendaftaran Aplikasi

Untuk memulainya, Anda harus membuat dan mendaftarkan aplikasi Anda di Portal Pendaftaran Aplikasi.

Dalam Bab ini Anda juga akan menemukan Kunci Layanan yang akan memungkinkan Anda melakukan panggilan ke Microsoft Graph untuk mengakses konten akun Anda.

  1. Buka Portal Pendaftaran Aplikasi Microsoft dan masuk dengan Akun Microsoft Anda. Setelah masuk, Anda akan diarahkan ke Portal Pendaftaran Aplikasi.

  2. Di bagian Aplikasi saya , klik tombol Tambahkan aplikasi.

    Cuplikan layar yang memperlihatkan tempat untuk memilih Tambahkan aplikasi.

    Penting

    Portal Pendaftaran Aplikasi dapat terlihat berbeda, tergantung pada apakah Anda sebelumnya telah bekerja dengan Microsoft Graph. Cuplikan layar di bawah ini menampilkan versi yang berbeda ini.

  3. Tambahkan nama untuk aplikasi Anda dan klik Buat.

    Cuplikan layar yang memperlihatkan tempat menambahkan nama untuk aplikasi Anda.

  4. Setelah aplikasi dibuat, Anda akan diarahkan ke halaman utama aplikasi. Salin Id Aplikasi dan pastikan untuk mencatat nilai ini di tempat yang aman, Anda akan segera menggunakannya dalam kode Anda.

    Cuplikan layar yang memperlihatkan tempat untuk melihat Id Aplikasi.

  5. Di bagian Platform , pastikan Aplikasi Asli ditampilkan. Jika tidak klik Tambahkan Platform dan pilih Aplikasi Asli.

    Cuplikan layar yang menyoroti bagian Aplikasi Asli.

  6. Gulir ke bawah di halaman yang sama dan di bagian yang disebut Izin Microsoft Graph, Anda harus menambahkan izin tambahan untuk aplikasi. Klik Tambahkan di samping Izin yang Didelegasikan.

    Cuplikan layar yang memperlihatkan tempat untuk memilih Tambahkan di samping Izin yang Didelegasikan.

  7. Karena Anda ingin aplikasi Anda mengakses Kalender pengguna, centang kotak yang disebut Calendars.Read dan klik OK.

    Cuplikan layar yang memperlihatkan kotak centang Calendars.Read.

  8. Gulir ke bawah dan klik tombol Simpan .

    Cuplikan layar yang memperlihatkan tempat untuk memilih Simpan.

  9. Penyimpanan Anda akan dikonfirmasi, dan Anda dapat keluar dari Portal Pendaftaran Aplikasi.

Bab 2 - Menyiapkan proyek Unity

Berikut ini adalah pengaturan khas untuk mengembangkan dengan realitas campuran, dan dengan demikian, adalah templat yang baik untuk proyek lain.

  1. Buka Unity dan klik Baru.

    Cuplikan layar yang memperlihatkan antarmuka Unity.

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

    Cuplikan layar yang memperlihatkan tempat untuk memilih Buat Proyek.

  3. 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 .

    Cuplikan layar yang memperlihatkan tempat mengatur Editor Skrip Eksternal ke Visual Studio 2017.

  4. Buka Pengaturan Build File>dan pilih Platform Windows Universal, lalu klik tombol Alihkan Platform untuk menerapkan pilihan Anda.

    Cuplikan layar yang memperlihatkan tempat untuk memilih Beralih Platform.

  5. Saat masih dalam >Pengaturan File Build, pastikan bahwa:

    1. Perangkat Target diatur ke HoloLens

    2. Jenis Build diatur ke D3D

    3. SDK diatur ke Terbaru diinstal

    4. Versi Visual Studio diatur ke Terbaru diinstal

    5. Build and Run diatur ke Komputer Lokal

    6. Simpan adegan dan tambahkan ke build.

      1. Lakukan ini dengan memilih Tambahkan Adegan Terbuka. Jendela penyimpanan akan muncul.

        Cuplikan layar yang memperlihatkan tempat untuk memilih Tambahkan Adegan Terbuka.

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

        Cuplikan layar yang memperlihatkan tempat untuk memberi nama folder baru.

      3. Buka folder Adegan yang baru dibuat, lalu di bidang Nama file: teks, ketik MR_ComputerVisionScene, lalu klik Simpan.

        Cuplikan layar yang memperlihatkan tempat mengetik nama file.

        Penting

        Ketahuilah, Anda harus menyimpan adegan Unity Anda dalam folder Aset , karena harus dikaitkan dengan proyek Unity. Membuat folder adegan (dan folder serupa lainnya) adalah cara umum untuk menyusun proyek Unity.

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

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

    Cuplikan layar yang memperlihatkan kotak dialog Pengaturan Pemutar.

  7. Di panel ini, beberapa pengaturan perlu diverifikasi:

    1. Di tab Pengaturan Lainnya:

      1. Versi Runtime Pembuatan Skrip harus Eksperimental (Setara.NET 4.6), yang akan memicu kebutuhan untuk memulai ulang Editor.

      2. Scripting Backend harus .NET

      3. Tingkat Kompatibilitas API harus .NET 4.6

        Cuplikan layar yang menunjukkan tempat untuk memeriksa tingkat kompatibilitas API.

    2. Dalam tab Pengaturan Penerbitan, di bawah Kemampuan, periksa:

      • InternetClient

        Cuplikan layar yang memperlihatkan tempat untuk memilih opsi InternetClient.

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

      Cuplikan layar yang menunjukkan tempat untuk menambahkan Windows Mixed Reality SDK.

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

  9. Tutup jendela Pengaturan Build.

  10. Simpan adegan dan proyek Anda (FILE>SAVE SCENES / FILE>SAVE PROJECT).

Bab 3 - Impor Pustaka di Unity

Penting

Jika Anda ingin melewati komponen Unity Siapkan kursus ini, dan lanjutkan langsung ke dalam kode, jangan ragu untuk mengunduh Paket Azure-MR-311.unity ini, impor ke proyek Anda sebagai Paket Kustom, lalu lanjutkan dari Bab 5.

Untuk menggunakan Microsoft Graph dalam Unity, Anda perlu menggunakan DLL Microsoft.Identity.Client . Dimungkinkan untuk menggunakan Microsoft Graph SDK, namun, ini akan memerlukan penambahan paket NuGet setelah Anda membangun proyek Unity (yang berarti mengedit proyek pasca-build). Dianggap lebih sederhana untuk mengimpor DLL yang diperlukan langsung ke Unity.

Catatan

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 Microsoft Graph ke proyek Anda sendiri, unduh file MSGraph_LabPlugins.zip. Paket ini telah dibuat dengan versi pustaka yang telah diuji.

Jika Anda ingin tahu lebih banyak tentang cara menambahkan DLL kustom ke proyek Unity Anda, ikuti tautan ini.

Untuk mengimpor paket:

  1. Tambahkan Paket Unity ke Unity dengan menggunakan opsi menu Paket Kustom Paket>Impor Aset.> Pilih paket yang baru saja Anda unduh.

  2. Dalam kotak Impor Paket Unity yang muncul, pastikan semuanya di bawah (dan termasuk) Plugin dipilih.

    Cuplikan layar yang memperlihatkan parameter konfigurasi yang dipilih di bawah Plugin.

  3. Klik tombol Impor untuk menambahkan item ke proyek Anda.

  4. Buka folder MSGraph di bawah Plugin di Panel Proyek dan pilih plugin yang disebut Microsoft.Identity.Client.

    Cuplikan layar yang memperlihatkan plugin Microsoft.Identity.Client.

  5. Dengan plugin yang dipilih, pastikan bahwa Platform Apa pun tidak dicentang, lalu pastikan bahwa WSAPlayer juga tidak dicentang, lalu klik Terapkan. Ini hanya untuk mengonfirmasi bahwa file dikonfigurasi dengan benar.

    Cuplikan layar yang menunjukkan tempat untuk mengonfirmasi bahwa Platform apa pun dan WSAPlayer tidak dicentang.

    Catatan

    Menandai plugin ini mengonfigurasinya untuk hanya digunakan di Editor Unity. Ada sekumpulan DLL yang berbeda di folder WSA yang akan digunakan setelah proyek diekspor dari Unity sebagai Aplikasi Windows Universal.

  6. Selanjutnya, Anda perlu membuka folder WSA , di dalam folder MSGraph . Anda akan melihat salinan file yang sama yang baru saja Anda konfigurasikan. Pilih file, lalu di pemeriksa:

    • pastikan bahwa Platform Apa pun tidak dicentang, dan hanya WSAPlayer yang diperiksa.

    • Pastikan SDK diatur ke UWP, dan Backend Scripting diatur ke Dot Net

    • Pastikan bahwa Jangan proses dicentang.

      Cuplikan layar yang menunjukkan bahwa Jangan Proses dipilih.

  7. Klik Terapkan.

Bab 4 - Penyiapan Kamera

Selama Bab ini, Anda akan menyiapkan Kamera Utama adegan Anda:

  1. Di Panel Hierarki, pilih Kamera Utama.

  2. Setelah dipilih, Anda akan dapat melihat semua komponen Kamera Utama di panel Inspektur .

    1. Objek Kamera harus diberi nama Kamera Utama (perhatikan ejaan!)

    2. Tag Kamera Utama harus diatur ke MainCamera (perhatikan ejaan!)

    3. Pastikan Posisi Transformasi diatur ke 0, 0, 0

    4. Atur Hapus Bendera ke Warna Solid

    5. Atur Warna Latar Belakang Komponen Kamera ke Hitam, Alpha 0 (Kode Hex: #00000000)

      Cuplikan layar yang menyoroti tempat mengatur warna latar belakang.

  3. Struktur objek akhir di Panel Hierarki harus seperti yang ditunjukkan pada gambar di bawah ini:

    Cuplikan layar yang memperlihatkan struktur objek akhir di Panel Hierarki.

Bab 5 - Membuat kelas MeetingsUI

Skrip pertama yang perlu Anda buat adalah MeetingsUI, yang bertanggung jawab untuk menghosting dan mengisi UI aplikasi (pesan selamat datang, instruksi, dan detail rapat).

Untuk membuat kelas ini:

  1. Klik kanan pada folder Aset di Panel Proyek, lalu pilih Buat>Folder. Beri nama folder Skrip.

    Cuplikan layar yang memperlihatkan tempat menemukan folder Aset.Cuplikan layar yang memperlihatkan tempat untuk membuat folder Skrip.

  2. Buka folder Skrip lalu, di dalam folder tersebut, klik kanan, Buat>Skrip C#. Beri nama skrip MeetingsUI.

    Cuplikan layar yang memperlihatkan tempat untuk membuat folder MeetingsUI.

  3. Klik dua kali pada skrip MeetingsUI baru untuk membukanya dengan Visual Studio.

  4. Sisipkan namespace berikut:

    using System;
    using UnityEngine;
    
  5. Di dalam kelas sisipkan variabel berikut:

        /// <summary>
        /// Allows this class to behave like a singleton
        /// </summary>
        public static MeetingsUI Instance;
    
        /// <summary>
        /// The 3D text of the scene
        /// </summary>
        private TextMesh _meetingDisplayTextMesh;
    
  6. Kemudian ganti metode Start() dan tambahkan metode Awake(). Ini akan dipanggil ketika kelas menginisialisasi:

        /// <summary>
        /// Called on initialization
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        void Start ()
        {
            // Creating the text mesh within the scene
            _meetingDisplayTextMesh = CreateMeetingsDisplay();
        }
    
  7. Tambahkan metode yang bertanggung jawab untuk membuat UI Rapat dan isi dengan rapat saat ini saat diminta:

        /// <summary>
        /// Set the welcome message for the user
        /// </summary>
        internal void WelcomeUser(string userName)
        {
            if(!string.IsNullOrEmpty(userName))
            {
                _meetingDisplayTextMesh.text = $"Welcome {userName}";
            }
            else 
            {
                _meetingDisplayTextMesh.text = "Welcome";
            }
        }
    
        /// <summary>
        /// Set up the parameters for the UI text
        /// </summary>
        /// <returns>Returns the 3D text in the scene</returns>
        private TextMesh CreateMeetingsDisplay()
        {
            GameObject display = new GameObject();
            display.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f);
            display.transform.position = new Vector3(-3.5f, 2f, 9f);
            TextMesh textMesh = display.AddComponent<TextMesh>();
            textMesh.anchor = TextAnchor.MiddleLeft;
            textMesh.alignment = TextAlignment.Left;
            textMesh.fontSize = 80;
            textMesh.text = "Welcome! \nPlease gaze at the button" +
                "\nand use the Tap Gesture to display your meetings";
    
            return textMesh;
        }
    
        /// <summary>
        /// Adds a new Meeting in the UI by chaining the existing UI text
        /// </summary>
        internal void AddMeeting(string subject, DateTime dateTime, string location)
        {
            string newText = $"\n{_meetingDisplayTextMesh.text}\n\n Meeting,\nSubject: {subject},\nToday at {dateTime},\nLocation: {location}";
    
            _meetingDisplayTextMesh.text = newText;
        }
    
  8. Hapus metode Update(), dan simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.

Bab 6 - Buat kelas Grafik

Skrip berikutnya yang akan dibuat adalah skrip Grafik . Skrip ini bertanggung jawab untuk melakukan panggilan untuk mengautentikasi pengguna dan mengambil rapat terjadwal untuk hari ini dari kalender pengguna.

Untuk membuat kelas ini:

  1. Klik dua kali pada folder Skrip , untuk membukanya.

  2. Klik kanan di dalam folder Skrip, klik Buat>Skrip C#. Beri nama Grafik skrip.

  3. Klik dua kali pada skrip untuk membukanya dengan Visual Studio.

  4. Sisipkan namespace berikut:

    using System.Collections.Generic;
    using UnityEngine;
    using Microsoft.Identity.Client;
    using System;
    using System.Threading.Tasks;
    
    #if !UNITY_EDITOR && UNITY_WSA
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Windows.Storage;
    #endif
    

    Penting

    Anda akan melihat bahwa bagian kode dalam skrip ini dibungkus di sekitar Arahan Prekompilasi, ini untuk menghindari masalah dengan pustaka saat membangun Solusi Visual Studio.

  5. Hapus metode Start() dan Update(), karena tidak akan digunakan.

  6. Di luar kelas Grafik, sisipkan objek berikut, yang diperlukan untuk mendeserialisasi objek JSON yang mewakili rapat terjadwal harian:

    /// <summary>
    /// The object hosting the scheduled meetings
    /// </summary>
    [Serializable]
    public class Rootobject
    {
        public List<Value> value;
    }
    
    [Serializable]
    public class Value
    {
        public string subject { get; set; }
        public StartTime start { get; set; }
        public Location location { get; set; }
    }
    
    [Serializable]
    public class StartTime
    {
        public string dateTime;
    
        private DateTime? _startDateTime;
        public DateTime StartDateTime
        {
            get
            {
                if (_startDateTime != null)
                    return _startDateTime.Value;
                DateTime dt;
                DateTime.TryParse(dateTime, out dt);
                _startDateTime = dt;
                return _startDateTime.Value;
            }
        }
    }
    
    [Serializable]
    public class Location
    {
        public string displayName { get; set; }
    }
    
  7. Di dalam kelas Graph, tambahkan variabel berikut:

        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        private string _appId = "-- Insert your Application Id here --";
    
        /// <summary>
        /// Application scopes, determine Microsoft Graph accessibility level to user account
        /// </summary>
        private IEnumerable<string> _scopes = new List<string>() { "User.Read", "Calendars.Read" };
    
        /// <summary>
        /// Microsoft Graph API, user reference
        /// </summary>
        private PublicClientApplication _client;
    
        /// <summary>
        /// Microsoft Graph API, authentication
        /// </summary>
        private AuthenticationResult _authResult;
    
    

    Catatan

    Ubah nilai appId menjadi Id Aplikasi yang telah Anda catat di Bab 1, langkah 4. Nilai ini harus sama dengan yang ditampilkan di Portal Pendaftaran Aplikasi, di halaman pendaftaran aplikasi Anda.

  8. Dalam kelas Grafik, tambahkan metode SignInAsync() dan AquireTokenAsync(), yang akan meminta pengguna untuk menyisipkan kredensial masuk.

        /// <summary>
        /// Begin the Sign In process using Microsoft Graph Library
        /// </summary>
        internal async void SignInAsync()
        {
    #if !UNITY_EDITOR && UNITY_WSA
            // Set up Grap user settings, determine if needs auth
            ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
            string userId = localSettings.Values["UserId"] as string;
            _client = new PublicClientApplication(_appId);
    
            // Attempt authentication
            _authResult = await AcquireTokenAsync(_client, _scopes, userId);
    
            // If authentication is successful, retrieve the meetings
            if (!string.IsNullOrEmpty(_authResult.AccessToken))
            {
                // Once Auth as been completed, find the meetings for the day
                await ListMeetingsAsync(_authResult.AccessToken);
            }
    #endif
        }
    
        /// <summary>
        /// Attempt to retrieve the Access Token by either retrieving
        /// previously stored credentials or by prompting user to Login
        /// </summary>
        private async Task<AuthenticationResult> AcquireTokenAsync(
            IPublicClientApplication app, IEnumerable<string> scopes, string userId)
        {
            IUser user = !string.IsNullOrEmpty(userId) ? app.GetUser(userId) : null;
            string userName = user != null ? user.Name : "null";
    
            // Once the User name is found, display it as a welcome message
            MeetingsUI.Instance.WelcomeUser(userName);
    
            // Attempt to Log In the user with a pre-stored token. Only happens
            // in case the user Logged In with this app on this device previously
            try
            {
                _authResult = await app.AcquireTokenSilentAsync(scopes, user);
            }
            catch (MsalUiRequiredException)
            {
                // Pre-stored token not found, prompt the user to log-in 
                try
                {
                    _authResult = await app.AcquireTokenAsync(scopes);
                }
                catch (MsalException msalex)
                {
                    Debug.Log($"Error Acquiring Token: {msalex.Message}");
                    return _authResult;
                }
            }
    
            MeetingsUI.Instance.WelcomeUser(_authResult.User.Name);
    
    #if !UNITY_EDITOR && UNITY_WSA
            ApplicationData.Current.LocalSettings.Values["UserId"] = 
            _authResult.User.Identifier;
    #endif
            return _authResult;
        }
    
  9. Tambahkan dua metode berikut:

    1. BuildTodayCalendarEndpoint(), yang membangun URI yang menentukan hari, dan rentang waktu, tempat rapat terjadwal diambil.

    2. ListMeetingsAsync(), yang meminta rapat terjadwal dari Microsoft Graph.

        /// <summary>
        /// Build the endpoint to retrieve the meetings for the current day.
        /// </summary>
        /// <returns>Returns the Calendar Endpoint</returns>
        public string BuildTodayCalendarEndpoint()
        {
            DateTime startOfTheDay = DateTime.Today.AddDays(0);
            DateTime endOfTheDay = DateTime.Today.AddDays(1);
            DateTime startOfTheDayUTC = startOfTheDay.ToUniversalTime();
            DateTime endOfTheDayUTC = endOfTheDay.ToUniversalTime();
    
            string todayDate = startOfTheDayUTC.ToString("o");
            string tomorrowDate = endOfTheDayUTC.ToString("o");
            string todayCalendarEndpoint = string.Format(
                "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={0}&enddatetime={1}",
                todayDate,
                tomorrowDate);
    
            return todayCalendarEndpoint;
        }
    
        /// <summary>
        /// Request all the scheduled meetings for the current day.
        /// </summary>
        private async Task ListMeetingsAsync(string accessToken)
        {
    #if !UNITY_EDITOR && UNITY_WSA
            var http = new HttpClient();
    
            http.DefaultRequestHeaders.Authorization = 
            new AuthenticationHeaderValue("Bearer", accessToken);
            var response = await http.GetAsync(BuildTodayCalendarEndpoint());
    
            var jsonResponse = await response.Content.ReadAsStringAsync();
    
            Rootobject rootObject = new Rootobject();
            try
            {
                // Parse the JSON response.
                rootObject = JsonUtility.FromJson<Rootobject>(jsonResponse);
    
                // Sort the meeting list by starting time.
                rootObject.value.Sort((x, y) => DateTime.Compare(x.start.StartDateTime, y.start.StartDateTime));
    
                // Populate the UI with the meetings.
                for (int i = 0; i < rootObject.value.Count; i++)
                {
                    MeetingsUI.Instance.AddMeeting(rootObject.value[i].subject,
                                                rootObject.value[i].start.StartDateTime.ToLocalTime(),
                                                rootObject.value[i].location.displayName);
                }
            }
            catch (Exception ex)
            {
                Debug.Log($"Error = {ex.Message}");
                return;
            }
    #endif
        }
    
  10. Anda sekarang telah menyelesaikan skrip Graph . Simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.

Bab 7 - Buat skrip GazeInput

Anda sekarang akan membuat GazeInput. Kelas ini menangani dan melacak tatapan pengguna, menggunakan Raycast yang berasal dari Kamera Utama, memproyeksikan ke depan.

Untuk membuat skrip:

  1. Klik dua kali pada folder Skrip , untuk membukanya.

  2. Klik kanan di dalam folder Skrip, klik Buat>Skrip C#. Beri nama skrip GazeInput.

  3. Klik dua kali pada skrip untuk membukanya dengan Visual Studio.

  4. Ubah kode namespace agar sesuai dengan yang di bawah ini, bersama dengan menambahkan tag '[System.Serializable]' di atas kelas GazeInput Anda, sehingga dapat diserialisasikan:

    using UnityEngine;
    
    /// <summary>
    /// Class responsible for the User's Gaze interactions
    /// </summary>
    [System.Serializable]
    public class GazeInput : MonoBehaviour
    {
    
  5. Di dalam kelas GazeInput, tambahkan variabel berikut:

        [Tooltip("Used to compare whether an object is to be interacted with.")]
        internal string InteractibleTag = "SignInButton";
    
        /// <summary>
        /// Length of the gaze
        /// </summary>
        internal float GazeMaxDistance = 300;
    
        /// <summary>
        /// Object currently gazed
        /// </summary>
        internal GameObject FocusedObject { get; private set; }
    
        internal GameObject oldFocusedObject { get; private set; }
    
        internal RaycastHit HitInfo { get; private set; }
    
        /// <summary>
        /// Cursor object visible in the scene
        /// </summary>
        internal GameObject Cursor { get; private set; }
    
        internal bool Hit { get; private set; }
    
        internal Vector3 Position { get; private set; }
    
        internal Vector3 Normal { get; private set; }
    
        private Vector3 _gazeOrigin;
    
        private Vector3 _gazeDirection;
    
  6. Tambahkan metode CreateCursor() untuk membuat kursor HoloLens di adegan, dan panggil metode dari metode Start():

        /// <summary>
        /// Start method used upon initialisation.
        /// </summary>
        internal virtual void Start()
        {
            FocusedObject = null;
            Cursor = CreateCursor();
        }
    
        /// <summary>
        /// Method to create a cursor object.
        /// </summary>
        internal 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 = new Vector3(0.05f, 0.05f, 0.05f);
            Material mat = new Material(Shader.Find("Diffuse"));
            newCursor.GetComponent<MeshRenderer>().material = mat;
            mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
            newCursor.SetActive(true);
    
            return newCursor;
        }
    
  7. Metode berikut memungkinkan tatapan Raycast dan melacak objek yang berfokus.

    /// <summary>
    /// Called every frame
    /// </summary>
    internal virtual void Update()
    {
        _gazeOrigin = Camera.main.transform.position;
    
        _gazeDirection = Camera.main.transform.forward;
    
        UpdateRaycast();
    }
    /// <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))
            {
                // Provide the 'Gaze Exited' event.
                oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver);
            }
        }
    }
    
        private void UpdateRaycast()
        {
            // Set the old focused gameobject.
            oldFocusedObject = FocusedObject;
            RaycastHit hitInfo;
    
            // Initialise Raycasting.
            Hit = Physics.Raycast(_gazeOrigin,
                _gazeDirection,
                out hitInfo,
                GazeMaxDistance);
                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. If so, reset the focused object.
            if (FocusedObject != oldFocusedObject)
            {
                ResetFocusedObject();
                if (FocusedObject != null)
                {
                    if (FocusedObject.CompareTag(InteractibleTag))
                    {
                        // Provide the 'Gaze Entered' event.
                        FocusedObject.SendMessage("OnGazeEntered", 
                            SendMessageOptions.DontRequireReceiver);
                    }
                }
            }
        }
    
  8. Simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.

Bab 8 - Buat kelas Interaksi

Anda sekarang perlu membuat skrip Interaksi , yang bertanggung jawab untuk:

  • Menangani interaksi Ketuk dan Tatapan Kamera, yang memungkinkan pengguna berinteraksi dengan "tombol" masuk di adegan.

  • Membuat objek "tombol" masuk di adegan untuk berinteraksi dengan pengguna.

Untuk membuat skrip:

  1. Klik dua kali pada folder Skrip , untuk membukanya.

  2. Klik kanan di dalam folder Skrip, klik Buat>Skrip C#. Beri nama skrip Interaksi.

  3. Klik dua kali pada skrip untuk membukanya dengan Visual Studio.

  4. Sisipkan namespace berikut:

    using UnityEngine;
    using UnityEngine.XR.WSA.Input;
    
  5. Ubah warisan kelas Interaksi dari MonoBehaviour menjadi GazeInput.

    Interaksi kelas publik : MonoBehaviour

    public class Interactions : GazeInput
    
  6. Di dalam kelas Interaksi sisipkan variabel berikut:

        /// <summary>
        /// Allows input recognition with the HoloLens
        /// </summary>
        private GestureRecognizer _gestureRecognizer;
    
  7. Ganti metode Mulai; perhatikan bahwa metode ini adalah metode penimpaan, yang memanggil metode kelas Tatapan 'dasar'. Start() akan dipanggil ketika kelas menginisialisasi, mendaftar untuk pengenalan input dan membuat tombol masuk di adegan:

        /// <summary>
        /// Called on initialization, after Awake
        /// </summary>
        internal override void Start()
        {
            base.Start();
    
            // Register the application to recognize HoloLens user inputs
            _gestureRecognizer = new GestureRecognizer();
            _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap);
            _gestureRecognizer.Tapped += GestureRecognizer_Tapped;
            _gestureRecognizer.StartCapturingGestures();
    
            // Add the Graph script to this object
            gameObject.AddComponent<MeetingsUI>();
            CreateSignInButton();
        }
    
  8. Tambahkan metode CreateSignInButton(), yang akan membuat instans tombol masuk di adegan dan mengatur propertinya:

        /// <summary>
        /// Create the sign in button object in the scene
        /// and sets its properties
        /// </summary>
        void CreateSignInButton()
        {
            GameObject signInButton = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            Material mat = new Material(Shader.Find("Diffuse"));
            signInButton.GetComponent<Renderer>().material = mat;
            mat.color = Color.blue;
    
            signInButton.transform.position = new Vector3(3.5f, 2f, 9f);
            signInButton.tag = "SignInButton";
            signInButton.AddComponent<Graph>();
        }
    
  9. Tambahkan metode GestureRecognizer_Tapped(), yang akan merespons peristiwa Ketuk pengguna.

        /// <summary>
        /// Detects the User Tap Input
        /// </summary>
        private void GestureRecognizer_Tapped(TappedEventArgs obj)
        {
            if(base.FocusedObject != null)
            {
                Debug.Log($"TAP on {base.FocusedObject.name}");
                base.FocusedObject.SendMessage("SignInAsync", SendMessageOptions.RequireReceiver);
            }
        }
    
  10. Hapus metode Update(), lalu simpan perubahan Anda di Visual Studio sebelum kembali ke Unity.

Bab 9 - Menyiapkan referensi skrip

Dalam Bab ini Anda perlu menempatkan skrip Interaksi ke Kamera Utama. Skrip itu kemudian akan menangani penempatan skrip lain di mana mereka perlu berada.

  • Dari folder Skrip di Panel Proyek, seret Interaksi skrip ke objek Kamera Utama, seperti yang digambatkan di bawah ini.

    Cuplikan layar yang memperlihatkan tempat untuk menyeret skrip Interaksi.

Bab 10 - Menyiapkan Tag

Kode yang menangani tatapan akan menggunakan Tag SignInButton untuk mengidentifikasi objek mana yang akan berinteraksi dengan pengguna untuk masuk ke Microsoft Graph.

Untuk membuat Tag:

  1. Di Editor Unity klik Kamera Utama di Panel Hierarki.

  2. Di Panel Pemeriksa klik Tag MainCamera untuk membuka daftar drop-down. Klik Tambahkan Tag...

    Cuplikan layar yang menyoroti Tambahkan Tag... pilihan.

  3. Klik tombol +.

    Cuplikan layar yang memperlihatkan tombol + .

  4. Tulis nama Tag sebagai SignInButton dan klik Simpan.

    Cuplikan layar yang memperlihatkan tempat untuk menambahkan nama tag SignInButton.

Bab 11 - Membangun proyek Unity ke UWP

Semua yang diperlukan untuk bagian Unity dari proyek ini sekarang telah selesai, jadi sekarang saatnya untuk membangunnya dari Unity.

  1. Navigasi ke Pengaturan Build (Pengaturan Build File>).

    Cuplikan layar yang memperlihatkan kotak dialog Pengaturan Build.

  2. Jika belum, centang Proyek Unity C#.

  3. 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, klik Pilih Folder.

  4. Unity akan mulai membangun proyek Anda ke folder Aplikasi .

  5. 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 ke HoloLens

Untuk menyebarkan di HoloLens:

  1. Anda akan memerlukan Alamat IP HoloLens Anda (untuk Penyebaran Jarak Jauh), dan untuk memastikan HoloLens Anda berada dalam Mode Pengembang. Untuk melakukan ini:

    1. Sementara mengenakan HoloLens Anda, buka Pengaturan.

    2. Buka Opsi Tingkat Lanjut Wi-Fi Jaringan & Internet>>

    3. Perhatikan alamat IPv4.

    4. Selanjutnya, navigasikan kembali ke Pengaturan, lalu ke Pembaruan & Keamanan>Untuk Pengembang

    5. Atur Mode Pengembang Aktif.

  2. Navigasi ke build Unity baru Anda ( folder Aplikasi ) dan buka file solusi dengan Visual Studio.

  3. Di Konfigurasi Solusi pilih Debug.

  4. Di Platform Solusi, pilih x86, Komputer Jarak Jauh. Anda akan diminta untuk memasukkan alamat IP perangkat jarak jauh (HoloLens, dalam hal ini, yang Anda catat).

    Cuplikan layar yang memperlihatkan tempat memilih x86 dan Komputer Jarak Jauh.

  5. Buka menu Build dan klik Sebarkan Solusi untuk memuat samping aplikasi ke HoloLens Anda.

  6. Aplikasi Anda sekarang akan muncul dalam daftar aplikasi yang diinstal di HoloLens Anda, siap untuk diluncurkan!

Aplikasi Microsoft Graph HoloLens Anda

Selamat, Anda membuat aplikasi realitas campuran yang memanfaatkan Microsoft Graph, untuk membaca dan menampilkan data Kalender pengguna.

Cuplikan layar yang memperlihatkan aplikasi realitas campuran yang telah selesai.

Latihan bonus

Latihan 1

Menggunakan Microsoft Graph untuk menampilkan informasi lain tentang pengguna

  • Email pengguna / nomor telepon / gambar profil

Latihan 1

Terapkan kontrol suara untuk menavigasi UI Microsoft Graph.