Dane wejściowe MR 213: Kontrolery ruchu

Uwaga

Samouczki dotyczące akademii Mixed Reality 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 tych urządzeń. Te samouczki nie zostaną zaktualizowane przy użyciu najnowszych zestawów narzędzi ani interakcji używanych do HoloLens 2. Będą one utrzymywane w celu kontynuowania pracy na obsługiwanych urządzeniach. Opublikowano nową serię samouczków dla HoloLens 2.

Kontrolery ruchu w świecie rzeczywistości mieszanej dodają kolejny poziom interakcyjności. Dzięki kontrolerom ruchu możemy bezpośrednio wchodzić w interakcje z obiektami w bardziej naturalny sposób, podobnie jak w przypadku naszych interakcji fizycznych w prawdziwym życiu, zwiększając immersję i rozkosz w środowisku aplikacji.

W danych wejściowych MR 213 zbadamy zdarzenia wejściowe kontrolera ruchu, tworząc proste środowisko malowania przestrzennego. Dzięki tej aplikacji użytkownicy mogą malować w przestrzeni trójwymiarowej z różnymi typami pędzli i kolorów.

Tematy omówione w tym samouczku

MixedReality213 Temat1 MixedReality213 Temat2 MixedReality213 Temat3
Wizualizacja kontrolera Zdarzenia wejściowe kontrolera Kontroler niestandardowy i interfejs użytkownika
Dowiedz się, jak renderować modele kontrolera ruchu w trybie gry i środowisku uruchomieniowym aparatu Unity. Omówienie różnych typów zdarzeń przycisków i ich aplikacji. Dowiedz się, jak nakładać elementy interfejsu użytkownika na kontrolerze lub w pełni go dostosować.

Obsługa urządzeń

Kurs HoloLens Immersyjne zestawy słuchawkowe
Dane wejściowe MR 213: Kontrolery ruchu ✔️

Przed rozpoczęciem

Wymagania wstępne

Zobacz listę kontrolną instalacji, aby uzyskać immersyjne zestawy nagłowne na tej stronie.

Pliki projektu

  • Pobierz pliki wymagane przez projekt i wyodrębnij pliki do pulpitu.

Uwaga

Jeśli chcesz przejrzeć kod źródłowy przed pobraniem, jest on dostępny w witrynie GitHub.

Konfiguracja aparatu Unity

Cele

  • Optymalizowanie aparatu Unity pod kątem programowania Windows Mixed Reality
  • Konfigurowanie aparatu Mixed Reality
  • Środowisko konfiguracji

Instrukcje

  • Uruchom środowisko Unity.

  • Wybierz pozycję Otwórz.

  • Przejdź do pulpitu i znajdź wcześniej niearchiwniony folder MixedReality213-master .

  • Kliknij przycisk Wybierz folder.

  • Po zakończeniu ładowania plików projektu przez środowisko Unity będzie można zobaczyć edytor aparatu Unity.

  • W środowisku Unity wybierz pozycję Ustawienia kompilacji pliku>.

    MR213_BuildSettings

  • Wybierz pozycję platforma uniwersalna systemu Windows na liście Platforma, a następnie kliknij przycisk Przełącz platformę.

  • Ustaw urządzenie docelowe na dowolne urządzenie

  • Ustaw typ kompilacji na D3D

  • Ustaw zestaw SDK na najnowszą zainstalowaną

  • Sprawdzanie projektów języka C# aparatu Unity

    • Dzięki temu można modyfikować pliki skryptów w projekcie programu Visual Studio bez ponownego kompilowania projektu aparatu Unity.
  • Kliknij pozycję Ustawienia odtwarzacza.

  • W panelu Inspektor przewiń w dół do dołu

  • W obszarze Ustawienia XR sprawdź, czy jest obsługiwana rzeczywistość wirtualna

  • W obszarze Zestawy SDK rzeczywistości wirtualnej wybierz pozycję Windows Mixed Reality

    MR213_XRSettings

  • Zamknij okno Ustawienia kompilacji .

Struktura projektu

W tym samouczku jest używany zestaw narzędzi Mixed Reality Toolkit — Unity. Wydania można znaleźć na tej stronie.

Struktura projektu

Ukończone sceny dla dokumentacji

  • W obszarze Sceny znajdują się dwie ukończone sceny aparatu Unity.
    • MixedReality213: Ukończono scenę z pojedynczym pędzlem
    • MixedReality213Advanced: Ukończono scenę do zaawansowanego projektowania z wieloma pędzlami

Konfiguracja nowej sceny na potrzeby samouczka

  • W środowisku Unity kliknij pozycję Plik > nowa scena

  • Usuń kamerę główną i światło kierunkowe

  • Z panelu Projekt wyszukaj i przeciągnij następujące prefabki do panelu Hierarchia :

    • Assets/HoloToolkit/Input/Prefabs/MixedRealityCamera
    • Assets/AppPrefabs/Environment

    Aparat fotograficzny i środowisko

  • W zestawie narzędzi Mixed Reality znajdują się dwa prefabryki aparatu:

    • MixedRealityCamera.prefab: Tylko aparat fotograficzny
    • MixedRealityCameraParent.prefab: Aparat + Teleportacja + Granica
    • W tym samouczku użyjemy funkcji MixedRealityCamera bez funkcji teleportacji. W związku z tym dodaliśmy prostą prefabę Środowiska , która zawiera podstawową podłogę, aby użytkownik czuł się uziemiony.
    • Aby dowiedzieć się więcej o teleportacji za pomocą MixedRealityCameraParent, zobacz Advanced design - Teleportation and locomotion

