Delen via


MR-invoer 213: Bewegingscontrollers

Notitie

De Mixed Reality Academy-zelfstudies zijn ontworpen met HoloLens (1e generatie) en Mixed Reality Immersive Headsets in gedachten. Daarom vinden we het belangrijk om deze zelfstudies te laten staan voor ontwikkelaars die nog steeds op zoek zijn naar richtlijnen bij het ontwikkelen van deze apparaten. Deze zelfstudies worden niet bijgewerkt met de meest recente toolsets of interacties die worden gebruikt voor HoloLens 2. Ze worden onderhouden om te blijven werken op de ondersteunde apparaten. Er is een nieuwe reeks zelfstudies gepubliceerd voor HoloLens 2.

Bewegingscontrollers in de mixed reality-wereld voegen een ander niveau van interactiviteit toe. Met bewegingscontrollers kunnen we rechtstreeks op een natuurlijkere manier met objecten communiceren, vergelijkbaar met onze fysieke interacties in het echte leven, waardoor uw app-ervaring meer onderdompeling en plezier ervaart.

In MR Input 213 verkennen we de invoer gebeurtenissen van de bewegingscontroller door een eenvoudige ruimtelijke schilderervaring te creëren. Met deze app kunnen gebruikers in een driedimensionale ruimte schilderen met verschillende soorten borstels en kleuren.

Onderwerpen die in deze zelfstudie worden behandeld

MixedReality213-onderwerp1 MixedReality213 Onderwerp2 MixedReality213 Onderwerp3
Controllervisualisatie Invoer gebeurtenissen controller Aangepaste controller en gebruikersinterface
Meer informatie over het renderen van bewegingscontrollermodellen in de gamemodus en runtime van Unity. Inzicht in verschillende soorten knop gebeurtenissen en de bijbehorende toepassingen. Meer informatie over het overlayen van UI-elementen op de controller of het volledig aanpassen ervan.

Ondersteuning voor apparaten

Cursus HoloLens Immersive headsets
MR-invoer 213: Bewegingscontrollers ✔️

Voordat u begint

Vereisten

Zie de installatiecontrolelijst voor immersive headsets op deze pagina.

Projectbestanden

Notitie

Als u de broncode wilt bekijken voordat u deze downloadt, is deze beschikbaar op GitHub.

Unity instellen

Doelen

  • Unity optimaliseren voor Windows Mixed Reality ontwikkeling
  • Camera Mixed Reality instellen
  • Omgeving instellen

Instructies

  • Start Unity.

  • Selecteer Openen.

  • Navigeer naar uw bureaublad en zoek de map MixedReality213-master die u eerder hebt opgeslagen.

  • Klik op Map selecteren.

  • Zodra Unity klaar is met het laden van projectbestanden, kunt u de Unity-editor zien.

  • Selecteer in Unity Instellingen voor bestandsbuild>.

    MR213_BuildSettings

  • Selecteer Universeel Windows-platform in de lijst Platform en klik op de knop Ander platform.

  • Doelapparaat instellen op Elk apparaat

  • Buildtype instellen op D3D

  • SDK instellen op Laatst geïnstalleerd

  • Unity C#-projecten controleren

    • Hierdoor kunt u scriptbestanden in het Visual Studio-project wijzigen zonder dat u het Unity-project opnieuw hoeft te bouwen.
  • Klik op Spelerinstellingen.

  • Schuif in het deelvenster Inspector omlaag naar de onderkant

  • Schakel in XR-instellingen de optie Virtual Reality Supported (Virtual Reality Supported) in

  • Selecteer onder Virtual Reality SDK's de optie Windows Mixed Reality

    MR213_XRSettings

  • Sluit het venster Build-instellingen .

Projectstructuur

In deze zelfstudie wordt gebruikgemaakt van Mixed Reality Toolkit - Unity. U vindt de releases op deze pagina.

ProjectStructure

Voltooide scènes ter referentie

  • U vindt twee voltooide Unity-scènes onder de map Scènes .
    • MixedReality213: Voltooide scène met één penseel
    • MixedReality213Geavanceerd: Voltooide scène voor geavanceerd ontwerp met meerdere penselen

