Réalité mixte - Entrées - Cours 213 : Contrôleurs de mouvement

Notes

Les tutoriels Mixed Reality Academy ont été conçus pour les appareils HoloLens (1re génération) et les casques immersifs de réalité mixte. Nous estimons qu’il est important de laisser ces tutoriels à la disposition des développeurs qui recherchent encore des conseils pour développer des applications sur ces appareils. Notez que ces tutoriels ne sont pas mis à jour avec les derniers ensembles d’outils ou interactions utilisés pour HoloLens 2. Ils sont fournis dans le but de fonctionner sur les appareils pris en charge. Une nouvelle série de tutoriels a été publiée pour HoloLens 2.

Les contrôleurs de mouvement dans le monde de la réalité mixte ajoutent un autre niveau d’interactivité. Avec les contrôleurs de mouvement, nous pouvons interagir directement avec des objets d’une manière plus naturelle, comme nos interactions physiques dans la vie réelle, ce qui augmente l’immersion et le plaisir de votre expérience d’application.

Dans MR Input 213, nous allons explorer les événements d’entrée du contrôleur de mouvement en créant une expérience de peinture spatiale simple. Avec cette application, les utilisateurs peuvent peindre dans un espace en trois dimensions avec différents types de pinceaux et de couleurs.

Rubriques abordées dans ce tutoriel

MixedReality213 Topic1 MixedReality213 Topic2 MixedReality213 Topic3
Visualisation du contrôleur Événements d’entrée du contrôleur Contrôleur et interface utilisateur personnalisés
Découvrez comment restituer des modèles de contrôleur de mouvement dans le mode de jeu et l’exécution d’Unity. Comprendre les différents types d’événements de bouton et leurs applications. Découvrez comment superposer des éléments d’interface utilisateur sur le contrôleur ou le personnaliser entièrement.

Prise en charge des appareils

Cours HoloLens Casques immersifs
Réalité mixte - Entrées - Cours 213 : Contrôleurs de mouvement ✔️

Avant de commencer

Prérequis

Consultez la liste de contrôle d’installation pour les casques immersifs sur cette page.

Fichiers projet

Notes

Si vous souhaitez parcourir le code source avant de le télécharger, il est disponible sur GitHub.

Configuration d’Unity

Objectifs

  • Optimiser Unity pour le développement Windows Mixed Reality
  • Configurer Mixed Reality caméra
  • Configurez l’environnement.

Instructions

  • Démarrez Unity.

  • Sélectionnez Ouvrir.

  • Accédez à votre bureau et recherchez le dossier MixedReality213-master que vous avez précédemment désarchivé.

  • Cliquez sur Sélectionner un dossier.

  • Une fois que Unity a terminé le chargement des fichiers projet, vous pouvez voir l’éditeur Unity.

  • Dans Unity, sélectionnez Paramètres de build de fichier>.

    MR213_BuildSettings

  • Sélectionnez plateforme Windows universelle dans la liste Plateforme, puis cliquez sur le bouton Changer de plateforme.

  • Définir l’appareil cible sur N’importe quel appareil

  • Définissez Build Type sur D3D.

  • Définissez le KIT de développement logiciel (SDK) sur Dernier installé

  • Vérifier les projets Unity C#

    • Cela vous permet de modifier des fichiers de script dans le projet Visual Studio sans regénérer le projet Unity.
  • Cliquez sur Paramètres du lecteur.

  • Dans le panneau Inspecteur , faites défiler vers le bas

  • Dans les paramètres XR, case activée réalité virtuelle prise en charge

  • Sous Kits de développement logiciel (SDK) de réalité virtuelle, sélectionnez Windows Mixed Reality

    MR213_XRSettings

  • Fermez la fenêtre Paramètres de build .

Structure du projet

Ce tutoriel utilise Mixed Reality Toolkit - Unity. Vous trouverez les versions sur cette page.

ProjectStructure

Scènes terminées pour votre référence

  • Vous trouverez deux scènes Unity terminées sous le dossier Scènes .
    • MixedReality213 : scène terminée avec un seul pinceau
    • MixedReality213Advanced : Scène terminée pour la conception avancée avec plusieurs pinceaux