Konfiguracja skybox

  • Kliknij pozycję Ustawienia oświetlenia > okna >

  • Kliknij okrąg po prawej stronie pola Materiał skybox

  • Wpisz ciąg "gray" i wybierz pozycję SkyboxGray (Assets/AppPrefabs/Support/Materials/SkyboxGray.mat)

    Ustawianie skyboxu

  • Zaznacz opcję Skybox , aby móc zobaczyć przypisany szary gradient skybox

    Przełącz opcję skybox

  • Scena z MixedRealityCamera, Environment i szary skybox będzie wyglądać następująco.

    Środowisko MixedReality213

  • Kliknij pozycję Zapisz scenę pliku > jako

  • Zapisz scenę w folderze Sceny z dowolną nazwą

Rozdział 1 — Wizualizacja kontrolera

Cele

  • Dowiedz się, jak renderować modele kontrolera ruchu w trybie gry aparatu Unity i w czasie wykonywania.

Windows Mixed Reality udostępnia animowany model kontrolera do wizualizacji kontrolera. Istnieje kilka metod wizualizacji kontrolera w aplikacji:

  • Ustawienie domyślne — używanie kontrolera domyślnego bez modyfikacji
  • Hybryda — używanie domyślnego kontrolera, ale dostosowywanie niektórych elementów lub zastępowanie składników interfejsu użytkownika
  • Zastąpienie — korzystanie z własnego dostosowanego modelu 3D dla kontrolera

W tym rozdziale poznamy przykłady tych dostosowań kontrolera.

Instrukcje

  • W panelu Projekt wpisz MotionControllers w polu wyszukiwania . Można go również znaleźć w obszarze Assets/HoloToolkit/Input/Prefabs/.
  • Przeciągnij prefabrykacje MotionControllers do panelu Hierarchia .
  • Kliknij prefab MotionControllers w panelu Hierarchia .

Prefab motionControllers

Prefab MotionControllers ma skrypt MotionControllerVisualizer , który udostępnia gniazda dla alternatywnych modeli kontrolera. Jeśli przypiszesz własne niestandardowe modele 3D, takie jak ręka lub miecz, i sprawdzisz opcję "Zawsze używaj alternatywnego modelu lewego/prawego", zobaczysz je zamiast modelu domyślnego. Użyjemy tego gniazda w rozdziale 4, aby zastąpić model kontrolera pędzlem.

MR213_ControllerVisualizer

Instrukcje

  • W panelu Inspector (Inspektor ) kliknij dwukrotnie skrypt MotionControllerVisualizer , aby wyświetlić kod w programie Visual Studio

Skrypt MotionControllerVisualizer

Klasy MotionControllerVisualizer i MotionControllerInfo zapewniają środki dostępu do & modyfikowania domyślnych modeli kontrolera. MotionControllerVisualizer subskrybuje zdarzenie InteractionSourceDetected aparatu Unity i automatycznie tworzy wystąpienia modeli kontrolera po ich znalezieniu.

protected override void Awake()
{
    ...
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    ...
}

Modele kontrolera są dostarczane zgodnie ze specyfikacją glTF. Ten format został utworzony w celu zapewnienia wspólnego formatu, jednocześnie poprawiając proces przesyłania i rozpakowywania zasobów 3D. W takim przypadku musimy pobrać i załadować modele kontrolera w czasie wykonywania, ponieważ chcemy, aby środowisko użytkownika było jak najbardziej bezproblemowe i nie ma gwarancji, której wersji kontrolerów ruchu może używać użytkownik. Ten kurs, za pośrednictwem zestawu narzędzi Mixed Reality, używa wersji projektu UnityGLTF grupy Khronos.

Po dostarczeniu kontrolera skrypty mogą używać funkcji MotionControllerInfo do znajdowania przekształceń dla określonych elementów kontrolera, aby mogły prawidłowo ustawić się.

W dalszej części dowiesz się, jak za pomocą tych skryptów dołączać elementy interfejsu użytkownika do kontrolerów.

W niektórych skryptach znajdziesz bloki kodu z #if ! UNITY_EDITOR lub UNITY_WSA. Te bloki kodu są uruchamiane tylko w środowisku uruchomieniowym platformy UWP podczas wdrażania w systemie Windows. Dzieje się tak, ponieważ zestaw interfejsów API używanych przez edytor aparatu Unity i środowisko uruchomieniowe aplikacji platformy UWP różnią się.

  • Zapisz scenę i kliknij przycisk odtwarzania .