Nieuwe scène-instelling voor de zelfstudie

  • Klik in Unity op Nieuwe > scène bestand

  • Hoofdcamera en richtingslicht verwijderen

  • Zoek in het deelvenster Project de volgende prefabs en sleep deze naar het deelvenster Hiërarchie :

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

    Camera en omgeving

  • Er zijn twee camera-prefabs in Mixed Reality Toolkit:

    • MixedRealityCamera.prefab: alleen camera
    • MixedRealityCameraParent.prefab: Camera + Teleportation + Boundary
    • In deze zelfstudie gebruiken we MixedRealityCamera zonder teleportatiefunctie. Daarom hebben we eenvoudige Prefab Environment toegevoegd die een basisvloer bevat om de gebruiker zich geaard te laten voelen.
    • Zie Advanced design - Teleportation and locomotion (Geavanceerd ontwerp - teleportatie en locomotie) voor meer informatie over de teleportatie met MixedRealityCameraParent

Skybox instellen

  • Klik op Instellingen voor vensterverlichting >>

  • Klik op de cirkel aan de rechterkant van het veld Skybox-materiaal

  • Typ 'grijs' en selecteer SkyboxGray (Assets/AppPrefabs/Support/Materials/SkyboxGray.mat)

    Skybox instellen

  • Schakel de optie Skybox in om toegewezen skybox met grijze kleurovergang te kunnen zien

    Optie skybox in-/uitschakelen

  • De scène met MixedRealityCamera, Environment en grijze skybox ziet er als volgt uit.

    MixedReality213-omgeving

  • Klik op Bestand > Scène opslaan als

  • Sla uw scène op onder de map Scènes met een willekeurige naam

Hoofdstuk 1 - Visualisatie van controller

Doelen

  • Meer informatie over het renderen van bewegingscontrollermodellen in de gamemodus van Unity en tijdens runtime.

Windows Mixed Reality biedt een controllermodel met animatie voor controllervisualisatie. Er zijn verschillende benaderingen die u kunt gebruiken voor controllervisualisatie in uw app:

  • Standaard: standaardcontroller gebruiken zonder wijziging
  • Hybride: standaardcontroller gebruiken, maar enkele elementen ervan aanpassen of ui-onderdelen overlays
  • Vervanging: uw eigen aangepaste 3D-model gebruiken voor de controller

In dit hoofdstuk vindt u meer informatie over de voorbeelden van deze controlleraanpassingen.

Instructies

  • Typ motioncontrollers in het zoekvak in het deelvenster Project. U vindt deze ook onder Assets/HoloToolkit/Input/Prefabs/.
  • Sleep de prefab MotionControllers naar het deelvenster Hierarchy .
  • Klik op de prefab MotionControllers in het deelvenster Hierarchy .

MotionControllers prefab

MotionControllers-prefab heeft een MotionControllerVisualizer-script dat de sleuven voor alternatieve controllermodellen biedt. Als u uw eigen aangepaste 3D-modellen toewijst, zoals een hand of een zwaard en 'Altijd alternatief links/rechts model gebruiken' inschakelt, ziet u deze in plaats van het standaardmodel. We gebruiken deze sleuf in hoofdstuk 4 om het controllermodel te vervangen door een kwast.

MR213_ControllerVisualizer

Instructies

  • Dubbelklik in het deelvenster Inspector op MotionControllerVisualizer-script om de code in Visual Studio weer te geven

MotionControllerVisualizer-script

De klassen MotionControllerVisualizer en MotionControllerInfo bieden de middelen om toegang te krijgen tot & de standaardcontrollermodellen te wijzigen. MotionControllerVisualizer abonneert zich op de gebeurtenis InteractionSourceDetected van Unity en maakt automatisch een instantie van controllermodellen wanneer deze worden gevonden.

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

De controllermodellen worden geleverd volgens de glTF-specificatie. Deze indeling is gemaakt om een algemene indeling te bieden, terwijl het proces achter het verzenden en uitpakken van 3D-assets wordt verbeterd. In dit geval moeten we de controllermodellen tijdens runtime ophalen en laden, omdat we de gebruikerservaring zo naadloos mogelijk willen maken en het niet gegarandeerd is welke versie van de bewegingscontrollers de gebruiker mogelijk gebruikt. Deze cursus, via de Mixed Reality Toolkit, maakt gebruik van een versie van het UnityGLTF-project van de Khronos Group.

