Urządzenia HoloLens (1. generacji) i Azure 309: Application Insights

Uwaga

Samouczki Mixed Reality Academy zostały zaprojektowane z myślą o urządzeniach HoloLens (1. generacji) i Mixed Reality immersywnych zestawów słuchawkowych. W związku z tym uważamy, że ważne jest pozostawienie tych samouczków w miejscu dla deweloperów, którzy nadal szukają wskazówek dotyczących opracowywania dla tych urządzeń. Te samouczki nie zostaną zaktualizowane o najnowsze zestawy narzędzi ani interakcje używane na potrzeby HoloLens 2. Będą one utrzymywane w celu kontynuowania pracy na obsługiwanych urządzeniach. W przyszłości zostanie opublikowana nowa seria samouczków, które pokażą, jak opracowywać na potrzeby HoloLens 2. To powiadomienie zostanie zaktualizowane za pomocą linku do tych samouczków po ich opublikowaniu.

Ekran powitalny samouczka Mixed Reality Academy.

W tym kursie dowiesz się, jak dodać funkcje usługi Application Insights do aplikacji rzeczywistości mieszanej przy użyciu interfejsu API usługi aplikacja systemu Azure Insights w celu zbierania analiz dotyczących zachowania użytkowników.

Application Insights to usługa firmy Microsoft, która umożliwia deweloperom zbieranie analiz ze swoich aplikacji i zarządzanie nią z poziomu łatwego w użyciu portalu. Analiza może być niczym — od wydajności do niestandardowych informacji, które chcesz zbierać. Aby uzyskać więcej informacji, odwiedź stronę usługi Application Insights.

Po ukończeniu tego kursu będziesz mieć aplikację immersywną rzeczywistości mieszanej, która będzie mogła wykonać następujące czynności:

  1. Zezwalaj użytkownikowi na patrzenie i poruszanie się po scenie.
  2. Wyzwalanie wysyłania analiz do usługi Application Insights przy użyciu funkcji Gaze i Zbliżenia do obiektów w scenie.
  3. Aplikacja będzie również wywoływać usługę, pobierając informacje o tym, który obiekt został najbardziej zbliżył się do użytkownika w ciągu ostatnich 24 godzin. Ten obiekt zmieni kolor na zielony.

W tym kursie nauczysz się, jak uzyskać wyniki z usługi Application Insights w przykładowej aplikacji opartej na aplikacji aparatu Unity. Zastosowanie tych pojęć do aplikacji niestandardowej, którą można utworzyć, będzie możliwe.

Obsługa urządzeń

Kurs HoloLens Immersyjne zestawy nagłowne
MR i Azure 309: Application Insights ✔️ ✔️

Uwaga

Chociaż ten kurs koncentruje się głównie na Windows Mixed Reality immersywnych zestawach słuchawkowych (VR), możesz również zastosować to, czego uczysz się w tym kursie, aby Microsoft HoloLens. Wraz z kursem zobaczysz notatki dotyczące wszelkich zmian, które mogą być konieczne do zastosowania w celu obsługi urządzenia HoloLens. Podczas korzystania z urządzenia HoloLens można zauważyć pewne echo podczas przechwytywania głosu.

Wymagania wstępne

Uwaga

Ten samouczek jest przeznaczony dla deweloperów, którzy mają podstawowe doświadczenie w językach Unity i C#. Należy również pamiętać, że wymagania wstępne i pisemne instrukcje zawarte w tym dokumencie reprezentują to, co zostało przetestowane i zweryfikowane w momencie pisania dokumentu (lipiec 2018 r.). Możesz bezpłatnie korzystać z najnowszego oprogramowania, jak wymieniono w artykule dotyczącym instalacji narzędzi , choć nie należy zakładać, że informacje zawarte w tym kursie doskonale pasują do tego, co znajdziesz w nowszym oprogramowaniu niż to, co zostało wymienione poniżej.

Na potrzeby tego kursu zalecamy następujący sprzęt i oprogramowanie:

Przed rozpoczęciem

Aby uniknąć problemów podczas kompilowania tego projektu, zdecydowanie zaleca się utworzenie projektu w tym samouczku w folderze głównym lub niemal głównym (długie ścieżki folderów mogą powodować problemy w czasie kompilacji).

Ostrzeżenie

Należy pamiętać, że dane przechodzące do usługi Application Insights zajmują trochę czasu, więc bądź cierpliwy. Jeśli chcesz sprawdzić, czy usługa otrzymała dane, zapoznaj się z rozdziałem 14, który pokaże Ci, jak nawigować po portalu.

Rozdział 1 — Witryna Azure Portal

Aby korzystać z usługi Application Insights, należy utworzyć i skonfigurować usługę Application Insights w Azure Portal.

  1. Zaloguj się do Portalu Azure.

    Uwaga

    Jeśli nie masz jeszcze konta platformy Azure, musisz je utworzyć. Jeśli korzystasz z tego samouczka w sytuacji na potrzeby zajęć lub laboratorium, poproś instruktora lub jednego z opiekunów o pomoc przy konfigurowaniu nowego konta.

  2. Po zalogowaniu kliknij pozycję Nowy w lewym górnym rogu i wyszukaj ciąg Application Insights, a następnie kliknij przycisk Enter.

    Uwaga

    Wyraz Nowy mógł zostać zastąpiony ciągiem Create a resource (Utwórz zasób) w nowszych portalach.

    Zrzut ekranu przedstawiający witrynę Azure Portal. Analiza jest wyróżniona w okienku Wszystko.

  3. Nowa strona po prawej stronie zawiera opis usługi aplikacja systemu Azure Insights. W lewym dolnym rogu tej strony wybierz przycisk Utwórz , aby utworzyć skojarzenie z tą usługą.

    Zrzut ekranu przedstawiający ekran Application Insights z wyróżnioną pozycją Utwórz.

  4. Po kliknięciu pozycji Utwórz:

    1. Wstaw żądaną nazwę dla tego wystąpienia usługi.

    2. W polu Typ aplikacji wybierz pozycję Ogólne.

    3. Wybierz odpowiednią subskrypcję.

    4. Wybierz grupę zasobów lub utwórz nową. Grupa zasobów umożliwia monitorowanie, kontrolowanie dostępu, aprowizowania i zarządzania rozliczeniami dla kolekcji zasobów platformy Azure. Zaleca się zachowanie wszystkich usług platformy Azure skojarzonych z pojedynczym projektem (na przykład takimi jak te kursy) w ramach wspólnej grupy zasobów.

      Jeśli chcesz dowiedzieć się więcej na temat grup zasobów platformy Azure, odwiedź artykuł grupy zasobów.

    5. Wybierz lokalizację.

    6. Musisz również potwierdzić, że rozumiesz warunki i postanowienia zastosowane do tej usługi.

    7. Wybierz przycisk Utwórz.

      Zrzut ekranu przedstawiający okno usługi Application Insights. Nazwa i typ aplikacji są wyróżnione.

  5. Po kliknięciu pozycji Utwórz trzeba będzie poczekać na utworzenie usługi. Może to potrwać minutę.

  6. Po utworzeniu wystąpienia usługi w portalu zostanie wyświetlone powiadomienie.

    Zrzut ekranu przedstawiający część wstążki menu z wyróżnioną ikoną powiadomienia.

  7. Wybierz powiadomienia, aby eksplorować nowe wystąpienie usługi.

    Zrzut ekranu przedstawiający okno dialogowe Wdrażanie zakończyło się pomyślnie. Wyróżniono pozycję Przejdź do zasobu.

  8. Kliknij przycisk Przejdź do zasobu w powiadomieniu, aby zapoznać się z nowym wystąpieniem usługi. Nastąpi przekierowanie do nowego wystąpienia usługi Application Insights .

    Zrzut ekranu przedstawiający wystąpienie usługi Application Insights, w którym nazwa wystąpienia to MyNewInsight.

    Uwaga

    Pozostaw tę stronę internetową otwartą i łatwą do uzyskania dostępu. W tym miejscu często będziesz widzieć zebrane dane.

    Ważne

    Aby zaimplementować usługę Application Insights, należy użyć trzech (3) określonych wartości: Klucz instrumentacji, Identyfikator aplikacji i Klucz interfejsu API. Poniżej zobaczysz, jak pobrać te wartości z usługi. Pamiętaj, aby zanotować te wartości na pustej stronie Notatnika , ponieważ będą one używane wkrótce w kodzie.

  9. Aby znaleźć klucz instrumentacji, musisz przewinąć w dół listę funkcji usługi i wybrać pozycję Właściwości, na wyświetlonej karcie zostanie wyświetlony klucz usługi.

    Zrzut ekranu przedstawiający funkcje usługi, właściwości zostały wyróżnione w sekcji Konfigurowanie, a klucz instrumentacji został wyróżniony w okienku głównym.

  10. Nieco poniżej pozycji Właściwości znajdziesz dostęp do interfejsu API, który należy kliknąć. Panel po prawej stronie udostępni identyfikator aplikacji .

    Zrzut ekranu przedstawiający funkcje usługi, wyróżniono pozycję Dostęp do interfejsu API. W okienku głównym wyróżniono pozycję Utwórz klucz P I i identyfikator aplikacji.

  11. Po otwarciu panelu Identyfikator aplikacji kliknij pozycję Utwórz klucz interfejsu API, co spowoduje otwarcie panelu Tworzenie klucza interfejsu API .

    Zrzut ekranu przedstawiający panel Tworzenie klucza P I.

  12. W panelu Tworzenie klucza interfejsu API wpisz opis i zaznacz trzy pola.

  13. Kliknij pozycję Generuj klucz. Klucz interfejsu API zostanie utworzony i wyświetlony.

    Zrzut ekranu przedstawiający panel Tworzenie klucza P I przedstawiający nowe informacje o kluczu usługi.

    Ostrzeżenie

    Jest to jedyny czas wyświetlania klucza usługi , dlatego upewnij się, że teraz utworzysz kopię.