W zestawie słuchawkowym będzie można zobaczyć scenę z kontrolerami ruchu. Szczegółowe animacje można wyświetlić pod kątem kliknięć przycisków, ruchu szminki i wyróżniania dotyku touchpadu.

domyślna wizualizacja MR213_Controller

Rozdział 2 . Dołączanie elementów interfejsu użytkownika do kontrolera

Cele

  • Dowiedz się więcej o elementach kontrolerów ruchu
  • Dowiedz się, jak dołączać obiekty do określonych części kontrolerów

W tym rozdziale dowiesz się, jak dodawać elementy interfejsu użytkownika do kontrolera, do którego użytkownik może łatwo uzyskiwać dostęp i manipulować nimi w dowolnym momencie. Dowiesz się również, jak dodać prosty interfejs użytkownika selektora kolorów przy użyciu danych wejściowych touchpad.

Instrukcje

  • W panelu Projekt wyszukaj skrypt MotionControllerInfo .
  • W wyniku wyszukiwania kliknij dwukrotnie skrypt MotionControllerInfo , aby wyświetlić kod w programie Visual Studio.

Skrypt MotionControllerInfo

Pierwszym krokiem jest wybranie elementu kontrolera, do którego ma zostać dołączony interfejs użytkownika. Te elementy są definiowane w pliku ControllerElementEnum w pliku MotionControllerInfo.cs.

MR213 MotionControllerElements

  • Ekran główny
  • Menu
  • Zrozumieć
  • Szminka
  • Wybierz
  • Touchpad
  • Pozycja wskazująca — ten element reprezentuje końcówkę kontrolera wskazującego kierunek do przodu.

Instrukcje

  • W panelu Projekt wyszukaj skrypt AttachToController .
  • W wynikach wyszukiwania kliknij dwukrotnie skrypt AttachToController , aby wyświetlić kod w programie Visual Studio.

AttachToController script (Skrypt AttachToController)

Skrypt AttachToController umożliwia proste dołączanie wszystkich obiektów do określonej ręki i elementu kontrolera.

W elemecie AttachElementToController(),

  • Sprawdzanie rękojści za pomocą elementu MotionControllerInfo.Handedness
  • Uzyskiwanie określonego elementu kontrolera przy użyciu elementu MotionControllerInfo.TryGetElement()
  • Po pobraniu przekształcenia elementu z modelu kontrolera umieść obiekt pod nim i ustaw pozycję lokalną obiektu & rotacji na zero.
public MotionControllerInfo.ControllerElementEnum Element { get { return element; } }

private void AttachElementToController(MotionControllerInfo newController)
{
     if (!IsAttached && newController.Handedness == handedness)
     {
          if (!newController.TryGetElement(element, out elementTransform))
          {
               Debug.LogError("Unable to find element of type " + element + " under controller " + newController.ControllerParent.name + "; not attaching.");
               return;
          }

          controller = newController;

          SetChildrenActive(true);

          // Parent ourselves under the element and set our offsets
          transform.parent = elementTransform;
          transform.localPosition = positionOffset;
          transform.localEulerAngles = rotationOffset;
          if (setScaleOnAttach)
          {
               transform.localScale = scale;
          }

          // Announce that we're attached
          OnAttachToController();
          IsAttached = true;
     }
}

Najprostszym sposobem użycia skryptu AttachToController jest dziedziczenie po nim, jak to zrobiliśmy w przypadku elementu ColorPickerWheel. Po prostu przesłonięć funkcje OnAttachToController i OnDetachFromController , aby wykonać konfigurację/podział po wykryciu/rozłączeniu kontrolera.

Instrukcje

  • W panelu Projekt wpisz pole wyszukiwania ColorPickerWheel. Można go również znaleźć w obszarze Assets/AppPrefabs/.
  • Przeciągnij prefab colorPickerWheel do panelu Hierarchia .
  • Kliknij prefab ColorPickerWheel w panelu Hierarchia .
  • W panelu Inspector (Inspektor) kliknij dwukrotnie pozycję ColorPickerWheel Script (Skrypt ColorPickerWheel ), aby wyświetlić kod w programie Visual Studio.

Prefab colorPickerWheel

Skrypt ColorPickerWheel

Ponieważ ColorPickerWheel dziedziczy element AttachToController, wyświetla on pozycję Ręka i element w panelu Inspektor . Dołączymy interfejs użytkownika do elementu Touchpad na lewym kontrolerze.

Skrypt ColorPickerWheel

ColorPickerWheel zastępuje element OnAttachToController i OnDetachFromController w celu zasubskrybowania zdarzenia wejściowego, które będzie używane w następnym rozdziale do wyboru kolorów z danymi wejściowymi touchpad.

public class ColorPickerWheel : AttachToController, IPointerTarget
{
    protected override void OnAttachToController()
    {
        // Subscribe to input now that we're parented under the controller
        InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
    }

    protected override void OnDetachFromController()
    {
        Visible = false;

        // Unsubscribe from input now that we've detached from the controller
        InteractionManager.InteractionSourceUpdated -= InteractionSourceUpdated;
    }
    ...
}
  • Zapisz scenę i kliknij przycisk odtwarzania .