Zodra de controller is geleverd, kunnen scripts MotionControllerInfo gebruiken om de transformaties voor specifieke controllerelementen te vinden, zodat ze zichzelf correct kunnen positioneren.

In een later hoofdstuk leert u hoe u deze scripts kunt gebruiken om UI-elementen aan de controllers te koppelen.

In sommige scripts vindt u codeblokken met #if ! UNITY_EDITOR of UNITY_WSA. Deze codeblokken worden alleen uitgevoerd op de UWP-runtime wanneer u implementeert in Windows. Dit komt doordat de set API's die wordt gebruikt door de Unity-editor en de UWP-app-runtime verschillend zijn.

  • Sla de scène op en klik op de knop Afspelen .

U kunt de scène zien met bewegingscontrollers in uw headset. U ziet gedetailleerde animaties voor klikken op knoppen, bewegingen van duimsticks en aanraakmarkeringen op de touchpad.

Standaardvisualisatie van MR213_Controller

Hoofdstuk 2: UI-elementen koppelen aan de controller

Doelen

  • Meer informatie over de elementen van de bewegingscontrollers
  • Meer informatie over het koppelen van objecten aan specifieke onderdelen van de controllers

In dit hoofdstuk leert u hoe u elementen van de gebruikersinterface toevoegt aan de controller die de gebruiker gemakkelijk op elk gewenst moment kan openen en bewerken. U leert ook hoe u een eenvoudige gebruikersinterface voor kleurenkiezer toevoegt met behulp van de touchpadinvoer.

Instructies

  • Zoek in het deelvenster Project het script MotionControllerInfo .
  • Dubbelklik in het zoekresultaat op het script MotionControllerInfo om de code in Visual Studio weer te geven.

MotionControllerInfo-script

De eerste stap bestaat uit het kiezen van het element van de controller waaraan u de gebruikersinterface wilt koppelen. Deze elementen worden gedefinieerd in ControllerElementEnum in MotionControllerInfo.cs.

MR213 MotionControllerElements

  • Start
  • Menu
  • Begrijpen
  • Duimstick
  • Selecteren
  • Touchpad
  • Wijzende houding : dit element vertegenwoordigt de punt van de controller die naar voren wijst.

Instructies

  • Zoek in het deelvenster Project het script AttachToController .
  • Dubbelklik in het zoekresultaat op AttachToController-script om de code in Visual Studio weer te geven.

AttachToController-script

Het script AttachToController biedt een eenvoudige manier om objecten te koppelen aan een opgegeven controllerhandigheid en -element.

In AttachElementToController(),

  • Handvermogen controleren met MotionControllerInfo.Handedness
  • Een specifiek element van de controller ophalen met MotionControllerInfo.TryGetElement()
  • Nadat u de transformatie van het element uit het controllermodel hebt opgehaald, plaatst u het object eronder en stelt u de lokale positie van het object & rotatie in op nul.
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;
     }
}

De eenvoudigste manier om het AttachToController-script te gebruiken, is door ervan over te nemen, zoals we hebben gedaan in het geval van ColorPickerWheel. U hoeft alleen de functies OnAttachToController en OnDetachFromController te overschrijven om uw installatie/uitsplitsing uit te voeren wanneer de controller wordt gedetecteerd/verbroken.

Instructies

  • Typ in het deelvenster Project in het zoekvak ColorPickerWheel. U vindt deze ook onder Assets/AppPrefabs/.
  • Sleep de prefab ColorPickerWheel naar het deelvenster Hierarchy .
  • Klik op de prefab ColorPickerWheel in het deelvenster Hierarchy .
  • Dubbelklik in het deelvenster Inspector op ColorPickerWheel Script om de code in Visual Studio weer te geven.

ColorPickerWheel prefab

ColorPickerWheel-script

Omdat ColorPickerWheelAttachToController over neemt, worden Handheid en Element weergegeven in het deelvenster Inspector . We koppelen de gebruikersinterface aan het Touchpad-element op de linkercontroller.

ColorPickerWheel-script

ColorPickerWheel overschrijft de OnAttachToController en OnDetachFromController om u te abonneren op de invoergebeurtenis die in het volgende hoofdstuk wordt gebruikt voor kleurselectie met touchpadinvoer.

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;
    }
    ...
}
  • Sla de scène op en klik op de knop Afspelen .