Rozdział 2 . Konfigurowanie projektu aparatu Unity

Poniżej przedstawiono typową konfigurację do opracowywania za pomocą rzeczywistości mieszanej, a w związku z tym jest to dobry szablon dla innych projektów.

  1. Otwórz aparat Unity i kliknij pozycję Nowy.

    Zrzut ekranu przedstawiający okno projektów aparatu Unity. Nie są wyświetlane żadne informacje o projekcie.

  2. Teraz musisz podać nazwę projektu aparatu Unity, wstawić MR_Azure_Application_Insights. Upewnij się, że dla szablonu ustawiono wartość 3D. Ustaw lokalizację na odpowiednią dla Ciebie (pamiętaj, że bliżej katalogów głównych jest lepiej). Następnie kliknij pozycję Utwórz projekt.

    Zrzut ekranu przedstawiający okno nowych projektów aparatu Unity z informacjami o projekcie.

  3. Po otwarciu aparatu Unity warto sprawdzić, czy domyślny edytor skryptów jest ustawiony na program Visual Studio. Przejdź do pozycji Edytuj > preferencje , a następnie w nowym oknie przejdź do pozycji Narzędzia zewnętrzne. Zmień edytor skryptów zewnętrznych na Visual Studio 2017. Zamknij okno Preferencje .

    Zrzut ekranu przedstawiający konfigurowanie programu Visual Studio jako edytora skryptów zewnętrznych.

  4. Następnie przejdź do pozycji Ustawienia kompilacji plików > i przełącz platformę na platforma uniwersalna systemu Windows, klikając przycisk Przełącz platformę.

    Zrzut ekranu przedstawiający okno Ustawienia kompilacji z listą Wyboru platformy. platforma uniwersalna systemu Windows jest zaznaczona.

  5. Przejdź do pozycji Ustawienia kompilacji pliku > i upewnij się, że:

    1. Urządzenie docelowe jest ustawione na dowolne urządzenie

      W przypadku Microsoft HoloLens ustaw wartość Urządzenie docelowe na HoloLens.

    2. Typ kompilacji jest ustawiony na D3D

    3. Zestaw SDK jest ustawiony na najnowszą zainstalowaną

    4. Kompilowanie i uruchamianie jest ustawione na komputer lokalny

    5. Zapisz scenę i dodaj ją do kompilacji.

      1. Zrób to, wybierając pozycję Dodaj otwarte sceny. Zostanie wyświetlone okno zapisywania.

        Zrzut ekranu przedstawiający okno Ustawienia kompilacji, wybrano pozycję Dodaj otwarte sceny.

      2. Utwórz nowy folder dla tego i dowolnej przyszłej sceny, a następnie kliknij przycisk Nowy folder , aby utworzyć nowy folder, nadaj mu nazwę Sceny.

        Zrzut ekranu przedstawiający okno Zapisz scenę i zaznaczono folder Sceny.

      3. Otwórz nowo utworzony folder Sceny , a następnie w polu Nazwa pliku: tekst wpisz ApplicationInsightsScene, a następnie kliknij przycisk Zapisz.

        Zrzut ekranu przedstawiający okno Zapisz scenę z wprowadzoną nazwą pliku.

  6. Pozostałe ustawienia w obszarze Ustawienia kompilacji powinny być pozostawione jako domyślne na razie.

  7. W oknie Ustawienia kompilacji wybierz pozycję Ustawienia odtwarzacza, spowoduje to otwarcie powiązanego panelu w obszarze, w którym znajduje się inspektor .

    Zrzut ekranu przedstawiający kartę Inspector (Inspektor) z wyświetlonymi ustawieniami odtwarzacza.

  8. W tym panelu należy zweryfikować kilka ustawień:

    1. Na karcie Inne ustawienia :

      1. Wersja środowiska uruchomieniowegoskryptów powinna być eksperymentalna (odpowiednik platformy.NET 4.6), co spowoduje konieczność ponownego uruchomienia edytora.

      2. Zaplecze skryptów powinno mieć wartość .NET

      3. Poziom zgodności interfejsu API powinien mieć wartość .NET 4.6

      Zrzut ekranu przedstawiający kartę Inspector (Inspektor) ze szczegółami w sekcji konfiguracji w sekcji Inne ustawienia.

    2. Na karcie Ustawienia publikowania w obszarze Możliwości sprawdź:

      • InternetClient

        Zrzut ekranu przedstawiający listę Możliwości zaznaczono klienta internetowego.

    3. W dalszej części panelu w obszarze Ustawienia XR (znajdujące się poniżej ustawień publikowania) zaznacz opcję Obsługa rzeczywistości wirtualnej, upewnij się, że dodano zestaw SDK Windows Mixed Reality.

      Zrzut ekranu przedstawiający sekcję Ustawienia języka X R— jest zaznaczona opcja Obsługiwana rzeczywistość wirtualna.

  9. Po powrocie do ustawień kompilacjiprojekty języka C# aparatu Unity nie są już wyszarzone; zaznacz pole wyboru obok tego.

  10. Zamknij okno Build Settings (Ustawienia kompilacji).

  11. Zapisz scenę i projekt (PLIK>ZAPISZ SCENĘ / PLIK>ZAPISZ PROJEKT).