Alternatywna metoda dołączania obiektów do kontrolerów

Zalecamy, aby skrypty dziedziczyły z elementu AttachToController i zastępowały onAttachToController. Jednak może to nie zawsze być możliwe. Alternatywą jest użycie go jako autonomicznego składnika. Może to być przydatne, gdy chcesz dołączyć istniejącą prefabę do kontrolera bez refaktoryzacji skryptów. Po prostu poczekaj na ustawienie isAttached na wartość true przed wykonaniem dowolnej konfiguracji. Najprostszym sposobem, aby to zrobić, jest użycie coroutine dla "Start".

private IEnumerator Start() {
    AttachToController attach = gameObject.GetComponent<AttachToController>();

    while (!attach.IsAttached) {
        yield return null;
    }

    // Perform setup here
}

Rozdział 3 . Praca z danymi wejściowymi touchpad

Cele

  • Dowiedz się, jak uzyskać zdarzenia danych wejściowych aplikacji TouchPad
  • Dowiedz się, jak używać informacji o położeniu osi touchpad dla środowiska aplikacji

Instrukcje

  • W panelu Hierarchia kliknij pozycję ColorPickerWheel
  • W panelu Inspector (Inspektor ) w obszarze Animator kliknij dwukrotnie pozycję ColorPickerWheelController
  • Będzie można zobaczyć otwartą kartę Animator

Wyświetlanie/ukrywanie interfejsu użytkownika za pomocą kontrolera animacji aparatu Unity

Aby pokazać i ukryć interfejs użytkownika ColorPickerWheel z animacją, używamy systemu animacji aparatu Unity. Ustawienie właściwości ColorPickerWheel'sVisible na wyzwalacze true lub false Pokaż i Ukryj wyzwalacze animacji. Pokaż i Ukryj parametry są definiowane w kontrolerze animacji ColorPickerWheelController .

Kontroler animacji aparatu Unity

Instrukcje

  • W panelu Hierarchia wybierz pozycję ColorPickerWheel prefab
  • W panelu Inspector (Inspektor) kliknij dwukrotnie skrypt ColorPickerWheel , aby wyświetlić kod w programie Visual Studio

Skrypt ColorPickerWheel

ColorPickerWheel subskrybuje zdarzenie InteractionSourceUpdated aparatu Unity w celu nasłuchiwania zdarzeń touchpad.

W obszarze InteractionSourceUpdated()skrypt najpierw sprawdza, czy:

  • jest w rzeczywistości zdarzeniem touchpad (obj.state.touchpadTouched)
  • pochodzi z lewego kontrolera (obj.state.source.wręczenie)

Jeśli oba są prawdziwe, pozycja tabletu dotykowego (obj.state).TouchpadPosition) jest przypisywany do selektoraPozycja.

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness && obj.state.touchpadTouched)
    {
        Visible = true;
        selectorPosition = obj.state.touchpadPosition;
    }
}

W elemencie Update(), na podstawie właściwości visible , wyzwala wyzwalacze Pokaż i Ukryj animacje w składniku animatora selektora kolorów

if (visible != visibleLastFrame)
{
    if (visible)
    {
        animator.SetTrigger("Show");
    }
    else
    {
        animator.SetTrigger("Hide");
    }
}

W update(), selektorPosition służy do rzutowania promienia na zderzacz siatki koła kolorów, który zwraca pozycję UV. Następnie można użyć tej pozycji do znalezienia współrzędnych pikseli i wartości koloru tekstury koła kolorów. Ta wartość jest dostępna dla innych skryptów za pośrednictwem właściwości SelectedColor .

Raycasting koła selektora kolorów

...
    // Clamp selector position to a radius of 1
    Vector3 localPosition = new Vector3(selectorPosition.x * inputScale, 0.15f, selectorPosition.y * inputScale);
    if (localPosition.magnitude > 1)
    {
        localPosition = localPosition.normalized;
    }
    selectorTransform.localPosition = localPosition;

    // Raycast the wheel mesh and get its UV coordinates
    Vector3 raycastStart = selectorTransform.position + selectorTransform.up * 0.15f;
    RaycastHit hit;
    Debug.DrawLine(raycastStart, raycastStart - (selectorTransform.up * 0.25f));

    if (Physics.Raycast(raycastStart, -selectorTransform.up, out hit, 0.25f, 1 << colorWheelObject.layer, QueryTriggerInteraction.Ignore))
    {
        // Get pixel from the color wheel texture using UV coordinates
        Vector2 uv = hit.textureCoord;
        int pixelX = Mathf.FloorToInt(colorWheelTexture.width * uv.x);
        int pixelY = Mathf.FloorToInt(colorWheelTexture.height * uv.y);
        selectedColor = colorWheelTexture.GetPixel(pixelX, pixelY);
        selectedColor.a = 1f;
    }
    // Set the selector's color and blend it with white to make it visible on top of the wheel
    selectorRenderer.material.color = Color.Lerp (selectedColor, Color.white, 0.5f);
}

Rozdział 4 — zastępowanie modelu kontrolera

Cele

  • Dowiedz się, jak zastąpić model kontrolera niestandardowym modelem 3D.