Alternatieve methode voor het koppelen van objecten aan de controllers

U wordt aangeraden uw scripts over te nemen van AttachToController en OnAttachToController te overschrijven. Dit is echter niet altijd mogelijk. Een alternatief is het gebruik als een zelfstandig onderdeel. Dit kan handig zijn als u een bestaande prefab aan een controller wilt koppelen zonder uw scripts te herstructureren. Laat uw klas gewoon wachten tot IsAttached is ingesteld op true voordat u een installatie uitvoert. De eenvoudigste manier om dit te doen, is met behulp van een coroutine voor 'Start'.

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

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

    // Perform setup here
}

Hoofdstuk 3- Werken met touchpad-invoer

Doelen

  • Meer informatie over het ophalen van invoergegevens voor touchpads
  • Informatie over het gebruik van informatie over de positie van de touchpadas voor uw app-ervaring

Instructies

  • Klik in het deelvenster Hierarchy op ColorPickerWheel
  • Dubbelklik in het deelvenster Inspector onder Animator op ColorPickerWheelController
  • U kunt zien dat het tabblad Animator is geopend

Gebruikersinterface weergeven/verbergen met de animatiecontroller van Unity

We gebruiken het animatiesysteem van Unity om de gebruikersinterface van ColorPickerWheel met animatie weer te geven en te verbergen. Stel de eigenschap Visible van ColorPickerWheel in op waar of onwaar-triggers Animatietriggers weergeven en Verbergen. De parameters Weergeven en Verbergen zijn gedefinieerd in de animatiecontroller ColorPickerWheelController .

Unity Animation Controller

Instructies

  • Selecteer in het deelvenster Hierarchyde optie ColorPickerWheel prefab
  • Dubbelklik in het deelvenster Inspector op het script ColorPickerWheel om de code in Visual Studio weer te geven

ColorPickerWheel-script

ColorPickerWheel abonneert u op de gebeurtenis InteractionSourceUpdated van Unity om te luisteren naar touchpadgebeurtenissen.

In InteractionSourceUpdated() controleert het script eerst of het:

  • is eigenlijk een touchpadgebeurtenis (obj.state.touchpadTouched)
  • is afkomstig van de linkercontroller (obj.state.source.handgeleverdheid)

Als beide waar zijn, wordt de touchpadpositie (obj.state.touchpadPosition) is toegewezen aan selectorPosition.

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

In Update() worden, op basis van de eigenschap visible , animatietriggers weergeven en verbergen geactiveerd in de component van de kleurkiezer

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

In Update() wordt selectorPosition gebruikt om een straal te werpen op de mesh-collider van het kleurenwiel, die een UV-positie retourneert. Deze positie kan vervolgens worden gebruikt om de pixelcoördinaat en kleurwaarde van het patroon van het kleurenwiel te vinden. Deze waarde is toegankelijk voor andere scripts via de eigenschap SelectedColor .

Raycasting van kleurenkiezerwiel

...
    // 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);
}

Hoofdstuk 4- Controllermodel overschrijven

Doelen

  • Meer informatie over het overschrijven van het controllermodel met een aangepast 3D-model.

MR213_BrushToolOverride

Instructies

  • Klik op MotionControllers in het deelvenster Hiërarchie .
  • Klik op de cirkel aan de rechterkant van het veld Alternatieve rechtercontroller .
  • Typ 'BrushController' en selecteer de prefab in het resultaat. U vindt deze onder Assets/AppPrefabs/BrushController.
  • Schakel het selectievakje Altijd alternatief rechtsmodel gebruiken in

MR213_BrushToolOverrideSlot

De BrushController-prefab hoeft niet te worden opgenomen in het deelvenster Hiërarchie . Als u echter de onderliggende onderdelen wilt uitchecken, gaat u als volgende te werk:

  • Typ in het deelvenster Project de tekst BrushController en sleep BrushController prefab naar het deelvenster Hiërarchie .

MR213_BrushTool_Prefab2

U vindt het onderdeel Tip in BrushController. We gebruiken de transformatie om het tekenen van lijnen te starten/stoppen.

  • Verwijder de BrushController uit het deelvenster Hiërarchie .
  • Sla de scène op en klik op de afspeelknop. U kunt zien dat het borstelmodel de rechterbewegingscontroller heeft vervangen.

