Udostępnij za pośrednictwem


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

Uwaga

Samouczki akademii rzeczywistości mieszanej zostały zaprojektowane z myślą o urządzeniach HoloLens (1. generacji) i zestawach słuchawkowych immersyjnych rzeczywistości mieszanej. W związku z tym uważamy, że ważne jest pozostawienie tych samouczków na miejscu dla deweloperów, którzy nadal szukają wskazówek dotyczących opracowywania tych urządzeń. Te samouczki nie zostaną zaktualizowane przy użyciu najnowszych zestawów narzędzi ani interakcji używanych dla urządzenia 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ć urządzenia 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 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 łatwego w użyciu portalu. Analiza może być niczym, od wydajności do informacji niestandardowych, 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. Wyzwól wysyłanie 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 środowisku Unity. Zastosowanie tych pojęć do niestandardowej aplikacji, 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 zestawach nagłownych immersywnych windows Mixed Reality (VR), możesz również zastosować to, czego nauczysz się w tym kursie do urządzenia Microsoft HoloLens. Zgodnie 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ć 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ące oprogramowanie i sprzęt:

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, 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 witrynie Azure Portal.

  1. Zaloguj się do Portalu Azure.

    Uwaga

    Jeśli nie masz jeszcze konta platformy Azure, musisz je utworzyć. Jeśli obserwujesz ten samouczek w sytuacji w klasie 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. Szczegółowe informacje zostały wyróżnione 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 Usługi 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 pozycję 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ąć 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 są 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 aplikacji.

    Zrzut ekranu przedstawiający funkcje usługi, wyróżniono pozycję A P I Access. 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 Utwórz klucz 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, więc upewnij się, że teraz utworzysz jego kopię.

Rozdział 2 . Konfigurowanie projektu aparatu Unity

Poniżej przedstawiono typową konfigurację programowania z rzeczywistością mieszaną, 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 szablon jest ustawiony na 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 nowe projekty 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 zewnętrznego edytora skryptów.

  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 urządzenia 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. W tym celu wybierz 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 dowolnego przyszłego sceny, a następnie kliknij przycisk Nowy folder, aby utworzyć nowy folder , nazwij go Sceny.

        Zrzut ekranu przedstawiający okno Zapisz scenę i wybrano 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 Zapisywanie sceny 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 przestrzeni, w której 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 uruchomieniowego skryptó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 pole wyboru Klient internetowy.

    3. W dalszej części panelu w obszarze Ustawienia XR (znajdujące się poniżej ustawień publikowania) zaznacz pole Virtual Reality Supported (Obsługiwana rzeczywistość wirtualna), upewnij się, że dodano zestaw WINDOWS Mixed Reality SDK.

      Zrzut ekranu przedstawiający sekcję Ustawienia języka X R z zaznaczoną pozycją Obsługiwana rzeczywistość wirtualna.

  9. Po powrocie do ustawień kompilacji projekty 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 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 w środowisku Unity występuje znany problem, 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 wyświetlonym oknie Importuj pakiet aparatu Unity upewnij się, że wybrano wszystkie elementy w obszarze (i w tym) 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 Szczegółowe informacje w obszarze Wtyczki w widoku Projektu i wybierz tylko następujące wtyczki:

    • Microsoft.ApplicationInsights

    Zrzut ekranu przedstawiający panel Project (Projekt) otwarty folder Insights.

  5. Po wybraniu tej wtyczki upewnij się, że wszystkie platformyniezaznaczone, a następnie upewnij się, że 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 (Autonomiczna).

    Uwaga

    Oznaczanie wtyczek w następujący sposób powoduje skonfigurowanie ich 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 skonfigurowanego pliku. Wybierz ten plik, a następnie w inspektorze upewnij się, że pole wyboru Dowolna platforma jest niezaznaczone, a następnie upewnij się, że zaznaczono tylko element WSAPlayer. Kliknij Zastosuj.

    Zrzut ekranu przedstawiający panel Inspector (Inspektor) z zaznaczonym polem W S A Player (Odtwarzacz W S A).

  7. Teraz należy wykonać kroki 4–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 wtyczki.

Rozdział 4 . Konfigurowanie aparatu i kontrolek użytkownika