Nouvelle configuration de scène pour le tutoriel

  • Dans Unity, cliquez sur Fichier > nouvelle scène

  • Supprimer la caméra principale et la lumière directionnelle

  • Dans le panneau Projet, recherchez et faites glisser les préfabriqués suivants dans le panneau Hiérarchie :

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

    Caméra et environnement

  • Il existe deux préfabriqués de caméra dans Mixed Reality Toolkit :

    • MixedRealityCamera.prefab : Caméra uniquement
    • MixedRealityCameraParent.prefab : Caméra + Téléportation + Limite
    • Dans ce tutoriel, nous allons utiliser MixedRealityCamera sans fonctionnalité de téléportation. Pour cette raison, nous avons ajouté un préfabriqué environnement simple qui contient un plancher de base pour que l’utilisateur se sente à la terre.
    • Pour en savoir plus sur la téléportation avec MixedRealityCameraParent, consultez Conception avancée - Téléportation et locomotion

Configuration de Skybox

  • Cliquez sur Paramètres d’éclairage de > la fenêtre >

  • Cliquez sur le cercle situé à droite du champ Skybox Material

  • Tapez « gray » et sélectionnez SkyboxGray (Assets/AppPrefabs/Support/Materials/SkyboxGray.mat)

    Définition de skybox

  • Cochez l’option Skybox pour voir la skybox de dégradé gris affectée

    Option Basculez skybox

  • La scène avec MixedRealityCamera, Environnement et skybox gris ressemblera à ceci.

    MixedReality213 Environment

  • Cliquez sur Fichier > Enregistrer la scène en tant que

  • Enregistrez votre scène sous le dossier Scènes avec n’importe quel nom

Chapitre 1 - Visualisation du contrôleur

Objectifs

  • Découvrez comment restituer des modèles de contrôleur de mouvement en mode de jeu unity et au moment de l’exécution.

Windows Mixed Reality fournit un modèle de contrôleur animé pour la visualisation du contrôleur. Vous pouvez adopter plusieurs approches pour la visualisation du contrôleur dans votre application :

  • Par défaut : utilisation du contrôleur par défaut sans modification
  • Hybride : utilisation du contrôleur par défaut, mais personnalisation de certains de ses éléments ou superposition de composants d’interface utilisateur
  • Remplacement : utilisation de votre propre modèle 3D personnalisé pour le contrôleur

Dans ce chapitre, nous allons découvrir les exemples de ces personnalisations de contrôleur.

Instructions

  • Dans le panneau Projet , tapez MotionControllers dans la zone de recherche . Vous pouvez également le trouver sous Assets/HoloToolkit/Input/Prefabs/.
  • Faites glisser le préfabriqué MotionControllers dans le panneau Hiérarchie .
  • Cliquez sur le préfabriqué MotionControllers dans le panneau Hiérarchie .

Préfabriqué MotionControllers

Le préfabriqué MotionControllers a un script MotionControllerVisualizer qui fournit les emplacements pour d’autres modèles de contrôleur. Si vous affectez vos propres modèles 3D personnalisés tels qu’une main ou une épée et case activée ' Toujours utiliser un autre modèle gauche/droit', vous les verrez au lieu du modèle par défaut. Nous allons utiliser cet emplacement dans le chapitre 4 pour remplacer le modèle de contrôleur par un pinceau.

MR213_ControllerVisualizer

Instructions

  • Dans le panneau Inspecteur , double-cliquez sur Script MotionControllerVisualizer pour voir le code dans Visual Studio

Script MotionControllerVisualizer

Les classes MotionControllerVisualizer et MotionControllerInfo permettent d’accéder aux & de modifier les modèles de contrôleur par défaut. MotionControllerVisualizer s’abonne à l’événement InteractionSourceDetected de Unity et instancie automatiquement les modèles de contrôleur lorsqu’ils sont trouvés.

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

Les modèles de contrôleur sont fournis conformément à la spécification glTF. Ce format a été créé pour fournir un format commun, tout en améliorant le processus de transmission et de décompression des ressources 3D. Dans ce cas, nous devons récupérer et charger les modèles de contrôleur au moment de l’exécution, car nous voulons rendre l’expérience de l’utilisateur aussi fluide que possible, et il n’est pas garanti quelle version des contrôleurs de mouvement l’utilisateur peut utiliser. Ce cours, via le Mixed Reality Toolkit, utilise une version du projet UnityGLTF du groupe Khronos.