Hoofdstuk 5 - Schilderen met invoer selecteren

Doelen

  • Meer informatie over het gebruik van de knop Selecteren-gebeurtenis om een lijntekening te starten en te stoppen

Instructies

  • Zoek in het deelvenster Project naar BrushController-prefab.
  • Dubbelklik in het deelvenster Inspector op BrushController Script om de code in Visual Studio weer te geven

BrushController-script

BrushController abonneert zich op de gebeurtenissen InteractionSourcePressed en InteractionSourceReleased van InteractionManager. Wanneer de gebeurtenis InteractionSourcePressed wordt geactiveerd, wordt de eigenschap Tekenen van het penseel ingesteld op true; wanneer de gebeurtenis InteractionSourceReleased wordt geactiveerd, wordt de eigenschap Draw van het penseel ingesteld op 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;
    }
}

Terwijl Tekenen is ingesteld op true, genereert het penseel punten in een geïnstantieerde Unity LineRenderer. Een verwijzing naar deze prefab wordt bewaard in het veld Stroke Prefab van het penseel.

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;
    }
}

Als u de geselecteerde kleur uit de gebruikersinterface van het kleurenkiezerwiel wilt gebruiken, moet BrushController een verwijzing hebben naar het object ColorPickerWheel . Omdat de BrushController-prefab tijdens runtime wordt geïnstantieerd als een vervangende controller, moeten alle verwijzingen naar objecten in de scène tijdens runtime worden ingesteld. In dit geval gebruiken we GameObject.FindObjectOfType om het ColorPickerWheel te vinden:

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

    // Assign currently selected color to the brush’s material color
    brushRenderer.material.color = colorPicker.SelectedColor;
    ...
}
  • Sla de scène op en klik op de afspeelknop. U kunt de lijnen tekenen en schilderen met behulp van de selectieknop op de rechtercontroller.

Hoofdstuk 6 - Object spawning met invoer selecteren

Doelen

  • Meer informatie over het gebruik van knopinvoerevenementen selecteren en begrijpen
  • Meer informatie over het instantiëren van objecten

Instructies

  • Typ objectspawner in het zoekvak in het deelvenster Project. U kunt deze ook vinden onder Assets/AppPrefabs/

  • Sleep de prefab ObjectSpawner naar het deelvenster Hierarchy .

  • Klik op ObjectSpawner in het deelvenster Hiërarchie .

  • ObjectSpawner heeft een veld met de naam Kleurbron.

  • Sleep vanuit het deelvenster Hierarchy de verwijzing ColorPickerWheel naar dit veld.

    Object Spawner Inspector

  • Klik op de prefab ObjectSpawner in het deelvenster Hiërarchie .

  • Dubbelklik in het deelvenster Inspector op ObjectSpawner Script om de code in Visual Studio weer te geven.

ObjectSpawner-script

De ObjectSpawner instantiëert kopieën van een primitief gaas (kubus, bol, cilinder) in de ruimte. Wanneer een InteractionSourcePressed wordt gedetecteerd, wordt de handheid gecontroleerd en of het een InteractionSourcePressType.Grasp - of InteractionSourcePressType.Select-gebeurtenis is.

Voor een Grasp-gebeurtenis wordt de index van het huidige mesh-type (bol, kubus, cilinder) verhoogd

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;
        }
    }
}

Voor een select-gebeurtenis wordt in SpawnObject() een nieuw object geïnstantieerd, niet-bovenliggend en vrijgegeven in de wereld.

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;
}

De ObjectSpawner gebruikt het ColorPickerWheel om de kleur van het materiaal van het weergaveobject in te stellen. Voortgebrachte objecten krijgen een exemplaar van dit materiaal, zodat ze hun kleur behouden.

  • Sla de scène op en klik op de afspeelknop.

U kunt de objecten wijzigen met de knop Grijpen en objecten spawnen met de knop Selecteren.