Rozdział 3 — Importowanie pakietu aparatu Unity

Ważne

Jeśli chcesz pominąć konfigurowanie składników aparatu Unity w tym kursie i kontynuować bezpośrednio w kodzie, możesz pobrać ten pakiet Azure-MR-309.unitypackage, zaimportować go do projektu jako pakiet niestandardowy. Będzie to również zawierać biblioteki DLL z następnego rozdziału. Po zaimportowaniu przejdź do rozdziału 6.

Ważne

Aby użyć usługi Application Insights w środowisku Unity, należy zaimportować dla niej bibliotekę DLL wraz z biblioteką DLL Newtonsoft. Obecnie istnieje znany problem w środowisku Unity, który wymaga ponownego skonfigurowania wtyczek po zaimportowaniu. Te kroki (4–7 w tej sekcji) nie będą już wymagane po rozwiązaniu usterki.

Aby zaimportować usługę Application Insights do własnego projektu, upewnij się , że pobrano pakiet ".unitypackage" zawierający wtyczki. Następnie wykonaj następujące czynności:

  1. Dodaj plik unitypackage** do aparatu Unity przy użyciu opcji menu Importuj pakiet > niestandardowy pakietu Assets>.

  2. W oknie Importuj pakiet aparatu Unity wyskakującym upewnij się, że wybrano wszystkie elementy w obszarze (i włącznie) Wtyczki .

    Zrzut ekranu przedstawiający okno dialogowe Importowanie pakietu aparatu Unity z zaznaczonymi wszystkimi elementami.

  3. Kliknij przycisk Importuj , aby dodać elementy do projektu.

  4. Przejdź do folderu Insights w obszarze Wtyczki w widoku Projektu i wybierz tylko następujące wtyczki:

    • Microsoft.ApplicationInsights

    Zrzut ekranu przedstawiający panel Project (Projekt), w folderze Insights jest otwarty.

  5. Po wybraniu tej wtyczki upewnij się, że wszystkie platformyniezaznaczone, a następnie upewnij się, że program WSAPlayer jest również niezaznaczone, a następnie kliknij przycisk Zastosuj. W tym celu wystarczy potwierdzić, że pliki są poprawnie skonfigurowane.

    Zrzut ekranu przedstawiający panel Inspector (Inspektor) z zaznaczonym polem Editor (Edytor) i Standalone (Autonomiczny).

    Uwaga

    Oznaczanie wtyczek, takich jak to, konfiguruje je do użycia tylko w Edytorze aparatu Unity. Istnieje inny zestaw bibliotek DLL w folderze WSA, który będzie używany po wyeksportowaniu projektu z aparatu Unity.

  6. Następnie należy otworzyć folder WSA w folderze Insights . Zobaczysz kopię tego samego pliku, który został skonfigurowany. Wybierz ten plik, a następnie w inspektorze upewnij się, że pole wyboru Dowolna platforma jest niezaznaczone, a następnie upewnij się, że zaznaczono tylkoelement WSAPlayer. Kliknij pozycję Zastosuj.

    Zrzut ekranu przedstawiający panel Inspektor z zaznaczonym polem W S A Player.

  7. Teraz musisz wykonać kroki od 4 do 6, ale w przypadku wtyczek Newtonsoft . Zapoznaj się z poniższym zrzutem ekranu, aby dowiedzieć się, jak powinien wyglądać wynik.

    Zrzut ekranu przedstawiający cztery widoki paneli Project and Inspector z wynikami konfigurowania folderu Newtonsoft i wybranych wtyczek.

Rozdział 4 . Konfigurowanie aparatu i kontrolek użytkownika

W tym rozdziale skonfigurujesz aparat i kontrolki, aby umożliwić użytkownikowi wyświetlanie i przenoszenie w scenie.

  1. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie w obszarze Utwórz>puste.

    Zrzut ekranu przedstawiający panel Hierarchia, wybrano pozycję Utwórz puste.

  2. Zmień nazwę nowego pustego obiektu GameObject na Element nadrzędny aparatu.

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną wartością Aparat nadrzędny. Panel Inspektor

  3. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie na obiekcie 3D, a następnie w obszarze Sphere.

  4. Zmień nazwę sfery na prawą.

  5. Ustaw skalę przekształcania prawej strony na 0.1, 0.1, 0.1, 0.1

    Zrzut ekranu przedstawiający panele Hierarchia i Inspektor, wyróżniono sekcję Przekształć na panelu Inspektor.

  6. Usuń składnik Zderzacz sfery z prawej strony, klikając koło zębate w składniku zderzacz sfery , a następnie usuń składnik.

    Zrzut ekranu przedstawiający panel Inspektor, ikonę koła zębatego i pozycję Usuń składnik został wyróżniony w sekcji Zderzacz kulis.

  7. W panelu hierarchii przeciągnij aparat główny i obiekty po prawej stronie do obiektu Nadrzędnego aparatu.

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną pozycją Main Camera (Główny aparat), na panelu Inspector (Inspektor) jest zaznaczona opcja Main Camera (Aparat główny).

  8. Ustaw pozycję przekształcania zarówno głównego aparatu, jak i obiektu prawego ręki na 0, 0, 0.

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną pozycją Główny aparat, ustawienia przekształcania są wyróżnione w panelu Inspektor.

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną pozycją Prawa ręka, ustawienia przekształcania są wyróżnione w panelu Inspektor.

Rozdział 5 . Konfigurowanie obiektów w scenie aparatu Unity