Une fois le contrôleur remis, les scripts peuvent utiliser MotionControllerInfo pour rechercher les transformations d’éléments de contrôleur spécifiques afin qu’ils puissent se positionner correctement.

Dans un chapitre ultérieur, nous allons apprendre à utiliser ces scripts pour attacher des éléments d’interface utilisateur aux contrôleurs.

Dans certains scripts, vous trouverez des blocs de code avec #if ! UNITY_EDITOR ou UNITY_WSA. Ces blocs de code s’exécutent uniquement sur le runtime UWP lorsque vous déployez sur Windows. Cela est dû au fait que l’ensemble des API utilisées par l’éditeur Unity et le runtime d’application UWP sont différents.

  • Enregistrez la scène et cliquez sur le bouton lecture .

Vous pourrez voir la scène avec des contrôleurs de mouvement dans votre casque. Vous pouvez voir des animations détaillées pour les clics de bouton, le mouvement du bâton et la mise en surbrillance tactile du pavé tactile.

MR213_Controller visualisation par défaut

Chapitre 2 - Attachement d’éléments d’interface utilisateur au contrôleur

Objectifs

  • En savoir plus sur les éléments des contrôleurs de mouvement
  • Découvrez comment attacher des objets à des parties spécifiques des contrôleurs

Dans ce chapitre, vous allez apprendre à ajouter des éléments d’interface utilisateur au contrôleur auquel l’utilisateur peut facilement accéder et manipuler à tout moment. Vous allez également apprendre à ajouter une interface utilisateur de sélecteur de couleurs simple à l’aide de l’entrée du pavé tactile.

Instructions

  • Dans le panneau Projet , recherchez le script MotionControllerInfo .
  • Dans le résultat de la recherche, double-cliquez sur script MotionControllerInfo pour voir le code dans Visual Studio.

Script MotionControllerInfo

La première étape consiste à choisir l’élément du contrôleur auquel l’interface utilisateur doit être attachée. Ces éléments sont définis dans ControllerElementEnum dans MotionControllerInfo.cs.

MR213 MotionControllerElements

  • Accueil
  • Menu
  • Saisir
  • Bâton de pouce
  • Select
  • Pavé tactile
  • Pose de pointage : cet élément représente l’extrémité du contrôleur pointant vers l’avant.

Instructions

  • Dans le panneau Projet , recherchez le script AttachToController .
  • Dans le résultat de la recherche, double-cliquez sur le script AttachToController pour voir le code dans Visual Studio.

Script AttachToController

Le script AttachToController fournit un moyen simple d’attacher des objets à un élément et une remise de contrôleur spécifiés.

Dans AttachElementToController(),

  • Vérifier la remise à l’aide de MotionControllerInfo.Handedness
  • Obtenir un élément spécifique du contrôleur à l’aide de MotionControllerInfo.TryGetElement()
  • Après avoir récupéré la transformation de l’élément à partir du modèle de contrôleur, parentez l’objet sous celui-ci et définissez la position locale de l’objet & rotation sur zéro.
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;
     }
}

Le moyen le plus simple d’utiliser le script AttachToController consiste à en hériter, comme nous l’avons fait dans le cas de ColorPickerWheel. Remplacez simplement les fonctions OnAttachToController et OnDetachFromController pour effectuer votre configuration/panne lorsque le contrôleur est détecté/déconnecté.

Instructions

  • Dans le panneau Projet , tapez dans la zone de recherche ColorPickerWheel. Vous pouvez également le trouver sous Ressources/AppPrefabs/.
  • Faites glisser le préfabriqué ColorPickerWheel dans le panneau Hiérarchie .
  • Cliquez sur le préfabriqué ColorPickerWheel dans le panneau Hiérarchie .
  • Dans le panneau Inspecteur , double-cliquez sur ColorPickerWheel Script pour afficher le code dans Visual Studio.

Préfabriqué ColorPickerWheel

Script ColorPickerWheel

Étant donné que ColorPickerWheel hérite de AttachToController, il affiche Handedness et Element dans le panneau Inspector . Nous allons attacher l’interface utilisateur à l’élément Touchpad sur le contrôleur gauche.

Script ColorPickerWheel

