Détecteurs de glissement 3D

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

L'instance DragDetector facilite et encourage l'interaction avec des objets 3D dans une expérience, tels que l'ouverture de portes et de tiroirs, le glissement d'une partie autour, la saisie et le lancer d'une boule de bowling, le retrait et le tir d'un lance-pierres, et bien plus encore.Les caractéristiques clés incluent :

  • Placez un DragDetector sous n'importe quel BasePart ou Model pour le rendre glissable via toutes les entrées (souris, toucher, manette de jeu et VR), sans une seule ligne de code.

  • Choisissez parmi plusieurs styles de glissement , définissez comment l'objet répond au mouvement et appliquez facultativement des limites d'axe ou de mouvement .

  • Les scripts peuvent répondre à la manipulation d'objets glissés pour piloter l'interface utilisateur ou prendre des décisions logiques, telles que l'ajustement du niveau de lumière dans une salle en fonction d'un interrupteur de mur glissant.

  • Les joueurs peuvent manipuler des parties ou des modèles ancrés et ils resteront exactement où vous les avez placés lors de la sortie.

  • DragDetectors travaillez dans Studio aussi longtemps que vous êtes pas en utilisant les outils sélectionner , déplacer , échelle ou tourner les outils, ce qui facilite le test et l'ajustement des objets glissables pendant l'édition.

Rendre les objets glissables

Pour rendre n'importe quelle partie ou modèle glissable, ajoutez simplement un DragDetector comme descendant direct.

  1. Dans la fenêtre Explorateur, passez la souris sur le Part, MeshPart ou Model et cliquez sur le bouton ⊕. Un menu contextuel s'affiche.

  2. Dans le menu, insérez un Détecteur de glissement .

  3. Par défaut, l'objet sera maintenant glissable dans l'avion au sol, mais vous pouvez personnaliser son , définir comment il répond au mouvement et appliquer facultativement des limites d'axe ou de mouvement .

Personnaliser les détecteurs de glissement

Glisser le style

DragDetectors map curseur de mouvement vers les lignes et les plans virtuels pour calculer la motion 3D proposée.Grâce à la propriété DragStyle, vous pouvez choisir parmi différentes mises en correspondance pour répondre à vos besoins.Par exemple, TranslatePlane produit une traduction dans un avion virtuel, tandis que RotateAxis produit une rotation autour d'un axe virtuel.

ParamètreAvertissement
TranslateLine1D mouvement le long de l'axe du détecteur Axis, par défaut l'axe du monde Y .
TranslatePlaneMouvement 2D dans l'avion perpendiculaire au plan du détecteur Axis, par défaut le plan du monde XZ .
TranslatePlaneOrLine2D mouvement dans l'avion perpendiculaire au détecteur de Axis et, lorsque le modifieur est actif, 1D mouvement le long du détecteur de Axis .
TranslateLineOrPlane1D mouvement le long du détecteur de Axis et, lorsque le modifieur est actif, 2D mouvement dans l'axe perpendiculaire au détecteur de Axis .
TranslateViewPlaneMouvement 2D dans l'avion perpendiculaire à la voirde la caméra.Dans ce mode, l'avion est constamment mis à jour, même en train de glisser, et sera toujours face à la voiractuelle de la caméra.
RotateAxisRotation autour de l'axe du détecteur Axis, par défaut du monde Y .
RotateTrackballRotation de la boule de suivi, plus personnalisée via les propriétés TrackballRadialPullFactor et TrackballRollFactor.
BestForDevice TranslatePlaneOrLine pour la souris et le gamepad ; TranslatePlane pour le toucher ; 6DOF pour la VR.
ScriptableCalcule le mouvement souhaité via une fonction personnalisée fournie via SetDragStyleFunction().

Diréction de glissement