Teraz utworzysz kilka podstawowych kształtów dla sceny, z którymi użytkownik może korzystać.

  1. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie w obiekcie 3D, a następnie wybierz pozycję Płaszczyzna.

  2. Ustaw pozycję Przekształcanie płaszczyzny na 0, -1, 0.

  3. Ustaw skalę przekształcenia płaszczyzny na 5, 1, 5.

    Zrzut ekranu przedstawiający panele Scena, Hierarchia i Inspektor. Sekcja Przekształć w panelu Inspector (Inspektor) jest wyróżniona.

  4. Utwórz podstawowy materiał do użycia z obiektem Płaszczyzna , dzięki czemu inne kształty są łatwiejsze do zobaczenia. Przejdź do panelu projektu, kliknij prawym przyciskiem myszy, a następnie pozycję Utwórz, a następnie pozycję Folder, aby utworzyć nowy folder. Nadaj jej nazwę Materiały.

    Zrzut ekranu przedstawiający panel Projekt z wyróżnioną pozycją Utwórz i Folder.Zrzut ekranu przedstawiający panel Projekt. Materiały są wyróżnione w okienku Zasoby.

  5. Otwórz folder Materiały , a następnie kliknij prawym przyciskiem myszy pozycję Utwórz, a następnie pozycję Materiał, aby utworzyć nowy materiał. Nadaj mu nazwę Niebieski.

    Zrzut ekranu przedstawiający panel Projekt z wyróżnioną pozycją Utwórz i Materiał.Zrzut ekranu przedstawiający panel Projekt. Niebieski jest wyróżniony w okienku Materiały.

  6. Po wybraniu nowego materiału Niebieskiego przyjrzyj się inspektorowi i kliknij prostokątne okno obok Albedo. Wybierz niebieski kolor (jeden z poniższych obrazów to Kolor szesnastkowy: #3592FFFF). Po wybraniu przycisku Zamknij kliknij przycisk Zamknij.

    Zrzut ekranu przedstawiający panel Inspektor. Sekcja koloru jest wyróżniona.

  7. Przeciągnij nowy materiał z folderu Materiały na nowo utworzoną płaszczyznę w scenie (lub upuść go na obiekcie Płaszczyzna w hierarchii).

    Zrzut ekranu przedstawiający panel Scena przedstawiający nowy materiał z folderu Materiały.

  8. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie na obiekcie 3D Kapsuła.

    • Po wybraniu pozycji Kapsuła zmień pozycję przekształcaniana:-10, 1, 0.
  9. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie na obiekcie 3D, module.

    • Po wybraniu pozycji Moduł zmień pozycję przekształcaniana:0, 0, 10.
  10. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie w obszarze Obiekt 3D, Sphere.

    • Po wybraniu pozycji Sphere zmień pozycję przekształcaniana: 10, 0, 0.

    Zrzut ekranu przedstawiający panele Scena, Hierarchia i Inspektor. Kapsuła jest zaznaczona w panelu Hierarchia.

    Uwaga

    Te wartości pozycjisugestiami. Możesz ustawić pozycje obiektów na dowolną wartość, choć jest to łatwiejsze dla użytkownika aplikacji, jeśli odległości obiektów nie są zbyt daleko od aparatu.

  11. Gdy aplikacja jest uruchomiona, musi być w stanie zidentyfikować obiekty w scenie, aby to osiągnąć, muszą zostać otagowane. Wybierz jeden z obiektów, a następnie w panelu Inspektor kliknij przycisk Dodaj tag..., co spowoduje zamianę inspektora na panel Tagi & Warstwy .

    Zrzut ekranu przedstawiający panel Inspektor z wyróżnioną opcją Dodaj tag.Zrzut ekranu przedstawiający panel Inspector (Inspektor) z wyróżnionymi tagami i warstwami.

  12. Kliknij symbol + (plus), a następnie wpisz nazwę tagu jako ObjectInScene.

    Zrzut ekranu przedstawiający panel Inspektor z wybranymi tagami i warstwami. Zostanie wyróżnione okno dialogowe Nowa nazwa tagu.

    Ostrzeżenie

    Jeśli używasz innej nazwy tagu, musisz upewnić się, że ta zmiana zostanie również wprowadzona w obszarze DataFromAnalytics, ObjectTrigger i Gaze, skrypty później, aby obiekty zostały znalezione i wykryte w scenie.

  13. Po utworzeniu tagu należy teraz zastosować go do wszystkich trzech obiektów. W hierarchii przytrzymaj klawisz Shift , a następnie kliknij utworzony tag Capsule, Cube i Sphere, a następnie w inspektorze kliknij menu rozwijane obok pozycji Tag, a następnie kliknij utworzony tag ObjectInScene .

    Zrzut ekranu przedstawiający panel Inspector (Inspektor) strzałkę wskazującą tag. W menu Nieoznaczone jest zaznaczone pole Wyboru nieoznaczone, a opcja ObjectInScene jest zaznaczona.Zrzut ekranu przedstawiający dwa menu z wyróżnioną pozycją Utwórz i Folder.

Rozdział 6 . Tworzenie klasy ApplicationInsightsTracker

Pierwszy skrypt, który należy utworzyć, to ApplicationInsightsTracker, który jest odpowiedzialny za:

  1. Tworzenie zdarzeń na podstawie interakcji użytkownika w celu przesyłania do usługi aplikacja systemu Azure Insights.

  2. Tworzenie odpowiednich nazw zdarzeń w zależności od interakcji użytkownika.

  3. Przesyłanie zdarzeń do wystąpienia usługi Application Insights.

Aby utworzyć tę klasę:

  1. Kliknij prawym przyciskiem myszy panel projektu, a następnie pozycję Utwórz>folder. Nadaj nazwę skryptom folderu.

    Zrzut ekranu przedstawiający panel Projekty. Ikona folderu Skrypty jest wyróżniona w okienku Zasoby.Zrzut ekranu przedstawiający opcje menu, w których wybrano opcje Utwórz i Skrypt języka C#.

  2. Po utworzeniu folderu Scripts kliknij go dwukrotnie, aby go otworzyć. Następnie w tym folderze kliknij prawym przyciskiem myszy pozycję Utwórz>skrypt języka C#. Nadaj skryptowi nazwę ApplicationInsightsTracker.

  3. Kliknij dwukrotnie nowy skrypt ApplicationInsightsTracker , aby otworzyć go za pomocą programu Visual Studio.

  4. Zaktualizuj przestrzenie nazw w górnej części skryptu tak, aby znajdowały się w następujący sposób:

        using Microsoft.ApplicationInsights;
        using Microsoft.ApplicationInsights.DataContracts;
        using Microsoft.ApplicationInsights.Extensibility;
        using UnityEngine;
    
  5. Wewnątrz klasy wstaw następujące zmienne:

        /// <summary>
        /// Allows this class to behavior like a singleton
        /// </summary>
        public static ApplicationInsightsTracker Instance;
    
        /// <summary>
        /// Insert your Instrumentation Key here
        /// </summary>
        internal string instrumentationKey = "Insert Instrumentation Key here";
    
        /// <summary>
        /// Insert your Application Id here
        /// </summary>
        internal string applicationId = "Insert Application Id here";
    
        /// <summary>
        /// Insert your API Key here
        /// </summary>
        internal string API_Key = "Insert API Key here";
    
        /// <summary>
        /// Represent the Analytic Custom Event object
        /// </summary>
        private TelemetryClient telemetryClient;
    
        /// <summary>
        /// Represent the Analytic object able to host gaze duration
        /// </summary>
        private MetricTelemetry metric;
    

    Uwaga

    Ustaw odpowiednio wartości instrumentationKey, applicationId i API_Key przy użyciu kluczy usługi z witryny Azure Portal, jak wspomniano w rozdziale 1, krok 9.

  6. Następnie dodaj metody Start() i Awake(), które będą wywoływane podczas inicjowania klasy:

        /// <summary>
        /// Sets this class instance as a singleton
        /// </summary>
        void Awake()
        {
            Instance = this;
        }
    
        /// <summary>
        /// Use this for initialization
        /// </summary>
        void Start()
        {
            // Instantiate telemetry and metric
            telemetryClient = new TelemetryClient();
    
            metric = new MetricTelemetry();
    
            // Assign the Instrumentation Key to the Event and Metric objects
            TelemetryConfiguration.Active.InstrumentationKey = instrumentationKey;
    
            telemetryClient.InstrumentationKey = instrumentationKey;
        }
    
  7. Dodaj metody odpowiedzialne za wysyłanie zdarzeń i metryk zarejestrowanych przez aplikację:

        /// <summary>
        /// Submit the Event to Azure Analytics using the event trigger object
        /// </summary>
        public void RecordProximityEvent(string objectName)
        {
            telemetryClient.TrackEvent(CreateEventName(objectName));
        }
    
        /// <summary>
        /// Uses the name of the object involved in the event to create 
        /// and return an Event Name convention
        /// </summary>
        public string CreateEventName(string name)
        {
            string eventName = $"User near {name}";
            return eventName;
        }
    
        /// <summary>
        /// Submit a Metric to Azure Analytics using the metric gazed object
        /// and the time count of the gaze
        /// </summary>
        public void RecordGazeMetrics(string objectName, int time)
        {
            // Output Console information about gaze.
            Debug.Log($"Finished gazing at {objectName}, which went for <b>{time}</b> second{(time != 1 ? "s" : "")}");
    
            metric.Name = $"Gazed {objectName}";
    
            metric.Value = time;
    
            telemetryClient.TrackMetric(metric);
        }
    
  8. Pamiętaj, aby zapisać zmiany w programie Visual Studio przed powrotem do aparatu Unity.

Rozdział 7 . Tworzenie skryptu uczenia

Następnym skryptem do utworzenia jest skrypt gazecie . Ten skrypt jest odpowiedzialny za utworzenie raycastu , który będzie przewidywany do przodu z kamery głównej, aby wykryć, który obiekt patrzy użytkownik. W takim przypadku raycast będzie musiał określić, czy użytkownik patrzy na obiekt z tagiem ObjectInScene , a następnie zlicza, jak długo użytkownik patrzy na ten obiekt.

  1. Kliknij dwukrotnie folder Scripts (Skrypty ), aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty ), kliknij pozycję Create C# Script ( Utwórz>skrypt języka C#). Nadaj nazwę gazecie skryptu.

  3. Kliknij dwukrotnie skrypt, aby otworzyć go za pomocą programu Visual Studio.

  4. Zastąp istniejący kod następującym kodem:

        using UnityEngine;
    
        public class Gaze : MonoBehaviour
        {
            /// <summary>
            /// Provides Singleton-like behavior to this class.
            /// </summary>
            public static Gaze Instance;
    
            /// <summary>
            /// Provides a reference to the object the user is currently looking at.
            /// </summary>
            public GameObject FocusedGameObject { get; private set; }
    
            /// <summary>
            /// Provides whether an object has been successfully hit by the raycast.
            /// </summary>
            public bool Hit { get; private set; }
    
            /// <summary>
            /// Provides a reference to compare whether the user is still looking at 
            /// the same object (and has not looked away).
            /// </summary>
            private GameObject _oldFocusedObject = null;
    
            /// <summary>
            /// Max Ray Distance
            /// </summary>
            private float _gazeMaxDistance = 300;
    
            /// <summary>
            /// Max Ray Distance
            /// </summary>
            private float _gazeTimeCounter = 0;
    
            /// <summary>
            /// The cursor object will be created when the app is running,
            /// this will store its values. 
            /// </summary>
            private GameObject _cursor;
        }
    
  5. Należy teraz dodać kod dla metod Awake() i Start( ).

        private void Awake()
        {
            // Set this class to behave similar to singleton
            Instance = this;
            _cursor = CreateCursor();
        }
    
        void Start()
        {
            FocusedGameObject = null;
        }
    
        /// <summary>
        /// Create a cursor object, to provide what the user
        /// is looking at.
        /// </summary>
        /// <returns></returns>
        private GameObject CreateCursor()    
        {
            GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    
            // Remove the collider, so it does not block raycast.
            Destroy(newCursor.GetComponent<SphereCollider>());
    
            newCursor.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
    
            newCursor.GetComponent<MeshRenderer>().material.color = 
            Color.HSVToRGB(0.0223f, 0.7922f, 1.000f);
    
            newCursor.SetActive(false);
            return newCursor;
        }
    
  6. Wewnątrz klasy Gaze dodaj następujący kod w metodzie Update(), aby projektować raycast i wykryć trafienie docelowe:

        /// <summary>
        /// Called every frame
        /// </summary>
        void Update()
        {
            // Set the old focused gameobject.
            _oldFocusedObject = FocusedGameObject;
    
            RaycastHit hitInfo;
    
            // Initialize Raycasting.
            Hit = Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, _gazeMaxDistance);
    
            // Check whether raycast has hit.
            if (Hit == true)
            {
                // Check whether the hit has a collider.
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at.
                    FocusedGameObject = hitInfo.collider.gameObject;
    
                    // Lerp the cursor to the hit point, which helps to stabilize the gaze.
                    _cursor.transform.position = Vector3.Lerp(_cursor.transform.position, hitInfo.point, 0.6f);
    
                    _cursor.SetActive(true);
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null.
                    FocusedGameObject = null;
    
                    _cursor.SetActive(false);
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedGameObject = null;
    
                _cursor.SetActive(false);
            }
    
            // Check whether the previous focused object is this same object. If so, reset the focused object.
            if (FocusedGameObject != _oldFocusedObject)
            {
                ResetFocusedObject();
            }
            // If they are the same, but are null, reset the counter. 
            else if (FocusedGameObject == null && _oldFocusedObject == null)
            {
                _gazeTimeCounter = 0;
            }
            // Count whilst the user continues looking at the same object.
            else
            {
                _gazeTimeCounter += Time.deltaTime;
            }
        }
    
  7. Dodaj metodę ResetFocusedObject(), aby wysyłać dane do usługi Application Insights , gdy użytkownik spojrzał na obiekt.

        /// <summary>
        /// Reset the old focused object, stop the gaze timer, and send data if it
        /// is greater than one.
        /// </summary>
        public void ResetFocusedObject()
        {
            // Ensure the old focused object is not null.
            if (_oldFocusedObject != null)
            {
                // Only looking for objects with the correct tag.
                if (_oldFocusedObject.CompareTag("ObjectInScene"))
                {
                    // Turn the timer into an int, and ensure that more than zero time has passed.
                    int gazeAsInt = (int)_gazeTimeCounter;
    
                    if (gazeAsInt > 0)
                    {
                        //Record the object gazed and duration of gaze for Analytics
                        ApplicationInsightsTracker.Instance.RecordGazeMetrics(_oldFocusedObject.name, gazeAsInt);
                    }
                    //Reset timer
                    _gazeTimeCounter = 0;
                }
            }
        }
    
  8. Ukończono skrypt gazecie . Zapisz zmiany w programie Visual Studio przed powrotem do aparatu Unity.