ColorPickerWheel remplace OnAttachToController et OnDetachFromController pour s’abonner à l’événement d’entrée qui sera utilisé dans le chapitre suivant pour la sélection des couleurs avec l’entrée du pavé tactile.

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;
    }
    ...
}
  • Enregistrez la scène et cliquez sur le bouton lecture .

Autre méthode pour attacher des objets aux contrôleurs

Nous vous recommandons d’hériter de AttachToController et de remplacer OnAttachToController. Toutefois, cela n’est peut-être pas toujours possible. Une alternative consiste à l’utiliser en tant que composant autonome. Cela peut être utile lorsque vous souhaitez attacher un préfabriqué existant à un contrôleur sans refactoriser vos scripts. Il vous suffit de demander à votre classe d’attendre que IsAttached soit défini sur true avant d’effectuer une configuration. La méthode la plus simple consiste à utiliser une coroutine pour « Démarrer ».

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

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

    // Perform setup here
}

Chapitre 3 - Utilisation de l’entrée du pavé tactile

Objectifs

  • Découvrez comment obtenir des événements de données d’entrée du pavé tactile
  • Découvrez comment utiliser les informations de position de l’axe du pavé tactile pour votre expérience d’application

Instructions

  • Dans le panneau Hiérarchie , cliquez sur ColorPickerWheel
  • Dans le panneau Inspecteur , sous Animator, double-cliquez sur ColorPickerWheelController
  • Vous pourrez voir l’onglet Animator ouvert

Affichage/masquage de l’interface utilisateur avec le contrôleur d’animation d’Unity

Pour afficher et masquer l’interface utilisateur ColorPickerWheel avec l’animation, nous utilisons le système d’animation d’Unity. Définition de la propriété Visible de ColorPickerWheel sur true ou false déclencheurs Afficher et Masquer les déclencheurs d’animation. Les paramètres Show et Hide sont définis dans le contrôleur d’animation ColorPickerWheelController .

Unity Animation Controller

Instructions

  • Dans le panneau Hiérarchie, sélectionnez Préfab ColorPickerWheel
  • Dans le panneau Inspecteur , double-cliquez sur Le script ColorPickerWheel pour afficher le code dans Visual Studio

Script ColorPickerWheel

ColorPickerWheel s’abonne à l’événement InteractionSourceUpdated de Unity pour écouter les événements du pavé tactile.

Dans InteractionSourceUpdated(), le script vérifie d’abord qu’il :

  • est en fait un événement de pavé tactile (obj.state.pavé tactileTouched)
  • provient du contrôleur gauche (obj.state.source.remise)

Si les deux sont true, la position du pavé tactile (obj.state.touchpadPosition) est affecté à selectorPosition.

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

Dans Update(), en fonction de la propriété visible , il déclenche les déclencheurs d’animation Afficher et Masquer dans le composant d’animation du sélecteur de couleurs

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

Dans Update(), selectorPosition est utilisé pour projeter un rayon au niveau de l’collisionneur de maillage de la roue de couleur, qui retourne une position UV. Cette position peut ensuite être utilisée pour rechercher la coordonnée de pixel et la valeur de couleur de la texture de la roue de couleur. Cette valeur est accessible à d’autres scripts via la propriété SelectedColor .

Color Picker Wheel Raycasting

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

Chapitre 4 - Remplacement du modèle de contrôleur

Objectifs

  • Découvrez comment remplacer le modèle de contrôleur par un modèle 3D personnalisé.

MR213_BrushToolOverride

Instructions

  • Cliquez sur MotionControllers dans le panneau Hiérarchie .
  • Cliquez sur le cercle situé à droite du champ Contrôleur de droite de remplacement .
  • Tapez « BrushController » et sélectionnez le préfabriqué dans le résultat. Vous pouvez le trouver sous Ressources/AppPrefabs/BrushController.
  • Vérifier toujours utiliser un autre modèle droit

MR213_BrushToolOverrideSlot

Le préfabriqué BrushController n’a pas besoin d’être inclus dans le panneau Hiérarchie . Toutefois, pour case activée ses composants enfants :

  • Dans le panneau Projet , tapez BrushController et faites glisser le préfabriqué BrushController dans le panneau Hiérarchie .

MR213_BrushTool_Prefab2

