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.
Dans la fenêtre Explorateur, passez la souris sur le Part, MeshPart ou Model et cliquez sur le bouton ⊕. Un menu contextuel s'affiche.
Dans le menu, insérez un Détecteur de glissement .
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ètre | Avertissement |
---|---|
TranslateLine | 1D mouvement le long de l'axe du détecteur Axis, par défaut l'axe du monde Y . |
TranslatePlane | Mouvement 2D dans l'avion perpendiculaire au plan du détecteur Axis, par défaut le plan du monde XZ . |
TranslatePlaneOrLine | 2D 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 . |
TranslateLineOrPlane | 1D 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 . |
TranslateViewPlane | Mouvement 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. |
RotateAxis | Rotation autour de l'axe du détecteur Axis, par défaut du monde Y . |
RotateTrackball | Rotation 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. |
Scriptable | Calcule 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é | Avertissement | Par défaut |
---|---|---|
ReferenceInstance | Une 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 |
Orientation | Spé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) |
Axis | L'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ètre | Comportement 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. |
Physical | Un 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. |
Custom | L'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és | Avertissement | Par défaut |
---|---|---|
Class.DragDetector.MinDragTranslation|MinDragTranslation``Class.DragDetector.MaxDragTranslation|MaxDragTranslation | Limites 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|MaxDragAngle | Seulement 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ètre | Avertissement |
---|---|
Nobody | Aucun joueur ne peut interagir avec le DragDetector. |
Everybody | Tous les joueurs peuvent interagir avec le DragDetector. |
Scriptable | Les 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é | Avertissement | Par défaut |
---|---|---|
ApplyAtCenterOfMass | Lorsque 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 |
MaxForce | Force maximale appliquée à l'objet pour atteindre son objectif. | 10000000 |
MaxTorque | Couple maximum appliqué à l'objet pour atteindre son objectif. | 10000 |
Responsiveness | Les 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énement | Avertissement |
---|---|
DragStart | S'enflamme lorsqu'un utilisateur commence à faire glisser l'objet. |
DragContinue | S'enflamme lorsqu'un utilisateur poursuit le glissement de l'objet après que DragStart ait été initié. |
DragEnd | S'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)