W tym rozdziale skonfigurujesz aparat i kontrolki, aby umożliwić użytkownikowi wyświetlanie i poruszanie się 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 z wybraną pozycją Utwórz puste.

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

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną funkcją Nawias fotograficzny. Panel Inspector (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 zderzającego sferę, a następnie usuń składnik.

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

  7. W panelu hierarchii przeciągnij obiekty Main Camera i Right Hand na obiekt nadrzędny aparatu fotograficznego.

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną pozycją Główny aparat, panel Inspector (Inspektor) pokazuje zaznaczoną opcję Main Camera (Główny aparat).

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

    Zrzut ekranu przedstawiający panel Hierarchia z wybraną pozycją Główny aparat, w panelu Inspector (Inspektor) wyróżniono pozycję Przekształć ustawienia.

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

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

Teraz utworzysz kilka podstawowych kształtów sceny, za pomocą których użytkownik może wchodzić w interakcje.

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

  2. Ustaw pozycję przekształcania płaszczyzny na 0, -1, 0.

  3. Ustaw skalowanie 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 , aby ułatwić wyświetlanie innych kształtów. 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 Materials, a następnie kliknij prawym przyciskiem myszy pozycję Utwórz, a następnie pozycję Materiał, aby utworzyć nowy materiał. Nadaj jej 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 Szesnastkowy kolor: #3592FFFF). Kliknij przycisk Zamknij po wybraniu.

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

  7. Przeciągnij nowy materiał z folderu Materials 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 Materials.

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

    • Po wybraniu opcji Kapsuła zmień położenie przekształcenia na: -10, 1, 0.
  9. Kliknij prawym przyciskiem myszy pusty obszar w panelu hierarchii, a następnie w obszarze Obiekt 3D, Cube.

    • Po wybraniu modułu zmień położenie przekształcenia na: 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ń położenie przekształcenia na: 10, 0, 0.

    Zrzut ekranu przedstawiający panele Scena, Hierarchia i Inspektor. Kapsuła jest wybrana na panelu Hierarchy (Hierarchia).

    Uwaga

    Te wartości pozycji to sugestie. Możesz ustawić położenie obiektów na dowolną wartość, chociaż jest to łatwiejsze dla użytkownika aplikacji, jeśli odległości obiektów nie są zbyt dalekie od aparatu.

  11. Gdy aplikacja jest uruchomiona, musi być w stanie zidentyfikować obiekty w scenie, aby to osiągnąć, muszą być oznakowane. Wybierz jeden z obiektów, a następnie w panelu Inspector (Inspektor) kliknij przycisk Add Tag...( Dodaj tag...), co spowoduje zamianę inspektora na panel Tagi i 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 Inspector (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ż zmieniona na 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 Shift, a następnie kliknij kapsułę, moduł i sferę, obiekty, 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 Untagged (Nieoznakowane), a opcja ObjectInScene (ObiektInScene) 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 przesłania ich 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 w panelu projektu, a następnie utwórz>folder. Nadaj folderowi nazwę Scripts( Skrypty).

    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 Skrypty 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 był następujący:

        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

    Odpowiednio ustaw 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. Przed powrotem do aparatu Unity pamiętaj o zapisaniu zmian w programie Visual Studio.

Rozdział 7 . Tworzenie skryptu okiem

Następnym skryptem do utworzenia jest skrypt gaze. Ten skrypt jest odpowiedzialny za utworzenie raycast, 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 Skrypty, aby go otworzyć.

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

  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. Teraz należy 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 wykrywać 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ępnym skryptem, który należy utworzyć, jest ObjectTrigger, który jest odpowiedzialny za:

  • Dodawanie składników potrzebnych 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 Skrypty, aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty), kliknij polecenie 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. Przed powrotem do aparatu Unity pamiętaj o zapisaniu zmian w programie Visual Studio.

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 zwróciła się kamera.
  • Używając 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 Skrypty, aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty), kliknij polecenie 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 klucz-wartość z obiektem GameObject i numerem liczby zdarzeń symbolu zastępczego. Następnie inicjuje coroutine GetWebRequest(). Struktura zapytań wywołania do 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 DeterminWinner(), która sortuje listę par GameObject i Int , zgodnie z największą liczbą zdarzeń. Następnie zmienia kolor materiału tego 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 DataFromAnalytics poza 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. Przed powrotem do aparatu Unity pamiętaj o zapisaniu zmian w programie Visual Studio.

Rozdział 10 — Tworzenie klasy Ruchu

Skrypt przenoszenia to następny 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 Skrypty, aby go otworzyć.

  2. Kliknij prawym przyciskiem myszy wewnątrz folderu Scripts (Skrypty), kliknij polecenie Create C# Script (Utwórz>skrypt języka C#). Nazwij ruch 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;
        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 Movement poniżej pustej metody Update() wstaw następujące metody, które umożliwiają użytkownikowi przenoszenie się w przestrzeni wirtualnej za pomocą kontrolera ręki:

        /// <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. Przed powrotem do aparatu Unity pamiętaj o zapisaniu zmian w programie Visual Studio.

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, w których muszą być.

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

    Zrzut ekranu przedstawiający panele Projekt i Hierarchia. Ruch jest wyróżniony.

  2. Kliknij element nadrzędny aparatu. 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 — Kompilowanie 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 kompilacji pliku>).

  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 utwórz inny folder (ponownie użyj 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. Skompilowanie projektu potrwa minutę.

  4. Po utworzeniu Eksplorator 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. Poruszanie się po scenie, zbliżanie się do obiektów i przyjrzenie się im, gdy usługa Azure Insight Service zebrała wystarczającą ilość danych zdarzenia, 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 upłynąć do 1 godziny.

Rozdział 14 — portal usługi Application Insights

Po przejeżdżeniu po scenie i spojrzeniu na kilka obiektów można zobaczyć dane zebrane w portalu usługi Application Insights.

  1. Wróć 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 związane z aplikacją. Jak wspomniano powyżej, wyświetlenie danych na wykresie może potrwać do 1 godziny

    Zrzut ekranu Przedstawiający wykres 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 Service

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 bonusowe

Ć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 (z spojrzenia lub wyników sąsiedztwa) i zduplikować dodatkowy obiekt.

Ćwiczenie 2

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