MR213_BrushToolOverride

Instrukcje

  • Kliknij pozycję MotionControllers na panelu Hierarchy (Hierarchia).
  • Kliknij okrąg po prawej stronie pola Alternatywny kontroler prawy .
  • Wpisz ciąg "BrushController" i wybierz prefab z wyniku. Można go znaleźć w obszarze Assets/AppPrefabs/BrushController.
  • Zaznacz zawsze używaj alternatywnego modelu prawego

MR213_BrushToolOverrideSlot

Prefab BrushController nie musi być uwzględniony w panelu Hierarchy ( Hierarchy ). Jednak aby sprawdzić jego składniki podrzędne:

  • W panelu Projekt wpisz BrushController i przeciągnij prefab BrushController do panelu Hierarchy (Hierarchia ).

MR213_BrushTool_Prefab2

Składnik Porada można znaleźć w narzędziu BrushController. Użyjemy jej transformacji, aby rozpocząć/zatrzymać linie rysunku.

  • Usuń narzędzie BrushController z panelu Hierarchy (Hierarchia ).
  • Zapisz scenę i kliknij przycisk odtwarzania . Zobaczysz, że model pędzla zastąpił prawy kontroler ruchu.

Rozdział 5 . Malowanie z wybieraniem danych wejściowych

Cele

  • Dowiedz się, jak użyć zdarzenia Wybierz przycisk, aby uruchomić i zatrzymać rysunek liniowy

Instrukcje

  • Wyszukaj prefabrykler BrushController w panelu Projekt .
  • Na panelu Inspector (Inspektor ) kliknij dwukrotnie pozycję BrushController Script (Skrypt BrushController ), aby wyświetlić kod w programie Visual Studio

Skrypt BrushController

BrushController subskrybuje zdarzenia InteractionSourcePressed i InteractionSourceReleased elementu InteractionManager. Po wyzwoleniu zdarzenia InteractionSourcePressed właściwość Draw pędzla jest ustawiona na wartość true; po wyzwoleniu zdarzenia InteractionSourceReleased właściwość Draw pędzla jest ustawiona na wartość false.

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = true;
    }
}

private void InteractionSourceReleased(InteractionSourceReleasedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = false;
    }
}

Gdy rysowanie ma wartość true, pędzel wygeneruje punkty w utworzeniu wystąpienia aparatu Unity LineRenderer. Odwołanie do tego prefab jest przechowywane w polu Stroke Prefab pędzla.

private IEnumerator DrawOverTime()
{
    // Get the position of the tip
    Vector3 lastPointPosition = tip.position;

    ...

    // Create a new brush stroke
    GameObject newStroke = Instantiate(strokePrefab);
    LineRenderer line = newStroke.GetComponent<LineRenderer>();
    newStroke.transform.position = startPosition;
    line.SetPosition(0, tip.position);
    float initialWidth = line.widthMultiplier;

    // Generate points in an instantiated Unity LineRenderer
    while (draw)
    {
        // Move the last point to the draw point position
        line.SetPosition(line.positionCount - 1, tip.position);
        line.material.color = colorPicker.SelectedColor;
        brushRenderer.material.color = colorPicker.SelectedColor;
        lastPointAddedTime = Time.unscaledTime;
        // Adjust the width between 1x and 2x width based on strength of trigger pull
        line.widthMultiplier = Mathf.Lerp(initialWidth, initialWidth * 2, width);

        if (Vector3.Distance(lastPointPosition, tip.position) > minPositionDelta || Time.unscaledTime > lastPointAddedTime + maxTimeDelta)
        {
            // Spawn a new point
            lastPointAddedTime = Time.unscaledTime;
            lastPointPosition = tip.position;
            line.positionCount += 1;
            line.SetPosition(line.positionCount - 1, lastPointPosition);
        }
        yield return null;
    }
}

Aby użyć aktualnie wybranego koloru z interfejsu użytkownika selektora kolorów, BrushController musi mieć odwołanie do obiektu ColorPickerWheel . Ponieważ prefab BrushController jest tworzone w czasie wykonywania jako kontroler zastępczy, wszystkie odwołania do obiektów w scenie będą musiały być ustawione w czasie wykonywania. W tym przypadku użyjemy elementu GameObject.FindObjectOfType do zlokalizowania elementu ColorPickerWheel:

private void OnEnable()
{
    // Locate the ColorPickerWheel
    colorPicker = FindObjectOfType<ColorPickerWheel>();

    // Assign currently selected color to the brush’s material color
    brushRenderer.material.color = colorPicker.SelectedColor;
    ...
}
  • Zapisz scenę i kliknij przycisk odtwarzania . Można narysować linie i malować za pomocą przycisku zaznacznia po prawej stronie kontrolera.

Rozdział 6 . Obiekt duplikujący z wybieraniem danych wejściowych

Cele

  • Dowiedz się, jak używać zdarzeń wejściowych przycisku Select and Grasp
  • Dowiedz się, jak utworzyć wystąpienia obiektów