Vous trouverez le composant Tip dans BrushController. Nous allons utiliser sa transformation pour démarrer/arrêter le dessin des lignes.

  • Supprimez le BrushController du panneau Hiérarchie .
  • Enregistrez la scène et cliquez sur le bouton lecture . Vous pourrez voir le modèle de pinceau remplacer le contrôleur de mouvement de droite.

Chapitre 5 - Peinture avec l’entrée Select

Objectifs

  • Découvrez comment utiliser l’événement Sélectionner un bouton pour démarrer et arrêter un dessin de trait

Instructions

  • Recherchez le préfabriqué BrushController dans le panneau Projet .
  • Dans le panneau Inspecteur , double-cliquez sur Script BrushController pour afficher le code dans Visual Studio

Script BrushController

BrushController s’abonne aux événements InteractionSourcePressed et InteractionSourceReleased d’InteractionManager. Lorsque l’événement InteractionSourcePressed est déclenché, la propriété Draw du pinceau a la valeur true ; lorsque l’événement InteractionSourceReleased est déclenché, la propriété Draw du pinceau a la valeur 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;
    }
}

Alors que Draw a la valeur true, le pinceau génère des points dans un Unity LineRenderer instancié. Une référence à ce préfabriqué est conservée dans le champ de la brosse à préfab trait .

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

Pour utiliser la couleur actuellement sélectionnée à partir de l’interface utilisateur de la roulette du sélecteur de couleurs, BrushController doit avoir une référence à l’objet ColorPickerWheel . Étant donné que le préfabriqué BrushController est instancié au moment de l’exécution en tant que contrôleur de remplacement, toutes les références aux objets de la scène doivent être définies au moment de l’exécution. Dans ce cas, nous utilisons GameObject.FindObjectOfType pour localiser le 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;
    ...
}
  • Enregistrez la scène et cliquez sur le bouton lecture . Vous pourrez dessiner les lignes et peindre à l’aide du bouton sélectionner sur le contrôleur de droite.

Chapitre 6 - Génération d’objets avec l’entrée Select

Objectifs

  • Découvrez comment utiliser les événements d’entrée de bouton Select et Grasp
  • Découvrez comment instancier des objets

Instructions

  • Dans le panneau Projet , tapez ObjectSpawner dans la zone de recherche. Vous pouvez également le trouver sous Ressources/AppPrefabs/

  • Faites glisser le préfabriqué ObjectSpawner dans le panneau Hiérarchie .

  • Cliquez sur ObjectSpawner dans le panneau Hiérarchie .

  • ObjectSpawner a un champ nommé Source de couleur.

  • Dans le panneau Hiérarchie , faites glisser la référence ColorPickerWheel dans ce champ.

    Inspecteur du frayeur d’objets

  • Cliquez sur le préfabriqué ObjectSpawner dans le panneau Hiérarchie .

  • Dans le panneau Inspecteur , double-cliquez sur ObjectSpawner Script pour afficher le code dans Visual Studio.

Script ObjectSpawner

ObjectSpawner instancie des copies d’un maillage primitif (cube, sphère, cylindre) dans l’espace. Lorsqu’un InteractionSourcePressed est détecté, il vérifie la remise et s’il s’agit d’un événement InteractionSourcePressType.Grasp ou InteractionSourcePressType.Select .

Pour un événement Grasp , il incrémente l’index du type de maillage actuel (sphère, cube, cylindre)

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

Pour un événement Select , dans SpawnObject(), un nouvel objet est instancié, non parenté et libéré dans le monde entier.

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

ObjectSpawner utilise le ColorPickerWheel pour définir la couleur du matériau de l’objet d’affichage. Les objets générés reçoivent une instance de ce matériau afin qu’ils conservent leur couleur.

  • Enregistrez la scène et cliquez sur le bouton lecture .

Vous pourrez modifier les objets avec le bouton Saisir et générer des objets avec le bouton Sélectionner.