Par défaut, le mouvement 3D et la carte associée DragStyle dans l'espace du monde.Cependant, vous pouvez vouloir modifier le ReferenceInstance , Orientation , ou Axis , par exemple lors de la construction de détecteurs de glisse dans des modèles avec des parties ajustables .

PropriétéAvertissementPar défaut
ReferenceInstanceUne instance dont le pivot fournit le cadre de référence pour le détecteur de glissement.Le DragFrame est exprimé par rapport à ce cadre de référence qui peut être récupéré via GetReferenceFrame() .Si le cadre de référence est nil , la traduction sera dans la direction de (ou dans l'axe perpendiculaire à) la propriété Axis dans l'espace mondial.nil
OrientationSpécifie la rotation YXZ des axes de mouvement par rapport au cadre de référence (ne change pas l'orientation du cadre de référence lui-même).La traduction linéaire et la rotation axiale seront sur cet axe réorienté Y , et la traduction planaire dans le plan XZ .Changer cette valeur met automatiquement à jour Axis et vice versa.(0, 0, 0)
AxisL'axe principal de mouvement, exprimé par rapport au cadre de référence. Changer cette valeur met automatiquement à jour Orientation et vice versa.(0, 1, 0)

Réponse à la motion

La propriété ResponseStyle spécifie comment un objet répond à la motion proposée, en fonction de savoir si l'objet est Anchored ou non.

ParamètreComportement ancréComportement non ancré
GeometricÀ la fois dans l'expérience en cours d'exécution et dans le mode d'édition Studio, la position/orientation d'un objet ancré sera mise à jour pour refléter exactement la motion proposée.Pour un objet non ancré, le comportement est le même que pour un objet ancré.Cependant, dans une expérience en cours d'exécution, l'objet sera ancré au début du glisser et restauré à l'arrêt du glisser.
PhysicalUn objet ancré utilisera par défaut le comportement géométrique Geometric , car il n'est pas affecté par les forces.Un objet non ancré sera déplacé par forces de contrainte qui tentent de le ramener à la position et/ou à l'orientation souhaitée donnée par la motion proposée.
CustomL'objet ne bougera pas du tout, mais DragFrame sera toujours mis à jour et vous pourrez répondre à la manipulation de glissement comme vous le souhaitez.(même que l'ancré)

Limites d'axe et de mouvement

Par défaut, il n'y a pas de limites à la mobilité 3D au-delà des restrictions inhérentes du DragStyle .Si nécessaire, vous pouvez appliquer des limites minimales et maximales à la fois à la traduction et à la rotation.Remarquez cependant que ce ne sont pas ces contraintes ; elles empêchent simplement les tentatives du détecteur de mouvement de générer des mouvements afin de rester dans les limites.

PropriétésAvertissementPar défaut
Class.DragDetector.MinDragTranslation|MinDragTranslation``Class.DragDetector.MaxDragTranslation|MaxDragTranslationLimites de la traduction glissante dans chaque dimension. Si MaxDragTranslation est supérieur à MinDragTranslation, la traduction sera claquée dans cette plage.(0, 0, 0)
Class.DragDetector.MinDragAngle|MinDragAngle``Class.DragDetector.MaxDragAngle|MaxDragAngleSeulement pertinent si DragStyle est réglé sur RotateAxis .Si MaxDragAngle est supérieur à MinDragAngle, la rotation sera comprise dans cette plage.0

Faire glisser les permissions

La permission aux joueurs d'interagir avec une instance de détecteur de glissement donnée peut être spécifiée par la propriété PermissionPolicy.Cela est défini par défaut à Enum.DragDetectorPermissionPolicy.Everybody et peut également être modifié pour prendre en charge les contrôles d'autorisation programmés comme indiqué dans l'exemple de code.

ParamètreAvertissement
NobodyAucun joueur ne peut interagir avec le DragDetector.
EverybodyTous les joueurs peuvent interagir avec le DragDetector.
ScriptableLes permissions de glisser des joueurs seront déterminées par une fonction enregistrée via SetPermissionPolicyFunction().Sous ce paramètre, l'échec de l'enregistrement d'une fonction ou le retour d'un résultat non valide empêchera tous les joueurs de faire glisser.
Détecteur de glissement - Permission de glissement scriptée

local dragDetector = script.Parent.DragDetector
dragDetector.PermissionPolicy = Enum.DragDetectorPermissionPolicy.Scriptable
dragDetector:SetPermissionPolicyFunction(function(player, part)
if player and player:GetAttribute("IsInTurn") then
return true
elseif part and not part:GetAttribute("IsDraggable") then
return false
else
return true
end
end)

Réponse physique

En supposant que le style de réponse d'un glisseur est réglé sur physique et qu'il est appliqué à un objet non ancré, cet objet sera déplacé par des forces de contrainte qui tentent de l'amener à la position/orientation donnée par la motion proposée.Vous pouvez personnaliser davantage la réponse physique via les propriétés suivantes :

PropriétéAvertissementPar défaut
ApplyAtCenterOfMassLorsque false, la force de trascinage est appliquée au point sur lequel l'utilisateur clique. Lorsque true, la force est appliquée au centre de masse de l'objet.faux
MaxForceForce maximale appliquée à l'objet pour atteindre son objectif.10000000
MaxTorqueCouple maximum appliqué à l'objet pour atteindre son objectif.10000
ResponsivenessLes valeurs plus élevées font en sorte que l'objet atteigne son objectif plus rapidement.10

Entrée modifiante

Certains modes DragStyle permettent aux utilisateurs de maintenir une touche modifiante enfoncée pour manipuler l'objet glissé de différentes manières.Par défaut, le modifieur est LeftControl sur PC, ButtonR1 sur manette de jeu, ou ButtonL2 sur VR.Vous pouvez personnaliser ces modifieurs via les propriétés KeyboardModeSwitchKeyCode , GamepadModeSwitchKeyCode ou VRSwitchKeyCode du détecteur de glissement de l'instance.

Réplication

Lorsque la propriété RunLocally est fausse (par défaut), le client interprète toutes les entrées pour produire des données qu'il envoie au serveur pour effectuer le glisser.Dans ce mode, tous les signaux d'événement personnalisés et les fonctions enregistrées doivent être dans le serveur Scripts .

Lorsque la propriété RunLocally est vraie, aucun événement n'est répliqué sur le serveur.Tous les signaux d'événement personnalisés et les fonctions enregistrées doivent être dans le client LocalScripts et vous devez utiliser événements à distance pour propager les modifications nécessaires au serveur.

Réponses de script au clic et au glissement

Grâce aux signaux d'événement , aux modifications de propriété, au style de glisser, et aux fonctions personnalisées, les scripts peuvent répondre à la manipulation des objets glissés pour piloter l'interface utilisateur ou prendre des décisions logiques, telles que l'ajustement du niveau de lumière dans une salle en fonction d'un interrupteur de mur glissant.

Signaux d'événement

Grâce aux signaux d'événement suivants, vous pouvez détecter quand un utilisateur commence, continue et termine le glissement d'un objet.

ÉvénementAvertissement
DragStartS'enflamme lorsqu'un utilisateur commence à faire glisser l'objet.
DragContinueS'enflamme lorsqu'un utilisateur poursuit le glissement de l'objet après que DragStart ait été initié.
DragEndS'enflamme lorsqu'un utilisateur arrête de faire glisser l'objet.
Détecteur de glissement - Signaux d'événement

local dragDetector = script.Parent.DragDetector
local highlight = Instance.new("Highlight")
highlight.Enabled = false
highlight.Parent = script.Parent
dragDetector.DragStart:Connect(function()
highlight.Enabled = true
end)
dragDetector.DragContinue:Connect(function()
end)
dragDetector.DragEnd:Connect(function()
highlight.Enabled = false
end)

Modifications de la fenêtre de glisser

En plus des signaux d'événement , vous pouvez surveiller les modifications du détecteur directement.

Détecteur de glissement - Changements de cadre de glissement

local dragDetector = script.Parent.DragDetector
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
local currentDragTranslation = dragDetector.DragFrame.Position
print(currentDragTranslation)
end)