Instrukcje

  • W panelu Projekt wpisz ObjectSpawner w polu wyszukiwania. Można go również znaleźć w obszarze Assets/AppPrefabs/

  • Przeciągnij prefab ObjectSpawner do panelu Hierarchy (Hierarchia ).

  • Kliknij pozycję ObjectSpawner na panelu Hierarchia .

  • ObiektSpawner ma pole o nazwie Źródło kolorów.

  • Z panelu Hierarchy (Hierarchia ) przeciągnij odwołanie ColorPickerWheel do tego pola.

    Inspektor duplikatora obiektów

  • Kliknij prefab ObjectSpawner w panelu Hierarchy (Hierarchia ).

  • Na panelu Inspector (Inspektor ) kliknij dwukrotnie pozycję ObjectSpawner Script (Skrypt objectSpawner ), aby wyświetlić kod w programie Visual Studio.

Skrypt ObjectSpawner

ObiektSpawner tworzy wystąpienia pierwotnej siatki (sześcianu, sfery, cylindra) w przestrzeni. Po wykryciu elementu InteractionSourcePressed sprawdza on rozdanie, a jeśli jest to zdarzenie InteractionSourcePressType.Grasp lub InteractionSourcePressType.Select .

W przypadku zdarzenia Uchwycić zwiększa indeks bieżącego typu siatki (sphere, cube, cylinder)

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    // Check handedness, see if it is left controller
    if (obj.state.source.handedness == handedness)
    {
        switch (obj.pressType)
        {
            // If it is Select button event, spawn object
            case InteractionSourcePressType.Select:
                if (state == StateEnum.Idle)
                {
                    // We've pressed the grasp - enter spawning state
                    state = StateEnum.Spawning;
                    SpawnObject();
                }
                break;

            // If it is Grasp button event
            case InteractionSourcePressType.Grasp:

                // Increment the index of current mesh type (sphere, cube, cylinder)
                meshIndex++;
                if (meshIndex >= NumAvailableMeshes)
                {
                    meshIndex = 0;
                }
                break;

            default:
                break;
        }
    }
}

W przypadku zdarzenia Select w metodzie SpawnObject()nowy obiekt jest tworzone, nieuwzroczone i zwalniane do świata.

private void SpawnObject()
{
    // Instantiate the spawned object
    GameObject newObject = Instantiate(displayObject.gameObject, spawnParent);
    // Detach the newly spawned object
    newObject.transform.parent = null;
    // Reset the scale transform to 1
    scaleParent.localScale = Vector3.one;
    // Set its material color so its material gets instantiated
    newObject.GetComponent<Renderer>().material.color = colorSource.SelectedColor;
}

ObiektSpawner używa colorPickerWheel, aby ustawić kolor materiału obiektu wyświetlania. Obiekty zduplikowane otrzymują wystąpienie tego materiału, dzięki czemu zachowają swój kolor.

  • Zapisz scenę i kliknij przycisk odtwarzania .

Będzie można zmienić obiekty za pomocą przycisku Uchwycić i zduplikować obiekty za pomocą przycisku Wybierz.

Kompilowanie i wdrażanie aplikacji w portalu Mixed Reality

  • W akrocie Unity wybierz pozycję Ustawienia kompilacji pliku>.
  • Kliknij pozycję Dodaj otwarte sceny , aby dodać bieżącą scenę do scen w kompilacji.
  • Kliknij pozycję Kompiluj.
  • Utwórz nowy folder o nazwie "Aplikacja".
  • Jednym kliknięciem folderu Aplikacja .
  • Kliknij przycisk Wybierz folder.
  • Po zakończeniu działania aparatu Unity zostanie wyświetlone okno Eksplorator plików.
  • Otwórz folder Aplikacja .
  • Kliknij dwukrotnie plik rozwiązania YourSceneName.sln programu Visual Studio.
  • Za pomocą górnego paska narzędzi w programie Visual Studio zmień element docelowy z Debuguj na Wydanie i z ARM na X64.
  • Kliknij strzałkę listy rozwijanej obok przycisku Urządzenie, a następnie wybierz pozycję Maszyna lokalna.
  • Kliknij pozycję Debuguj —> Rozpocznij bez debugowania w menu lub naciśnij klawisze Ctrl + F5.

Teraz aplikacja jest kompilowana i instalowana w portalu Mixed Reality. Możesz uruchomić go ponownie za pomocą menu Start w portalu Mixed Reality.

Zaawansowane projektowanie — narzędzia pędzla z układem promieniowym

MixedReality213 Main

W tym rozdziale dowiesz się, jak zastąpić domyślny model kontrolera ruchu niestandardowym kolekcją narzędzi pędzla. W dokumentacji można znaleźć ukończoną scenę MixedReality213Advanced w folderze Sceny .

