Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les solveurs sont des composants qui facilitent le calcul de la position & de l’orientation d’un objet en fonction d’un algorithme prédéfini. Un exemple peut être le placement d’un objet sur la surface que le raycast du regard de l’utilisateur atteint actuellement.
En outre, le système solveur définit de façon déterministe un ordre des opérations pour ces calculs de transformation, car il n’existe aucun moyen fiable de spécifier à Unity l’ordre de mise à jour des composants.
Les solveurs offrent une gamme de comportements pour attacher des objets à d’autres objets ou systèmes. Un autre exemple est un objet tag-along qui pointe devant l’utilisateur (en fonction de la caméra). Un solveur peut également être attaché à un contrôleur et un objet pour que l’objet soit le long du contrôleur. Tous les résolveurs peuvent être empilés en toute sécurité, par exemple un comportement tag-along + magnétisme de surface + momentum.
Utilisation d’un solveur
Le système solveur se compose de trois catégories de scripts :
-
Solver: classe abstraite de base dont dérivent tous les résolveurs. Il fournit le suivi de l’état, les paramètres de lissage et l’implémentation, l’intégration automatique du système du solveur et l’ordre de mise à jour. -
SolverHandler: définit l’objet de référence sur lequel effectuer le suivi (par exemple, la transformation principale de la caméra, le rayon de la main, etc.), gère la collecte des composants du solveur et exécute leur mise à jour dans l’ordre approprié.
La troisième catégorie est le solveur lui-même. Les solveurs suivants fournissent les blocs de construction pour le comportement de base :
-
Orbital: verrouille à une position spécifiée et un décalage par rapport à l’objet référencé. -
ConstantViewSize: met à l’échelle pour conserver une taille constante par rapport à la vue de l’objet référencé. -
RadialView: conserve l’objet dans un cône d’affichage par l’objet référencé. -
Follow: conserve l’objet dans un ensemble de limites définies par l’utilisateur de l’objet référencé. -
InBetween: conserve un objet entre deux objets suivis. -
SurfaceMagnetism: projette les rayons sur les surfaces du monde et aligne l’objet sur cette surface. -
DirectionalIndicator: détermine la position et l’orientation d’un objet en tant qu’indicateur directionnel. À partir du point de référence de la cible tracked SolverHandler, cet indicateur s’oriente vers la cible DirectionalTarget fournie. -
Momentum: applique l’accélération/vitesse/frottement pour simuler l’élan et la springiness d’un objet déplacé par d’autres solveurs/composants. -
HandConstraint: contraint l’objet à suivre les mains dans une région qui ne croise pas le GameObject avec les mains. Utile pour le contenu interactif à contrainte manuelle, tel que les menus, etc. Ce solveur est destiné à fonctionner avec IMixedRealityHand , mais fonctionne également avec IMixedRealityController. -
HandConstraintPalmUp: dérive de HandConstraint, mais inclut une logique pour tester si la paume est face à l’utilisateur avant l’activation. Ce solveur fonctionne uniquement avec les contrôleurs IMixedRealityHand , avec d’autres types de contrôleurs, ce solveur se comporte comme sa classe de base.
Pour utiliser le système solveur, ajoutez simplement l’un des composants répertoriés ci-dessus à un GameObject. Étant donné que tous les solveurs ont besoin d’un SolverHandler, un sera créé automatiquement par Unity.
Remarque
Vous trouverez des exemples d’utilisation du système solveurs dans le fichier SolverExamples.scene .
Guide pratique pour modifier les informations de référence sur le suivi
La propriété Type de cible suivi du SolverHandler composant définit le point de référence que tous les résolveurs utiliseront pour calculer leurs algorithmes. Par exemple, un type valeur avec Head un composant simple SurfaceMagnetism entraîne un raycast à partir de la tête et dans la direction du regard de l’utilisateur pour résoudre la surface atteinte. Les valeurs potentielles de la TrackedTargetType propriété sont les suivantes :
- Head : le point de référence est la transformation de la caméra principale
-
ControllerRay : le point de référence est la
LinePointertransformation sur un contrôleur (c’est-à-dire l’origine du pointeur sur un contrôleur de mouvement ou un contrôleur de main) pointant dans la direction du rayon de ligne- Utilisez la
TrackedHandednesspropriété pour sélectionner la préférence de remise (c’est-à-dire Gauche, Droite, Deux)
- Utilisez la
-
HandJoint : le point de référence est la transformation d’une articulation spécifique de la main
- Utilisez la
TrackedHandednesspropriété pour sélectionner la préférence de remise (c’est-à-dire Gauche, Droite, Deux) - Utilisez la
TrackedHandJointpropriété pour déterminer la transformation conjointe à utiliser
- Utilisez la
-
CustomOverride : point de référence à partir du affecté
TransformOverride
Remarque
Pour les types ControllerRay et HandJoint , le gestionnaire du solveur tente de fournir d’abord la transformation de contrôleur/main gauche, puis la droite si le premier n’est pas disponible ou sauf indication contraire de la TrackedHandedness propriété.
Exemple de différentes propriétés associées à chaque TrackedTargetType
Importante
La plupart des résolveurs utilisent le vecteur avant de la cible de transformation suivie fournie par le SolverHandler. Lors de l’utilisation d’un type cible suivi hand joint , le vecteur avant de l’articulation de la paume peut pointer à travers les doigts et non dans la paume. Cela dépend de la plateforme qui fournit les données du joint de main. Pour la simulation d’entrée et la Windows Mixed Reality, il s’agit du vecteur haut qui pointe vers le haut à travers la paume (c’est-à-dire que le vecteur vert est vers le haut, le vecteur bleu est vers l’avant).
Pour surmonter ce problème, mettez à jour la propriété Rotation supplémentaire sur le SolverHandler sur <90, 0, 0>. Cela permet de s’assurer que le vecteur avant fourni aux résolveurs pointe à travers la paume et à l’extérieur de la main.
Vous pouvez également utiliser le type de cible suivi par rayon de contrôleur pour obtenir un comportement similaire pour pointer avec les mains.
Guide pratique pour chaîner des résolveurs
Il est possible d’ajouter plusieurs Solver composants au même GameObject, chaînant ainsi leurs algorithmes. Les SolverHandler composants gèrent la mise à jour de tous les résolveurs sur le même GameObject. Par défaut, les SolverHandler appels GetComponents<Solver>() sur l’écran de démarrage qui retournent les solveurs dans l’ordre dans lequel ils apparaissent dans l’inspecteur.
En outre, la définition de la propriété Transformation liée mise à jour sur true indique que Solver pour enregistrer sa position calculée, son orientation & échelle dans une variable intermédiaire accessible par tous les solveurs (c’est-à-dire GoalPosition). Si la valeur est false, met Solver directement à jour la transformation du GameObject. En enregistrant les propriétés de transformation dans un emplacement intermédiaire, d’autres solveurs sont en mesure d’effectuer leurs calculs à partir de la variable intermédiaire. Cela est dû au fait que Unity n’autorise pas les mises à jour de gameObject.transform à s’empiler dans le même frame.
Remarque
Les développeurs peuvent modifier l’ordre d’exécution des solveurs en définissant directement la SolverHandler.Solvers propriété .
Comment créer un résolveur
Tous les résolveurs doivent hériter de la classe de base abstraite, Solver. Les principales exigences d’une extension solveur impliquent la substitution de la SolverUpdate méthode . Dans cette méthode, les développeurs doivent mettre à jour les propriétés héritées GoalPosition, GoalRotation et GoalScale avec les valeurs souhaitées. En outre, il est généralement utile de tirer parti SolverHandler.TransformTarget comme cadre de référence souhaité par le consommateur.
Le code fourni ci-dessous donne un exemple de nouveau composant solveur appelé InFront qui place l’objet attaché 2 m devant le SolverHandler.TransformTarget. Si est SolverHandler.TrackedTargetType défini par le consommateur sur Head, le SolverHandler.TransformTarget sera la transformation de caméra et, par conséquent, ce solveur placera le GameObject 2m attaché devant le regard des utilisateurs à chaque image.
/// <summary>
/// InFront solver positions an object 2m in front of the tracked transform target
/// </summary>
public class InFront : Solver
{
...
public override void SolverUpdate()
{
if (SolverHandler != null && SolverHandler.TransformTarget != null)
{
var target = SolverHandler.TransformTarget;
GoalPosition = target.position + target.forward * 2.0f;
}
}
}
Guides d’implémentation du solveur
Propriétés courantes du solveur
Chaque composant solveur a un jeu de cœurs de propriétés identiques qui contrôlent le comportement du solveur principal.
Si le lissage est activé, le solveur met progressivement à jour la transformation du GameObject au fil du temps vers les valeurs calculées. La vitesse de cette modification est déterminée par la propriété LerpTime de chaque composant de transformation. Par exemple, une valeur MoveLerpTime plus élevée entraîne des incréments plus lents dans le mouvement entre les images.
Si MaintainScale est activé, le solveur utilise l’échelle locale par défaut du GameObject.
Propriétés courantes héritées par tous les composants du solveur
Orbitale
La Orbital classe est un composant tag-along qui se comporte comme des planètes dans un système solaire. Ce solveur garantit que le GameObject attaché orbite autour de la transformation suivie. Par conséquent, si le type de cible suivi du SolverHandler est défini sur Head, le GameObject tourne autour de la tête de l’utilisateur avec un décalage fixe appliqué.
Les développeurs peuvent modifier ce décalage fixe pour conserver des menus ou d’autres composants de scène au niveau des yeux ou de la taille, etc. autour d’un utilisateur. Pour ce faire, modifiez les propriétés Décalage local et Décalage mondial . La propriété Type d’orientation détermine la rotation appliquée à l’objet s’il doit conserver sa rotation d’origine ou toujours faire face à la caméra ou à la transformation du visage qui pilote sa position, etc.
Exemple orbital
RadialView
Est RadialView un autre composant tag-along qui conserve une partie particulière d’un GameObject dans le frustum de la vue de l’utilisateur.
Les propriétés Degrés d’affichage min & max déterminent la taille d’une partie du GameObject qui doit toujours être visible.
Les propriétés Min & Max Distance déterminent la distance entre le GameObject et l’utilisateur. Par exemple, si vous vous dirigez vers le GameObject avec une distance minimale de 1 m, le GameObject est repoussé pour s’assurer qu’il n’est jamais plus proche de 1 m de l’utilisateur.
En règle générale, le RadialView est utilisé conjointement avec le type de cible suivi défini Head sur afin que le composant suive le regard de l’utilisateur. Toutefois, ce composant peut fonctionner pour être conservé dans la « vue » de n’importe quel type de cible suivi.
Exemple RadialView
Suivre
La Follow classe positionne un élément devant le de la cible suivie par rapport à son axe vers l’avant local. L’élément peut être faiblement limité (également nommé tag-along) afin qu’il ne suive pas tant que la cible suivie ne dépasse pas les limites définies par l’utilisateur.
Il fonctionne de la même façon que le solveur RadialView, avec des contrôles supplémentaires pour gérer le nombre maximal de degrés d’affichage horizontal & vertical et des mécanismes permettant de modifier l’orientation de l’objet.
Suivre les propriétés
Suivez l’exemple de scène (Assets/MRTK/Examples/Demos/Solvers/Scenes/FollowSolverExample.unity)
InBetween
La InBetween classe conserve le GameObject attaché entre deux transformations. Ces deux points de terminaison de transformation sont définis par le type SolverHandler de cible suivi du GameObject et la InBetween propriété Second Tracked Target Type du composant. En règle générale, les deux types sont définis sur CustomOverride et les valeurs résultantes SolverHandler.TransformOverride et InBetween.SecondTransformOverride définies sur les deux points de terminaison suivis.
Au moment de l’exécution, le InBetween composant crée un autre SolverHandler composant basé sur les propriétés Second Tracked Target Type et Second Transform Override .
Définit PartwayOffset où le long de la ligne entre deux transformations l’objet doit être placé avec 0,5 à mi-chemin, 1,0 à la première transformation et 0,0 à la deuxième transformation.
Exemple d’utilisation du solveur InBetween pour conserver l’objet entre deux transformations
SurfaceMagnetism
Le SurfaceMagnetism fonctionne en effectuant un raycast sur un LayerMask défini de surfaces et en plaçant le GameObject à ce point de contact.
Le décalage normal de surface place le GameObject à une distance définie en mètres de la surface dans la direction de la normale au point de contact sur la surface.
À l’inverse, le décalage de rayon de surface place le GameObject à une distance définie en mètres de la surface, mais dans la direction opposée du raycast effectué. Par conséquent, si le raycast est le regard de l’utilisateur, le GameObject se rapproche le long de la ligne, du point de frappe sur la surface à la caméra.
Le mode d’orientation détermine le type de rotation à appliquer par rapport à la normale sur la surface.
- Aucun : aucune rotation appliquée
- TrackedTarget : l’objet sera confronté à la transformation suivie qui pilote le raycast
- SurfaceNormal : l’objet s’aligne en fonction de la normale au point d’accès sur la surface
- Blended : l’objet s’aligne en fonction de la normale au point d’accès sur la surface ET en fonction de la transformation suivie.
Pour forcer le GameObject associé à rester vertical dans un mode autre que Aucun, activez Conserver l’orientation verticale.
Remarque
Utilisez la propriété Orientation Blend pour contrôler l’équilibre entre les facteurs de rotation lorsque le mode d’orientation est défini sur Blended. Une valeur de 0.0 aura une orientation entièrement pilotée par le mode TrackedTarget et une valeur de 1.0 aura une orientation entièrement pilotée par SurfaceNormal.
Déterminer quelles surfaces peuvent être atteintes
Lors de l’ajout d’un SurfaceMagnetism composant à un GameObject, il est important de prendre en compte la couche du GameObject et ses enfants, le cas échéant, ont des collisionneurs. Le composant fonctionne en effectuant différents types de raycasts pour déterminer la surface à « aimanter » lui-même. Si le solveur GameObject a un collisionneur sur l’une des couches répertoriées dans la MagneticSurfaces propriété de SurfaceMagnetism, le raycast se heurtera probablement lui-même, ce qui entraînera l’attachement du GameObject à son propre point de collisionneur. Ce comportement étrange peut être évité en définissant le GameObject principal et tous les enfants sur la couche Ignorer Raycast ou en modifiant le MagneticSurfaces tableau LayerMask de manière appropriée.
À l’inverse, un SurfaceMagnetism GameObject n’entre pas en conflit avec des surfaces sur une couche non répertoriée dans la MagneticSurfaces propriété . Il est généralement recommandé de placer toutes les surfaces souhaitées sur une couche dédiée (c’est-à-dire surfaces) et de définir la MagneticSurfaces propriété sur cette couche uniquement. L’utilisation de la valeur par défaut ou de tout peut entraîner la contribution de composants ou de curseurs d’interface utilisateur au solveur.
Enfin, les surfaces plus éloignées que le MaxRaycastDistance paramètre de propriété seront ignorées par les SurfaceMagnetism raycasts.
DirectionalIndicator
La DirectionalIndicator classe est un composant tag-along qui s’oriente vers la direction d’un point souhaité dans l’espace.
Le plus couramment utilisé lorsque le type de cible suivi du SolverHandler est défini sur Head. De cette façon, un composant d’expérience utilisateur avec le DirectionalIndicator solveur indique à l’utilisateur d’examiner le point souhaité dans l’espace.
Le point souhaité dans l’espace est déterminé via la propriété Cible directionnelle .
Si la cible directionnelle est visible par l’utilisateur, ou si un cadre de référence est défini dans , SolverHandlerce solveur désactive tous les Renderer composants sous-jacents. S’il n’est pas visible, tout est activé sur l’indicateur.
La taille de l’indicateur est réduite, plus l’utilisateur est proche de la capture de la cible directionnelle dans son FOV.
Échelle minimale de l’indicateur : échelle minimale de l’objet indicateur
Échelle maximale de l’indicateur : échelle maximale pour l’objet indicateur
Facteur d’échelle de visibilité : multiplicateur pour augmenter ou diminuer l’objet FOV qui détermine si le point cible directionnel est visible ou non
Décalage de la vue : du point de vue du cadre de référence (c’est-à-dire, éventuellement, caméra), cette propriété définit la distance dans le sens de l’indicateur de l’objet à partir du centre de la fenêtre d’affichage.
Propriétés de l’indicateur directionnel
Exemple de scène d’indicateur directionnel (assets/MRTK/Examples/Demos/Solvers/Scenes/DirectionalIndicatorSolverExample.unity)
Menu Main avec HandConstraint et HandConstraintPalmUp
Le HandConstraint comportement fournit un solveur qui limite l’objet suivi à une région sûre pour le contenu à contrainte manuelle (par exemple, l’interface utilisateur de la main, les menus, etc.). Les régions sûres sont considérées comme des zones qui ne se croisent pas avec la main. Une classe dérivée de HandConstraint appelée HandConstraintPalmUp est également incluse pour illustrer un comportement courant d’activation de l’objet suivi du solveur lorsque la paume est face à l’utilisateur.
Consultez la page Menu main pour obtenir des exemples d’utilisation du solveur hand constraint pour créer des menus de main.