Rozdział 8 — tworzenie klasy ObjectTrigger

Następny skrypt, który należy utworzyć, to ObjectTrigger, który jest odpowiedzialny za:

  • Dodanie składników wymaganych do kolizji z aparatem głównym.
  • Wykrywanie, czy aparat znajduje się w pobliżu obiektu oznaczonego jako ObjectInScene.

Aby utworzyć skrypt:

  1. Kliknij dwukrotnie folder Scripts (Skrypty ), aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty ), kliknij pozycję Create C# Script ( Utwórz>skrypt języka C#). Nadaj skryptowi nazwę ObjectTrigger.

  3. Kliknij dwukrotnie skrypt, aby otworzyć go za pomocą programu Visual Studio. Zastąp istniejący kod następującym kodem:

        using UnityEngine;
    
        public class ObjectTrigger : MonoBehaviour
        {
            private void Start()
            {
                // Add the Collider and Rigidbody components, 
                // and set their respective settings. This allows for collision.
                gameObject.AddComponent<SphereCollider>().radius = 1.5f;
    
                gameObject.AddComponent<Rigidbody>().useGravity = false;
            }
    
            /// <summary>
            /// Triggered when an object with a collider enters this objects trigger collider.
            /// </summary>
            /// <param name="collision">Collided object</param>
            private void OnCollisionEnter(Collision collision)
            {
                CompareTriggerEvent(collision, true);
            }
    
            /// <summary>
            /// Triggered when an object with a collider exits this objects trigger collider.
            /// </summary>
            /// <param name="collision">Collided object</param>
            private void OnCollisionExit(Collision collision)
            {
                CompareTriggerEvent(collision, false);
            }
    
            /// <summary>
            /// Method for providing debug message, and sending event information to InsightsTracker.
            /// </summary>
            /// <param name="other">Collided object</param>
            /// <param name="enter">Enter = true, Exit = False</param>
            private void CompareTriggerEvent(Collision other, bool enter)
            {
                if (other.collider.CompareTag("ObjectInScene"))
                {
                    string message = $"User is{(enter == true ? " " : " no longer ")}near <b>{other.gameObject.name}</b>";
    
                    if (enter == true)
                    {
                        ApplicationInsightsTracker.Instance.RecordProximityEvent(other.gameObject.name);
                    }
                    Debug.Log(message);
                }
            }
        }
    
  4. Pamiętaj, aby zapisać zmiany w programie Visual Studio przed powrotem do aparatu Unity.