Créer et déployer une application sur Mixed Reality Portail

  • Dans Unity, sélectionnez Paramètres de build de fichier>.
  • Cliquez sur Ajouter des scènes ouvertes pour ajouter la scène actuelle aux scènes dans la build.
  • Cliquez sur Générer.
  • Créez un dossier nommé « App ».
  • Cliquez sur le dossier Application .
  • Cliquez sur Sélectionner un dossier.
  • Une fois Unity terminé, une fenêtre Explorateur de fichiers s’affiche.
  • Ouvrez le dossier Application .
  • Double-cliquez sur YourSceneName.sln Fichier solution Visual Studio.
  • À l’aide de la barre d’outils supérieure de Visual Studio, remplacez la cible de Déboguer par Release et d’ARM en X64.
  • Cliquez sur la flèche déroulante en regard du bouton Appareil, puis sélectionnez Ordinateur local.
  • Cliquez sur Déboguer -> Démarrer sans débogage dans le menu ou appuyez sur Ctrl + F5.

À présent, l’application est générée et installée dans Mixed Reality portail. Vous pouvez le lancer à nouveau via le menu Démarrer dans Mixed Reality portail.

Conception avancée - Outils de pinceau avec disposition radiale

MixedReality213 Main

Dans ce chapitre, vous allez apprendre à remplacer le modèle de contrôleur de mouvement par défaut par une collection d’outils de pinceau personnalisé. Pour votre référence, vous trouverez la scène MixedReality213Advanced terminée sous le dossier Scènes .

Instructions

  • Dans le panneau Projet , tapez BrushSelector dans la zone de recherche . Vous pouvez également le trouver sous Ressources/AppPrefabs/

  • Faites glisser le préfabriqué BrushSelector dans le panneau Hiérarchie .

  • Pour organization, créez un GameObject vide appelé Pinceaux

  • Faites glisser les préfabriqués suivants à partir du panneau Projet vers Pinceaux

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

    Pinceaux

  • Cliquez sur Préfabriqué MotionControllers dans le panneau Hiérarchie .

  • Dans le panneau Inspecteur, décochez Toujours utiliser un autre modèle droit sur le visualiseur du contrôleur de mouvement.

  • Dans le panneau Hiérarchie , cliquez sur BrushSelector

  • BrushSelector a un champ nommé ColorPicker

  • Dans le panneau Hiérarchie , faites glisser le ColorPickerWheel dans le champ ColorPicker dans le panneau Inspecteur .

    Affecter ColorPickerWheel au sélecteur de pinceau

  • Dans le panneau Hiérarchie , sous Le préfabriqué BrushSelector , sélectionnez l’objet Menu .

  • Dans le panneau Inspecteur , sous le composant LineObjectCollection , ouvrez la liste déroulante Tableau d’objets . Vous verrez 6 emplacements vides.

  • À partir du panneau Hiérarchie , faites glisser chacun des préfabriqués parentés sous pinceaux GameObject dans ces emplacements dans n’importe quel ordre. (Assurez-vous que vous faites glisser les préfabriqués de la scène, et non les préfabriqués dans le dossier du projet.)

Sélecteur de pinceau

Préfabriqué BrushSelector

Étant donné que BrushSelector hérite d’AttachToController, il affiche les options Handedness et Element dans le panneau Inspector . Nous avons sélectionné Pose droite et pointage pour attacher les outils de pinceau au contrôleur de la main droite avec direction vers l’avant.

BrushSelector utilise deux utilitaires :

  • Ellipse : utilisée pour générer des points dans l’espace le long d’une forme d’ellipse.
  • LineObjectCollection : distribue les objets à l’aide des points générés par n’importe quelle classe Line (par exemple, Ellipse). C’est ce que nous allons utiliser pour placer nos pinceaux le long de la forme Ellipse.

Lorsqu’ils sont combinés, ces utilitaires peuvent être utilisés pour créer un menu radial.

Script LineObjectCollection

LineObjectCollection a des contrôles pour la taille, la position et la rotation des objets distribués le long de sa ligne. Cela est utile pour créer des menus radial comme le sélecteur de pinceau. Pour créer l’apparence de pinceaux qui montent à l’échelle à partir de rien à mesure qu’ils s’approchent de la position centrale sélectionnée, la courbe ObjectScale pointe au centre et se réduit aux bords.

Script BrushSelector

Dans le cas de BrushSelector, nous avons choisi d’utiliser l’animation procédurale. Tout d’abord, les modèles de pinceau sont distribués dans une ellipse par le script LineObjectCollection . Ensuite, chaque pinceau est responsable du maintien de sa position dans la main de l’utilisateur en fonction de sa valeur DisplayMode , qui change en fonction de la sélection. Nous avons choisi une approche procédurale en raison de la probabilité élevée d’interruption des transitions de position de pinceau à mesure que l’utilisateur sélectionne les pinceaux. Les animations Mecanim peuvent gérer les interruptions correctement, mais elles ont tendance à être plus compliquées qu’une simple opération Lerp.