Style de glisser programmé

Si vous définissez le DragStyle d'un détecteur à Scriptable , vous pouvez fournir votre propre fonction qui prend un Ray et renvoie un espace mondial CFrame .Le détecteur déplacera la motion afin que l'objet traîné aille à cet endroit/orientation personnalisé.

Détecteur de glissement - Style de glissement scripté

local Workspace = game:GetService("Workspace")
local dragDetector = script.Parent.DragDetector
dragDetector.DragStyle = Enum.DragDetectorDragStyle.Scriptable
local cachedHitPoint = Vector3.zero
local cachedHitNormal = Vector3.yAxis
local function followTheCursor(cursorRay)
-- Exclure l'objet glissé de la détection de raycast
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {dragDetector.Parent}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local hitPoint = Vector3.zero
local hitNormal = Vector3.yAxis
local raycastResult = Workspace:Raycast(cursorRay.Origin, cursorRay.Direction, raycastParams)
if raycastResult then
hitPoint = raycastResult.Position
hitNormal = raycastResult.Normal.Unit
else
hitPoint = cachedHitPoint
hitNormal = cachedHitNormal
end
cachedHitPoint = hitPoint
cachedHitNormal = hitNormal
local lookDir1 = hitNormal:Cross(Vector3.xAxis)
local lookDir2 = hitNormal:Cross(Vector3.yAxis)
local lookDir = if lookDir1.Magnitude > lookDir2.Magnitude then lookDir1.Unit else lookDir2.Unit
return CFrame.lookAt(hitPoint, hitPoint + lookDir, hitNormal)
end
dragDetector:SetDragStyleFunction(followTheCursor)