Rozdział 9 — Tworzenie klasy DataFromAnalytics

Teraz musisz utworzyć skrypt DataFromAnalytics , który jest odpowiedzialny za:

  • Pobieranie danych analitycznych dotyczących tego, do którego obiektu najbardziej zbliżył się aparat.
  • Przy użyciu kluczy usługi, które umożliwiają komunikację z wystąpieniem usługi aplikacja systemu Azure Insights.
  • Sortowanie obiektów w scenie, zgodnie z którym ma najwyższą liczbę zdarzeń.
  • Zmiana koloru materiału, najbardziej zbliżył się do obiektu, na zielony.

Aby utworzyć skrypt:

  1. Kliknij dwukrotnie folder Scripts (Skrypty ), aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty ), kliknij pozycję Create C# Script ( Utwórz>skrypt języka C#). Nadaj skryptowi nazwę DataFromAnalytics.

  3. Kliknij dwukrotnie skrypt, aby otworzyć go za pomocą programu Visual Studio.

  4. Wstaw następujące przestrzenie nazw:

        using Newtonsoft.Json;
        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. Wewnątrz skryptu wstaw następujące elementy:

        /// <summary>
        /// Number of most recent events to be queried
        /// </summary>
        private int _quantityOfEventsQueried = 10;
    
        /// <summary>
        /// The timespan with which to query. Needs to be in hours.
        /// </summary>
        private int _timepspanAsHours = 24;
    
        /// <summary>
        /// A list of the objects in the scene
        /// </summary>
        private List<GameObject> _listOfGameObjectsInScene;
    
        /// <summary>
        /// Number of queries which have returned, after being sent.
        /// </summary>
        private int _queriesReturned = 0;
    
        /// <summary>
        /// List of GameObjects, as the Key, with their event count, as the Value.
        /// </summary>
        private List<KeyValuePair<GameObject, int>> _pairedObjectsWithEventCount = new List<KeyValuePair<GameObject, int>>();
    
        // Use this for initialization
        void Start()
        {
            // Find all objects in scene which have the ObjectInScene tag (as there may be other GameObjects in the scene which you do not want).
            _listOfGameObjectsInScene = GameObject.FindGameObjectsWithTag("ObjectInScene").ToList();
    
            FetchAnalytics();
        }
    
  6. W klasie DataFromAnalytics bezpośrednio po metodzie Start() dodaj następującą metodę o nazwie FetchAnalytics(). Ta metoda jest odpowiedzialna za wypełnianie listy par wartości klucza z obiektem GameObject i numerem liczby zdarzeń symbolu zastępczego. Następnie inicjuje koprocedurynę GetWebRequest(). Struktura zapytań wywołania usługi Application Insights można również znaleźć w tej metodzie jako punkt końcowy adresu URL zapytania .

        private void FetchAnalytics()
        {
            // Iterate through the objects in the list
            for (int i = 0; i < _listOfGameObjectsInScene.Count; i++)
            {
                // The current event number is not known, so set it to zero.
                int eventCount = 0;
    
                // Add new pair to list, as placeholder, until eventCount is known.
                _pairedObjectsWithEventCount.Add(new KeyValuePair<GameObject, int>(_listOfGameObjectsInScene[i], eventCount));
    
                // Set the renderer of the object to the default color, white
                _listOfGameObjectsInScene[i].GetComponent<Renderer>().material.color = Color.white;
    
                // Create the appropriate object name using Insights structure
                string objectName = _listOfGameObjectsInScene[i].name;
    
     		    // Build the queryUrl for this object.
     		    string queryUrl = Uri.EscapeUriString(string.Format(
                    "https://api.applicationinsights.io/v1/apps/{0}/events/$all?timespan=PT{1}H&$search={2}&$select=customMetric/name&$top={3}&$count=true",
     			    ApplicationInsightsTracker.Instance.applicationId, _timepspanAsHours, "Gazed " + objectName, _quantityOfEventsQueried));
    
    
                // Send this object away within the WebRequest Coroutine, to determine it is event count.
                StartCoroutine("GetWebRequest", new KeyValuePair<string, int>(queryUrl, i));
            }
        }
    
  7. Tuż poniżej metody FetchAnalytics() dodaj metodę o nazwie GetWebRequest(), która zwraca moduł IEnumerator. Ta metoda jest odpowiedzialna za żądanie liczby wywołań zdarzenia odpowiadającego określonemu obiektowi GameObject w usłudze Application Insights. Po zwróceniu wszystkich wysłanych zapytań wywoływana jest metoda DetermineWinner().

        /// <summary>
        /// Requests the data count for number of events, according to the
        /// input query URL.
        /// </summary>
        /// <param name="webQueryPair">Query URL and the list number count.</param>
        /// <returns></returns>
        private IEnumerator GetWebRequest(KeyValuePair<string, int> webQueryPair)
        {
            // Set the URL and count as their own variables (for readability).
            string url = webQueryPair.Key;
            int currentCount = webQueryPair.Value;
    
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(url))
            {
                DownloadHandlerBuffer handlerBuffer = new DownloadHandlerBuffer();
    
                unityWebRequest.downloadHandler = handlerBuffer;
    
                unityWebRequest.SetRequestHeader("host", "api.applicationinsights.io");
    
                unityWebRequest.SetRequestHeader("x-api-key", ApplicationInsightsTracker.Instance.API_Key);
    
                yield return unityWebRequest.SendWebRequest();
    
                if (unityWebRequest.isNetworkError)
                {
                    // Failure with web request.
                    Debug.Log("<color=red>Error Sending:</color> " + unityWebRequest.error);
                }
                else
                {
                    // This query has returned, so add to the current count.
                    _queriesReturned++;
    
                    // Initialize event count integer.
                    int eventCount = 0;
    
                    // Deserialize the response with the custom Analytics class.
                    Analytics welcome = JsonConvert.DeserializeObject<Analytics>(unityWebRequest.downloadHandler.text);
    
                    // Get and return the count for the Event
                    if (int.TryParse(welcome.OdataCount, out eventCount) == false)
                    {
                        // Parsing failed. Can sometimes mean that the Query URL was incorrect.
                        Debug.Log("<color=red>Failure to Parse Data Results. Check Query URL for issues.</color>");
                    }
                    else
                    {
                        // Overwrite the current pair, with its actual values, now that the event count is known.
                        _pairedObjectsWithEventCount[currentCount] = new KeyValuePair<GameObject, int>(_pairedObjectsWithEventCount[currentCount].Key, eventCount);
                    }
    
                    // If all queries (compared with the number which was sent away) have 
                    // returned, then run the determine winner method. 
                    if (_queriesReturned == _pairedObjectsWithEventCount.Count)
                    {
                        DetermineWinner();
                    }
                }
            }
        }
    
  8. Następną metodą jest DetermineWinner(), która sortuje listę par GameObject i Int , zgodnie z największą liczbą zdarzeń. Następnie zmienia kolor materiału obiektu GameObject na zielony (jako opinie o najwyższej liczbie). Spowoduje to wyświetlenie komunikatu z wynikami analizy.

        /// <summary>
        /// Call to determine the keyValue pair, within the objects list, 
        /// with the highest event count.
        /// </summary>
        private void DetermineWinner()
        {
            // Sort the values within the list of pairs.
            _pairedObjectsWithEventCount.Sort((x, y) => y.Value.CompareTo(x.Value));
    
            // Change its colour to green
            _pairedObjectsWithEventCount.First().Key.GetComponent<Renderer>().material.color = Color.green;
    
            // Provide the winner, and other results, within the console window. 
            string message = $"<b>Analytics Results:</b>\n " +
                $"<i>{_pairedObjectsWithEventCount.First().Key.name}</i> has the highest event count, " +
                $"with <i>{_pairedObjectsWithEventCount.First().Value.ToString()}</i>.\nFollowed by: ";
    
            for (int i = 1; i < _pairedObjectsWithEventCount.Count; i++)
            {
                message += $"{_pairedObjectsWithEventCount[i].Key.name}, " +
                    $"with {_pairedObjectsWithEventCount[i].Value.ToString()} events.\n";
            }
    
            Debug.Log(message);
        }
    
  9. Dodaj strukturę klas, która będzie używana do deserializacji obiektu JSON otrzymanego z usługi Application Insights. Dodaj te klasy w dolnej części pliku klasy DataFromAnalyticspoza definicją klasy.

        /// <summary>
        /// These classes represent the structure of the JSON response from Azure Insight
        /// </summary>
        [Serializable]
        public class Analytics
        {
            [JsonProperty("@odata.context")]
            public string OdataContext { get; set; }
    
            [JsonProperty("@odata.count")]
            public string OdataCount { get; set; }
    
            [JsonProperty("value")]
            public Value[] Value { get; set; }
        }
    
        [Serializable]
        public class Value
        {
            [JsonProperty("customMetric")]
            public CustomMetric CustomMetric { get; set; }
        }
    
        [Serializable]
        public class CustomMetric
        {
            [JsonProperty("name")]
            public string Name { get; set; }
        }
    
  10. Pamiętaj, aby zapisać zmiany w programie Visual Studio przed powrotem do aparatu Unity.