Instrukcje

  • W panelu Projekt wpisz BrushSelector w polu wyszukiwania . Można go również znaleźć w obszarze Assets/AppPrefabs/

  • Przeciągnij prefabryktor BrushSelector do panelu Hierarchy (Hierarchia ).

  • W przypadku organizacji utwórz pusty obiekt GameObject o nazwie Brushes

  • Przeciągnij następujące prefabryki z panelu Projekt do obszaru Pędzle

    • Assets/AppPrefabs/BrushFat
    • Assets/AppPrefabs/BrushThin
    • Assets/AppPrefabs/Gumka
    • Assets/AppPrefabs/MarkerFat
    • Assets/AppPrefabs/MarkerThin
    • Assets/AppPrefabs/Pencil

    Pędzle

  • Kliknij pozycję Prefab motionControllers na panelu Hierarchy (Hierarchia).

  • Na panelu Inspector (Inspektor ) usuń zaznaczenie pola wyboru Always Use Alternate Right Model (Zawsze używaj alternatywnego modelu prawego ) w wizualizatorze kontrolera ruchu

  • Na panelu Hierarchia kliknij pozycję BrushSelector

  • BrushSelector ma pole o nazwie ColorPicker

  • Z panelu Hierarchia przeciągnij pole ColorPickerWheel do pola ColorPicker na panelu Inspector (Inspektor ).

    Przypisywanie elementu ColorPickerWheel do selektora pędzla

  • W panelu Hierarchy (Hierarchia ) w obszarze BrushSelector prefab (Prefab) wybierz obiekt Menu .

  • W panelu Inspector (Inspektor ) w obszarze składnika LineObjectCollection otwórz listę rozwijaną Tablica obiektów . Zobaczysz 6 pustych miejsc.

  • Z panelu Hierarchy (Hierarchia ) przeciągnij każdy z prefabów nadrzędnych pod obiektem Brushes GameObject do tych miejsc w dowolnej kolejności. (Upewnij się, że przeciągasz prefabryki ze sceny, a nie prefab w folderze projektu).

Selektor pędzla

Prefab brushSelector

Ponieważ funkcja BrushSelector dziedziczy element AttachToController, w panelu Inspector (Inspektor) są wyświetlane opcje Handedness i Element. Wybraliśmy opcję Right (Prawe ) i Pointing Pose (Punkt) w celu dołączenia narzędzi pędzla do prawego kontrolera z kierunkiem do przodu.

Aplikacja BrushSelector korzysta z dwóch narzędzi:

  • Elipsa: służy do generowania punktów w przestrzeni wzdłuż kształtu wielokropka.
  • LineObjectCollection: dystrybuuje obiekty przy użyciu punktów generowanych przez dowolną klasę Line (np. Elipse). To właśnie będziemy używać, aby umieścić nasze pędzle wzdłuż kształtu elipsy.

W połączeniu te narzędzia mogą służyć do tworzenia menu promieniowego.

Skrypt LineObjectCollection

Obiekt LineObjectCollection ma kontrolki dotyczące rozmiaru, położenia i obrotu obiektów rozmieszczonych wzdłuż linii. Jest to przydatne w przypadku tworzenia menu promieniowych, takich jak selektor pędzla. Aby utworzyć wygląd pędzli, które skalują się w górę z niczego, gdy zbliżają się do wybranej pozycji w centrum, krzywa ObjectScale szczyty w środku i przycinają się na krawędziach.

Skrypt BrushSelector

W przypadku narzędzia BrushSelector wybraliśmy opcję używania animacji proceduralnej. Po pierwsze modele pędzli są dystrybuowane w wielokropeku przez skrypt LineObjectCollection . Następnie każdy pędzel jest odpowiedzialny za utrzymanie swojej pozycji w ręku użytkownika na podstawie jego wartości DisplayMode , która zmienia się na podstawie zaznaczenia. Wybraliśmy podejście proceduralne ze względu na duże prawdopodobieństwo przerwania przejścia pozycji pędzla, gdy użytkownik wybiera pędzle. Animacje Mecanim mogą obsługiwać przerwy bezpiecznie, ale wydaje się być bardziej skomplikowane niż prosta operacja Lerp.

BrushSelector używa kombinacji obu tych elementów. Po wykryciu danych wejściowych touchpad opcje pędzla stają się widoczne i skalowane w górę wzdłuż menu promieniowego. Po upływie limitu czasu (co oznacza, że użytkownik dokonał wyboru) opcje pędzla są ponownie skalowane w dół, pozostawiając tylko zaznaczony pędzel.

Wizualizowanie danych wejściowych touchpad

Nawet w przypadkach, gdy model kontrolera został całkowicie zastąpiony, pomocne może być pokazanie danych wejściowych na oryginalnych danych wejściowych modelu. Pomaga to uziemić działania użytkownika w rzeczywistości. Dla pędzlaSelector wybraliśmy, aby touchpad był krótko widoczny po odebraniu danych wejściowych. Zostało to zrobione przez pobranie elementu Touchpad z kontrolera, zastąpienie jego materiału niestandardowym materiałem, a następnie zastosowanie gradientu do koloru tego materiału na podstawie ostatniego wejścia touchpad.