Fonction de contrainte personnalisée

Les détecteurs de glissement n'ont pas de règles de mouvement intégrées sur les grilles et la fixation, mais vous pouvez enregistrer des fonctions de contrainte personnalisées pour modifier les fonctions du détecteur avant qu'il ne soit appliqué.Par exemple, vous pouvez maintenir le mouvement sur une grille en arrondissant les positions aux multiples de l'augmentation de grille, ou simuler une partie d'échecs avec des règles de mouvement légales pour chaque pièce.

Détecteur de glissement - Fonction de contrainte personnalisée

local dragDetector = script.Parent.DragDetector
local startPartPosition = nil
local SNAP_INCREMENT = 4
dragDetector.DragStart:Connect(function()
startPartPosition = script.Parent.Position
end)
dragDetector.DragEnd:Connect(function()
startPartPosition = nil
end)
local function snapToWorldGrid(proposedMotion)
if startPartPosition == nil then
return proposedMotion
end
local snapIncrement = SNAP_INCREMENT // 1
if snapIncrement < 1 then
return proposedMotion
end
local newWorldPosition = startPartPosition + proposedMotion.Position
local roundedX = ((newWorldPosition.X / snapIncrement + 0.5) // 1) * snapIncrement
local roundedY = ((newWorldPosition.Y / snapIncrement + 0.5) // 1) * snapIncrement
local roundedZ = ((newWorldPosition.Z / snapIncrement + 0.5) // 1) * snapIncrement
local newRoundedWorldPosition = Vector3.new(roundedX, roundedY, roundedZ)
return proposedMotion.Rotation + (newRoundedWorldPosition - startPartPosition)
end
local connection = dragDetector:AddConstraintFunction(2, snapToWorldGrid)
-- When applicable, remove the constraint function by invoking connection:Disconnect()

Exemple d'utilisation

Objets physiques non ancrés

Une implémentation de base des détecteurs de glissement est un jeu d'équilibre de tour où les joueurs doivent retirer soigneusement les pièces et essayer de garder la tour debout.Dans la structure de tour suivante, chaque pièce a un enfant DragDetector avec un enfant par défaut DragStyle de TranslatePlane afin que les joueurs puissent sortir les pièces vers l'extérieur mais pas vers le haut ou vers le bas.

Modèles ancrés avec des parties réglables

Vous pouvez facilement créer et partager des modèles qui sont principalement ancrés, mais qui ont une ou plusieurs parties/modèles enfants que les joueurs peuvent faire glisser.Par exemple, le bureau suivant a deux tiroirs que les joueurs peuvent ouvrir pour inspecter ce qui est à l'intérieur.

Faire glisser détecteurs et contraintes

Vous pouvez combiner les détecteurs de glissement avec Constraints , par exemple une marionnette manipulée.Dans le paramètre suivant, les poignées de contrôle sont ancrées, les parties du corps ne sont pas ancrées et les contraintes maintiennent la marionnette ensemble.Déplacer les poignées avec le TranslateViewPlane rend la marionnette en mouvement, et les parties du corps individuelles peuvent également être déplacées avec des détecteurs de glissement, tout en conservant l'intégrité du modèle.

Interfaces utilisateur 3D

Les interfaces utilisateur 3D sont facilement réalisables via des détecteurs de glissement, comme l'ajustement de la luminosité d'un SpotLight basé sur un interrupteur à bascule.Vous pouvez également détecter les axes X et Z individuellement pour contrôler deux aspects différents d'une interface utilisateur 3D, tels que Size, Speed et Color d'un ParticleEmitter.

Détecteur de glissement - Interface utilisateur 3D

local model = script.Parent
local slider = model.SliderPart
local originPart = model.OriginPart
local emitter = script.Parent.EmitterPart.ParticleEmitter
local dragDetector = slider.DragDetector
dragDetector.ReferenceInstance = originPart
dragDetector.MinDragTranslation = Vector3.zero
dragDetector.MaxDragTranslation = Vector3.new(10, 0, 10)
local dragRangeX = dragDetector.MaxDragTranslation.X - dragDetector.MinDragTranslation.X
local dragRangeZ = dragDetector.MaxDragTranslation.Z - dragDetector.MinDragTranslation.Z
local MIN_PARTICLE_SIZE = 1
local MAX_PARTICLE_SIZE = 1.5
local MIN_PARTICLE_SPEED = 2.5
local MAX_PARTICLE_SPEED = 5
local COLOR1 = Color3.fromRGB(255, 150, 0)
local COLOR2 = Color3.fromRGB(255, 0, 50)
local function updateParticles(emitter)
local dragFactorX = (dragDetector.DragFrame.Position.X - dragDetector.MinDragTranslation.X) / dragRangeX
local dragFactorZ = (dragDetector.DragFrame.Position.Z - dragDetector.MinDragTranslation.Z) / dragRangeZ
-- Ajustez la taille et la vitesse des particules en fonction du facteur X du détecteur de traînée
emitter.Size = NumberSequence.new{
NumberSequenceKeypoint.new(0, 0),
NumberSequenceKeypoint.new(0.1, MIN_PARTICLE_SIZE + ((MAX_PARTICLE_SIZE - MIN_PARTICLE_SIZE) * dragFactorX)),
NumberSequenceKeypoint.new(1, 0)
}
local speed = MIN_PARTICLE_SPEED + ((MAX_PARTICLE_SPEED - MIN_PARTICLE_SPEED) * dragFactorX)
emitter.Speed = NumberRange.new(speed, speed * 1.2)
-- Ajuster la couleur des particules en fonction du facteur Z du détecteur de glissement
local color = COLOR2:Lerp(COLOR1, dragFactorZ)
emitter.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, color),
ColorSequenceKeypoint.new(1, color)
}
end
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
updateParticles(emitter)
end)