BrushSelector utilise une combinaison des deux. Lorsque l’entrée du pavé tactile est détectée, les options de pinceau deviennent visibles et montent en puissance le long du menu radial. Après un délai d’expiration (qui indique que l’utilisateur a effectué une sélection), les options de pinceau redescendent, ne laissant que le pinceau sélectionné.

Visualisation de l’entrée du pavé tactile

Même dans les cas où le modèle de contrôleur a été entièrement remplacé, il peut être utile d’afficher l’entrée sur les entrées du modèle d’origine. Cela permet de baser les actions de l’utilisateur dans la réalité. Pour le BrushSelector , nous avons choisi de rendre le pavé tactile brièvement visible lorsque l’entrée est reçue. Pour ce faire, récupérez l’élément Touchpad à partir du contrôleur, remplacez son matériau par un matériau personnalisé, puis appliquez un dégradé à la couleur de ce matériau en fonction de la dernière fois que l’entrée du pavé tactile a été reçue.

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

Sélection de l’outil Pinceau avec entrée pavé tactile

Lorsque le sélecteur de pinceau détecte l’entrée enfoncée du pavé tactile, il vérifie la position de l’entrée pour déterminer si elle se trouvait à gauche ou à droite.

Épaisseur de trait avec selectPressedAmount

Au lieu de l’événement InteractionSourcePressType.Select dans InteractionSourcePressed(), vous pouvez obtenir la valeur analogique du montant pressé via selectPressedAmount. Cette valeur peut être récupérée dans 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;
            }
        }
    }
}

Script de gomme

Eraser est un type spécial de pinceau qui remplace la fonction DrawOverTime() du pinceau de base. Bien que Dessin soit vrai, la gomme vérifie si sa pointe croise les traits de pinceau existants. Si c’est le cas, elles sont ajoutées à une file d’attente pour être réduites et supprimées.

Conception avancée - Téléportation et locomotion

Si vous souhaitez autoriser l’utilisateur à se déplacer dans la scène avec la téléportation à l’aide d’un bâton, utilisez MixedRealityCameraParent au lieu de MixedRealityCamera. Vous devez également ajouter InputManager et DefaultCursor. Étant donné que MixedRealityCameraParent inclut déjà MotionControllers et Boundary en tant que composants enfants, vous devez supprimer les préfabriqués MotionController et Environnement existants.

Instructions

  • Dans le panneau Hiérarchie , supprimez MixedRealityCamera, Environment et MotionControllers

  • Dans le panneau Projet, recherchez et faites glisser les préfabriqués suivants dans le panneau Hiérarchie :

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

    Mixed Reality Camera Parent

  • Dans le panneau Hiérarchie , cliquez sur Gestionnaire d’entrées

  • Dans le panneau Inspecteur, faites défiler jusqu’à la section Sélecteur de pointeur unique simple

  • Dans le panneau Hiérarchie, faites glisser DefaultCursor dans le champ Curseur

    Affectation de DefaultCursor

  • Enregistrez la scène et cliquez sur le bouton lecture . Vous serez en mesure d’utiliser le bâton pour faire pivoter gauche/droite ou téléporter.

La fin

Et c’est la fin de ce tutoriel ! Vous avez appris :

  • Comment utiliser des modèles de contrôleur de mouvement dans le mode de jeu et l’exécution d’Unity.
  • Comment utiliser différents types d’événements de bouton et leurs applications.
  • Comment superposer des éléments d’interface utilisateur sur le contrôleur ou le personnaliser entièrement.

Vous êtes maintenant prêt à commencer à créer votre propre expérience immersive avec les contrôleurs de mouvement !

Scènes terminées

  • Dans le panneau Projet d’Unity, cliquez sur le dossier Scènes .
  • Vous trouverez deux scènes Unity MixedReality213 et MixedReality213Advanced.
    • MixedReality213 : scène terminée avec un seul pinceau
    • MixedReality213Advanced : Scène terminée avec plusieurs pinceaux avec l’exemple de quantité d’appui du bouton de sélection

Voir aussi