protected override void OnAttachToController()
{
    // Turn off the default controller's renderers
    controller.SetRenderersVisible(false);

    // Get the touchpad and assign our custom material to it
    Transform touchpad;
    if (controller.TryGetElement(MotionControllerInfo.ControllerElementEnum.Touchpad, out touchpad))
    {
        touchpadRenderer = touchpad.GetComponentInChildren<MeshRenderer>();
        originalTouchpadMaterial = touchpadRenderer.material;
        touchpadRenderer.material = touchpadMaterial;
        touchpadRenderer.enabled = true;
    }

    // Subscribe to input now that we're parented under the controller
    InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
}

private void Update()
{
    ...
    // Update our touchpad material
    Color glowColor = touchpadColor.Evaluate((Time.unscaledTime - touchpadTouchTime) / touchpadGlowLossTime);
    touchpadMaterial.SetColor("_EmissionColor", glowColor);
    touchpadMaterial.SetColor("_Color", glowColor);
    ...
}

Wybór narzędzia pędzla z wejściem touchpad

Gdy selektor pędzla wykryje naciśnięcie danych wejściowych touchpadu, sprawdza położenie danych wejściowych, aby określić, czy znajduje się w lewo, czy w prawo.

Grubość pociągnięcia z wybraną pozycjąPressedAmount

Zamiast zdarzenia InteractionSourcePressType.Select w elemecie InteractionSourcePressed(), możesz uzyskać analogową wartość naciśniętej kwoty, wybierając pozycjęPressedAmount. Tę wartość można pobrać w pliku InteractionSourceUpdated().

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness)
    {
        if (obj.state.touchpadPressed)
        {
            // Check which side we clicked
            if (obj.state.touchpadPosition.x < 0)
            {
                currentAction = SwipeEnum.Left;
            }
            else
            {
                currentAction = SwipeEnum.Right;
            }

            // Ping the touchpad material so it gets bright
            touchpadTouchTime = Time.unscaledTime;
        }

        if (activeBrush != null)
        {
            // If the pressed amount is greater than our threshold, draw
            if (obj.state.selectPressedAmount >= selectPressedDrawThreshold)
            {
                activeBrush.Draw = true;
                activeBrush.Width = ProcessSelectPressedAmount(obj.state.selectPressedAmount);
            }
            else
            {
                // Otherwise, stop drawing
                activeBrush.Draw = false;
                selectPressedSmooth = 0f;
            }
        }
    }
}

Skrypt gumki

Gumka jest specjalnym typem pędzla, który zastępuje funkcję DrawOverTime()pędzla podstawowego. Podczas gdy rysowanie jest prawdziwe, gumka sprawdza, czy jego końcówka przecina się z dowolnymi istniejącymi pociągnięciami pędzla. Jeśli tak się stanie, zostaną one dodane do kolejki, aby zostały one zmniejszone i usunięte.

Zaawansowane projektowanie — teleportacja i lokalizowanie

Jeśli chcesz zezwolić użytkownikowi na poruszanie się po scenie za pomocą teleportacji przy użyciu szminki, użyj MixedRealityCameraParent zamiast MixedRealityCamera. Należy również dodać elementy InputManager i DefaultCursor. Ponieważ MixedRealityCameraParent zawiera już elementy MotionControllers i Boundary jako składniki podrzędne, należy usunąć istniejące prefabrykatory MotionControllers i Environment .

Instrukcje

  • Na panelu Hierarchia usuń MixedRealityCamera, Environment i MotionControllers

  • Na panelu Project (Projekt) wyszukaj i przeciągnij następujące prefabryki do panelu Hierarchy (Hierarchia ):

    • Assets/AppPrefabs/Input/Prefabs/MixedRealityCameraParent
    • Assets/AppPrefabs/Input/Prefabs/InputManager
    • Assets/AppPrefabs/Input/Prefabs/Cursor/DefaultCursor

    obiekt nadrzędny aparatu Mixed Reality

  • Na panelu Hierarchia kliknij pozycję Menedżer danych wejściowych

  • W panelu Inspector (Inspektor ) przewiń w dół do sekcji Simple Single Pointer Selector (Selektor prostych wskaźników pojedynczych )

  • Z panelu Hierarchia przeciągnij pozycję DefaultCursor do pola Kursor

    Przypisywanie elementu DefaultCursor

  • Zapisz scenę i kliknij przycisk odtwarzania . Możesz użyć szminki, aby obrócić lewą/prawą lub teleportować.

Koniec

A to koniec tego samouczka! Wiesz teraz:

  • Jak pracować z modelami kontrolera ruchu w trybie gry i środowisku uruchomieniowym aparatu Unity.
  • Jak używać różnych typów zdarzeń przycisków i ich aplikacji.
  • Jak nakładać elementy interfejsu użytkownika na kontrolerze lub w pełni go dostosować.

Teraz możesz rozpocząć tworzenie własnego immersyjnego środowiska z kontrolerami ruchu.

Ukończone sceny

  • Na panelu Projekt aparatu Unity kliknij folder Sceny .
  • Znajdziesz dwie sceny Aparatu Unity MixedReality213 i MixedReality213Advanced.
    • MixedReality213: Ukończono scenę z pojedynczym pędzlem
    • MixedReality213Advanced: Ukończono scenę z wieloma pędzlami z przykładem wielkości naciśnięcia przycisku

Zobacz też