App bouwen en implementeren in Mixed Reality Portal

  • Selecteer in Unity Instellingen voor bestandsbuild>.
  • Klik op Open scènes toevoegen om de huidige scène toe te voegen aan scènes in build.
  • Klik op Bouwen.
  • Maak een nieuwe map met de naam 'App'.
  • Klik één klik op de map App .
  • Klik op Map selecteren.
  • Wanneer Unity klaar is, wordt een Bestandenverkenner venster weergegeven.
  • Open de map App .
  • Dubbelklik op YourSceneName.sln Visual Studio Solution-bestand.
  • Gebruik de bovenste werkbalk in Visual Studio om het doel te wijzigen van Foutopsporing in Release en van ARM in X64.
  • Klik op de vervolgkeuzepijl naast de knop Apparaat en selecteer Lokale computer.
  • Klik op Fouten opsporen -> Starten zonder foutopsporing in het menu of druk op Ctrl+F5.

De app is nu gebouwd en geïnstalleerd in Mixed Reality Portal. U kunt het opnieuw starten via het Startmenu in Mixed Reality Portal.

Geavanceerd ontwerp - Hulpmiddelen voor kwasten met radiale indeling

MixedReality213 Main

In dit hoofdstuk leert u hoe u het standaard bewegingscontrollermodel kunt vervangen door een aangepaste verzameling penseelgereedschappen. Ter referentie vindt u de voltooide scène MixedReality213Geavanceerd onder de map Scènes .

Instructies

  • Typ brushSelector in het zoekvak in het deelvenster Project. U kunt deze ook vinden onder Assets/AppPrefabs/

  • Sleep de prefab BrushSelector naar het deelvenster Hierarchy .

  • Maak voor de organisatie een leeg GameObject met de naam Brushes

  • Sleep de volgende prefabs vanuit het deelvenster Project naar Penselen

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

    Kwasten

  • Klik op MotionControllers prefab in het deelvenster Hiërarchie .

  • Schakel in het deelvenster Inspector het selectievakje Altijd alternatief rechtermodel gebruiken in de bewegingscontroller visualiseren uit

  • Klik in het deelvenster Hiërarchie op BrushSelector

  • BrushSelector heeft een veld met de naam ColorPicker

  • Sleep vanuit het deelvenster Hierarchy het ColorPickerWheel naar het veld ColorPicker in het deelvenster Inspector .

    ColorPickerWheel toewijzen aan Brush Selector

  • Selecteer in het deelvenster Hierarchy onder BrushSelector prefab het object Menu .

  • Open in het deelvenster Inspector onder het onderdeel LineObjectCollection de vervolgkeuzelijst Objectenmatrix . U ziet 6 lege sleuven.

  • Sleep vanuit het deelvenster Hierarchy elk van de prefabs die boven elkaar zijn geplaatst onder brushes GameObject in een willekeurige volgorde naar deze sleuven. (Zorg ervoor dat u de prefabs uit de scène sleept, niet de prefabs in de projectmap.)

Kwastkiezer

BrushSelector prefab

Omdat de BrushSelectorAttachToController over neemt, worden de opties Voor hand- en element in het deelvenster Inspector weergegeven. We hebben Rechts en Aanwijzende houding geselecteerd om kwastgereedschappen te bevestigen aan de rechter controller met voorwaartse richting.

De BrushSelector maakt gebruik van twee hulpprogramma's:

  • Ellips: wordt gebruikt voor het genereren van punten in de ruimte langs een ellipsvorm.
  • LineObjectCollection: distribueert objecten met behulp van de punten die worden gegenereerd door een lijnklasse (bijvoorbeeld Ellipse). Dit is wat we gebruiken om onze borstels langs de ellipsvorm te plaatsen.

In combinatie kunnen deze hulpprogramma's worden gebruikt om een radiaal menu te maken.

LineObjectCollection-script

LineObjectCollection bevat besturingselementen voor de grootte, positie en rotatie van objecten die langs de lijn zijn verdeeld. Dit is handig voor het maken van radiale menu's zoals de kwastkiezer. Om het uiterlijk te creëren van kwasten die vanuit het niets omhoog worden geschaald wanneer ze de geselecteerde positie in het midden naderen, piekt de ObjectScale-curve in het midden en loopt af aan de randen.

BrushSelector-script

In het geval van de BrushSelector hebben we ervoor gekozen om procedurele animatie te gebruiken. Eerst worden brush-modellen verdeeld in een ellips door het LineObjectCollection-script . Vervolgens is elk penseel verantwoordelijk voor het handhaven van de positie in de hand van de gebruiker op basis van de DisplayMode-waarde , die wordt gewijzigd op basis van de selectie. We hebben gekozen voor een procedurele benadering omdat de kans groot is dat overgangen van de penseelpositie worden onderbroken wanneer de gebruiker penselen selecteert. Mecanim-animaties kunnen onderbrekingen probleemloos verwerken, maar het is meestal ingewikkelder dan een eenvoudige Lerp-bewerking.