Rozdział 10 — Tworzenie klasy Movement

Skrypt przenoszenia to kolejny skrypt, który należy utworzyć. Odpowiada za:

  • Przesuwanie kamery głównej zgodnie z kierunkiem, w kierunku, w który patrzy kamera.
  • Dodawanie wszystkich innych skryptów do obiektów sceny.

Aby utworzyć skrypt:

  1. Kliknij dwukrotnie folder Scripts ( Skrypty ), aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty), a następnie kliknij polecenie CreateC# Script (Utwórz > skrypt języka C#). Nadaj skryptowi nazwę Movement.

  3. Kliknij dwukrotnie skrypt, aby otworzyć go za pomocą programu Visual Studio.

  4. Zastąp istniejący kod następującym kodem:

        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
    
        public class Movement : MonoBehaviour
        {
            /// <summary>
            /// The rendered object representing the right controller.
            /// </summary>
            public GameObject Controller;
    
            /// <summary>
            /// The movement speed of the user.
            /// </summary>
            public float UserSpeed;
    
            /// <summary>
            /// Provides whether source updates have been registered.
            /// </summary>
            private bool _isAttached = false;
    
            /// <summary>
            /// The chosen controller hand to use. 
            /// </summary>
            private InteractionSourceHandedness _handness = InteractionSourceHandedness.Right;
    
            /// <summary>
            /// Used to calculate and proposes movement translation.
            /// </summary>
            private Vector3 _playerMovementTranslation;
    
            private void Start()
            {
                // You are now adding components dynamically 
                // to ensure they are existing on the correct object  
    
                // Add all camera related scripts to the camera. 
                Camera.main.gameObject.AddComponent<Gaze>();
                Camera.main.gameObject.AddComponent<ObjectTrigger>();
    
                // Add all other scripts to this object.
                gameObject.AddComponent<ApplicationInsightsTracker>();
                gameObject.AddComponent<DataFromAnalytics>();
            }
    
            // Update is called once per frame
            void Update()
            {
    
            }
        }
    
  5. W klasie Movementponiżej pustej metody Update() wstaw następujące metody, które umożliwiają użytkownikowi przenoszenie się w przestrzeni wirtualnej za pomocą kontrolera ręcznego:

        /// <summary>
        /// Used for tracking the current position and rotation of the controller.
        /// </summary>
        private void UpdateControllerState()
        {
    #if UNITY_WSA && UNITY_2017_2_OR_NEWER
            // Check for current connected controllers, only if WSA.
            string message = string.Empty;
    
            if (InteractionManager.GetCurrentReading().Length > 0)
            {
                foreach (var sourceState in InteractionManager.GetCurrentReading())
                {
                    if (sourceState.source.kind == InteractionSourceKind.Controller && sourceState.source.handedness == _handness)
                    {
                        // If a controller source is found, which matches the selected handness, 
                        // check whether interaction source updated events have been registered. 
                        if (_isAttached == false)
                        {
                            // Register events, as not yet registered.
                            message = "<color=green>Source Found: Registering Controller Source Events</color>";
                            _isAttached = true;
    
                            InteractionManager.InteractionSourceUpdated += InteractionManager_InteractionSourceUpdated;
                        }
    
                        // Update the position and rotation information for the controller.
                        Vector3 newPosition;
                        if (sourceState.sourcePose.TryGetPosition(out newPosition, InteractionSourceNode.Pointer) && ValidPosition(newPosition))
                        {
                            Controller.transform.localPosition = newPosition;
                        }
    
                        Quaternion newRotation;
    
                        if (sourceState.sourcePose.TryGetRotation(out newRotation, InteractionSourceNode.Pointer) && ValidRotation(newRotation))
                        {
                            Controller.transform.localRotation = newRotation;
                        }
                    }
                }
            }
            else
            {
                // Controller source not detected. 
                message = "<color=blue>Trying to detect controller source</color>";
    
                if (_isAttached == true)
                {
                    // A source was previously connected, however, has been lost. Disconnected
                    // all registered events. 
    
                    _isAttached = false;
    
                    InteractionManager.InteractionSourceUpdated -= InteractionManager_InteractionSourceUpdated;
    
                    message = "<color=red>Source Lost: Detaching Controller Source Events</color>";
                }
            }
    
            if(message != string.Empty)
            {
                Debug.Log(message);
            }
    #endif
        }
    
        /// <summary>
        /// This registered event is triggered when a source state has been updated.
        /// </summary>
        /// <param name="obj"></param>
        private void InteractionManager_InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
        {
            if (obj.state.source.handedness == _handness)
            {
                if(obj.state.thumbstickPosition.magnitude > 0.2f)
                {
                    float thumbstickY = obj.state.thumbstickPosition.y;
    
                    // Vertical Input.
                    if (thumbstickY > 0.3f || thumbstickY < -0.3f)
                    {
                        _playerMovementTranslation = Camera.main.transform.forward;
                        _playerMovementTranslation.y = 0;
                        transform.Translate(_playerMovementTranslation * UserSpeed * Time.deltaTime * thumbstickY, Space.World);
                    }
                }
            }
        }
    
        /// <summary>
        /// Check that controller position is valid. 
        /// </summary>
        /// <param name="inputVector3">The Vector3 to check</param>
        /// <returns>The position is valid</returns>
        private bool ValidPosition(Vector3 inputVector3)
        {
            return !float.IsNaN(inputVector3.x) && !float.IsNaN(inputVector3.y) && !float.IsNaN(inputVector3.z) && !float.IsInfinity(inputVector3.x) && !float.IsInfinity(inputVector3.y) && !float.IsInfinity(inputVector3.z);
        }
    
        /// <summary>
        /// Check that controller rotation is valid. 
        /// </summary>
        /// <param name="inputQuaternion">The Quaternion to check</param>
        /// <returns>The rotation is valid</returns>
        private bool ValidRotation(Quaternion inputQuaternion)
        {
            return !float.IsNaN(inputQuaternion.x) && !float.IsNaN(inputQuaternion.y) && !float.IsNaN(inputQuaternion.z) && !float.IsNaN(inputQuaternion.w) && !float.IsInfinity(inputQuaternion.x) && !float.IsInfinity(inputQuaternion.y) && !float.IsInfinity(inputQuaternion.z) && !float.IsInfinity(inputQuaternion.w);
        }   
    
  6. Na koniec dodaj wywołanie metody w metodzie Update().

        // Update is called once per frame
        void Update()
        {
            UpdateControllerState();
        }
    
  7. Pamiętaj, aby zapisać zmiany w programie Visual Studio przed powrotem do aparatu Unity.