BrushSelector maakt gebruik van een combinatie van beide. Wanneer invoer via de touchpad wordt gedetecteerd, worden de penseelopties zichtbaar en worden ze omhoog geschaald langs het radiale menu. Na een time-outperiode (die aangeeft dat de gebruiker een selectie heeft gemaakt) worden de kwastopties weer omlaag geschaald, zodat alleen het geselecteerde penseel overblijft.

Invoer van touchpad visualiseren

Zelfs in gevallen waarin het controllermodel volledig is vervangen, kan het handig zijn om invoer weer te geven op de oorspronkelijke modelinvoer. Dit helpt om de acties van de gebruiker in werkelijkheid te ondergronden. Voor de BrushSelector hebben we ervoor gekozen om het touchpad kort zichtbaar te maken wanneer de invoer wordt ontvangen. Dit is gedaan door het touchpad-element op te halen uit de controller, het materiaal te vervangen door een aangepast materiaal en vervolgens een kleurovergang toe te passen op de kleur van dat materiaal op basis van de laatste keer dat de touchpadinvoer is ontvangen.

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);
    ...
}

Selectie van penseelgereedschap met touchpad-invoer

Wanneer de penseelkiezer de ingedrukt invoer van de touchpad detecteert, wordt de positie van de invoer gecontroleerd om te bepalen of deze links of rechts was.

Dikte van lijn met selectPressedAmount

In plaats van de gebeurtenis InteractionSourcePressType.Select in de InteractionSourcePressed() kunt u de analoge waarde van de geperste hoeveelheid ophalen via selectPressedAmount. Deze waarde kan worden opgehaald in 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;
            }
        }
    }
}

Gumscript

Gum is een speciaal type penseel dat de functie DrawOverTime() van de basisborstel overschrijft. Terwijl Tekenen waar is, controleert de gum of de punt kruist met bestaande penseelstreken. Als dit het geval is, worden ze toegevoegd aan een wachtrij die moet worden ingekrompen en verwijderd.

Geavanceerd ontwerp - Teleportatie en locomotie

Als u de gebruiker wilt toestaan om door de scène te navigeren met teleportatie met behulp van een duimstick, gebruikt u MixedRealityCameraParent in plaats van MixedRealityCamera. U moet ook InputManager en DefaultCursor toevoegen. Aangezien MixedRealityCameraParent al MotionControllers en Boundary als onderliggende onderdelen bevat, moet u bestaande MotionControllers en environment-prefab verwijderen.

Instructies

  • Verwijder MixedRealityCamera, Environment en MotionControllers in het deelvenster Hierarchy

  • Zoek in het deelvenster Project de volgende prefabs en sleep deze naar het deelvenster Hiërarchie :

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

    bovenliggende camera Mixed Reality

  • Klik in het deelvenster Hiërarchie op Invoerbeheer

  • Schuif in het deelvenster Inspector omlaag naar de sectie Simple Single Pointer Selector

  • Sleep in het deelvenster HiërarchieDefaultCursor naar het veld Cursor

    DefaultCursor toewijzen

  • Sla de scène op en klik op de afspeelknop. U kunt de duimstick gebruiken om naar links/rechts te draaien of te teleporteren.

Het einde

En dat is het einde van deze zelfstudie! U hebt het volgende geleerd:

  • Werken met bewegingscontrollermodellen in de gamemodus en runtime van Unity.
  • Verschillende typen knopevenementen en hun toepassingen gebruiken.
  • UI-elementen over de controller heen leggen of deze volledig aanpassen.

U bent nu klaar om te beginnen met het creëren van uw eigen meeslepende ervaring met bewegingscontrollers!

Voltooide scènes

  • Klik in het deelvenster Project van Unity op de map Scènes .
  • U vindt er twee Unity-scènes MixedReality213 en MixedReality213Geavanceerd.
    • MixedReality213: Voltooide scène met één penseel
    • MixedReality213Geavanceerd: Voltooide scène met meerdere kwasten met voorbeeld van drukhoeveelheid van knop selecteren

Zie ook