Rozdział 11 — Konfigurowanie odwołań do skryptów

W tym rozdziale należy umieścić skrypt ruchu na obiekcie nadrzędnym aparatu i ustawić jego elementy docelowe odniesienia. Ten skrypt będzie następnie obsługiwać umieszczanie innych skryptów tam, gdzie muszą być.

  1. Z folderu Scripts (Skrypty ) w panelu projektu przeciągnij skrypt Movement do obiektu nadrzędnego aparatu znajdującego się w panelu hierarchii.

    Zrzut ekranu przedstawiający panele projektu i hierarchii. Ruch został wyróżniony.

  2. Kliknij pozycję Aparat nadrzędny. W Panelu hierarchii przeciągnij obiekt Prawa ręka z Panelu hierarchii do obiektu docelowego odwołania Kontroler w Panelu inspektora. Ustaw wartość Szybkość użytkownika na 5, jak pokazano na poniższej ilustracji.

    Zrzut ekranu przedstawiający panele Hierarchia i Inspektor. Linia łączy prawą rękę na obu panelach.

Rozdział 12 — Tworzenie projektu aparatu Unity

Wszystko, co jest potrzebne w sekcji aparatu Unity tego projektu, zostało ukończone, więc nadszedł czas, aby skompilować go z poziomu aparatu Unity.

  1. Przejdź do obszaru Ustawienia kompilacji (Ustawienia kompilacjipliku>).

  2. W oknie Ustawienia kompilacji kliknij pozycję Kompiluj.

    Zrzut ekranu przedstawiający okno Ustawienia kompilacji z wyświetlonymi scenami w kompilacji.

  3. Zostanie wyświetlone okno Eksplorator plików z monitem o lokalizację kompilacji. Utwórz nowy folder (klikając pozycję Nowy folder w lewym górnym rogu) i nadaj mu nazwę BUILDS.

    Zrzut ekranu przedstawiający Eksplorator plików z wyróżnionym folderem Kompilacje.

    1. Otwórz nowy folder BUILDS i ponownie utwórz inny folder (przy użyciu nowego folderu ) i nadaj mu nazwę MR_Azure_Application_Insights.

      Zrzut ekranu eksploratora plików przedstawiający folder MR_Azure_Insights.

    2. Po wybraniu folderu MR_Azure_Application_Insights kliknij pozycję Wybierz folder. Kompilacja projektu może potrwać kilka minut.

  4. Po utworzeniuEksplorator plików zostanie wyświetlona lokalizacja nowego projektu.

Rozdział 13 — Wdrażanie aplikacji MR_Azure_Application_Insights na maszynie

Aby wdrożyć aplikację MR_Azure_Application_Insights na komputerze lokalnym:

  1. Otwórz plik rozwiązania aplikacji MR_Azure_Application_Insights w programie Visual Studio.

  2. W polu Platforma rozwiązania wybierz pozycję x86, Komputer lokalny.

  3. W obszarze Konfiguracja rozwiązania wybierz pozycję Debuguj.

    Zrzut ekranu przedstawiający ekran Konfiguracja rozwiązania programu Visual Studio przedstawiający pozycję Debuguj na pasku menu.

  4. Przejdź do menu Kompilacja i kliknij pozycję Wdróż rozwiązanie , aby załadować aplikację bezpośrednio na maszynę.

  5. Aplikacja powinna być teraz wyświetlana na liście zainstalowanych aplikacji gotowych do uruchomienia.

  6. Uruchom aplikację rzeczywistości mieszanej.

  7. Poruszaj się po scenie, zbliżając się do obiektów i patrząc na nie, gdy usługa Azure Insight Service zebrała wystarczającą ilość danych zdarzeń, ustawi obiekt, który był najbardziej zielony.

Ważne

Podczas gdy średni czas oczekiwania na zbieranie zdarzeń i metryk przez usługę trwa około 15 minut, w niektórych przypadkach może to potrwać do 1 godziny.

Rozdział 14 — portal usługi Application Insights

Po wędrowania po scenie i przyjrzeniu się kilku obiektom można zobaczyć dane zebrane w portalu usługi Application Insights .

  1. Wstecz do portalu usługi Application Insights.

  2. Wybierz pozycję Eksplorator metryk.

    Zrzut ekranu przedstawiający panel MyNewInsight przedstawiający listę opcji. Eksplorator metryk znajduje się na liście w sekcji Badanie.

  3. Zostanie on otwarty na karcie zawierającej graf, który reprezentuje zdarzenia i metryki powiązane z aplikacją. Jak wspomniano powyżej, wyświetlenie danych na wykresie może potrwać do 1 godziny

    Zrzut ekranu przedstawiający graf zdarzeń i metryk w Eksploratorze metryk.

  4. Wybierz pasek Zdarzenia w obszarze Total of Events by Application Version ( Łączna liczba zdarzeń według wersji aplikacji), aby wyświetlić szczegółowy podział zdarzeń o ich nazwach.

    Zrzut ekranu przedstawiający panel Wyszukiwania przedstawiający wyniki niestandardowego filtru zdarzeń.

Ukończono aplikację usługi Application Insights

Gratulacje, utworzono aplikację rzeczywistości mieszanej, która korzysta z usługi Application Insights do monitorowania aktywności użytkownika w aplikacji.

Ekran powitalny kursu.

Ćwiczenia dodatkowe

Ćwiczenie 1

Spróbuj zduplikować, a nie ręcznie utworzyć obiekty ObjectInScene i ustawić ich współrzędne na płaszczyźnie w skryptach. W ten sposób można zapytać platformę Azure, jaki był najbardziej popularny obiekt (na podstawie spojrzenia lub wyników zbliżeniowych) i zduplikować dodatkowy obiekt.

Ćwiczenie 2

Posortuj wyniki usługi Application Insights według czasu, aby uzyskać najbardziej odpowiednie dane i zaimplementować te dane poufne czasowo w aplikacji.