A instância DragDetector facilita e incentiva a interação com objetos 3D em uma experiência, como abrir portas e gavetas, deslizar uma parte, pegar e lançar uma bola de boliche, puxar e disparar uma funda, e muito mais. As principais características incluem:
Coloque um DragDetector sob qualquer BasePart ou Model para torná-lo arrastável via todas as entradas (mouse, toque, gamepad e VR), tudo isso sem uma única linha de código.
Escolha entre vários estilos de arrasto, defina como o objeto responde ao movimento e, opcionalmente, aplique limites de movimento ou de eixo.
Scripts podem responder à manipulação de objetos arrastados para acionar a interface do usuário ou tomar decisões lógicas, como ajustar o nível de luz em uma sala com base em um dimmer de interruptor deslizante.
Os jogadores podem manipular partes ou modelos ancorados e eles ficarão exatamente onde você os colocou ao serem soltos.
DragDetectors funcionam no Estúdio desde que você não esteja usando as ferramentas Selecionar, Mover, Escalar ou Rotacionar, facilitando o teste e o ajuste de objetos arrastáveis durante a edição.
Tornar objetos arrastáveis
Para tornar qualquer parte ou modelo arrastável, basta adicionar um DragDetector como descendente direto.
No menu, insira um DragDetector.

Por padrão, o objeto agora será arrastável no plano do chão, mas você pode personalizar seu DragStyle, definir como ele responde ao movimento e, opcionalmente, aplicar limites de movimento ou de eixo.
Personalizar detectores de arrasto
Estilo de arrasto
DragDetectors mapeiam o movimento do cursor para linhas e planos virtuais para calcular o movimento 3D proposto. Através da propriedade DragStyle, você pode escolher entre diferentes mapeamentos para atender às suas necessidades. Por exemplo, TranslatePlane produz tradução em um plano virtual, enquanto RotateAxis produz rotação em torno de um eixo virtual.
| Configuração | Descrição |
|---|---|
| TranslateLine | Movimento 1D ao longo do Axis do detector, por padrão, o eixo Y do mundo. |
| TranslatePlane | Movimento 2D no plano perpendicular ao Axis do detector, por padrão, o plano XZ do mundo. |
| TranslatePlaneOrLine | Movimento 2D no plano perpendicular ao Axis do detector e, quando o modificador está ativo, movimento 1D ao longo do Axis do detector. |
| TranslateLineOrPlane | Movimento 1D ao longo do Axis do detector e, quando o modificador está ativo, movimento 2D no plano perpendicular ao Axis do detector. |
| TranslateViewPlane | Movimento 2D no plano perpendicular à visão da câmera. Nesse modo, o plano é constantemente atualizado, mesmo enquanto está sendo arrastado, e sempre enfrentará a visão atual da câmera. |
| RotateAxis | Rotação em torno do Axis do detector, por padrão, o eixo Y do mundo. |
| RotateTrackball | Rotação de trackball, personalizada ainda mais através das propriedades TrackballRadialPullFactor e TrackballRollFactor. |
| BestForDevice | TranslatePlaneOrLine para mouse e gamepad; TranslatePlane para toque; 6DOF para VR. |
| Scriptable | Calcula o movimento desejado através de uma função personalizada fornecida através de SetDragStyleFunction(). |
Direção do arrasto
Por padrão, o movimento 3D e o DragStyle associado mapeiam para o espaço mundial. No entanto, você pode querer mudar o ReferenceInstance, Orientation, ou Axis, por exemplo, ao construir detectores de arrasto em modelos com partes ajustáveis.
| Propriedade | Descrição | Padrão |
|---|---|---|
| ReferenceInstance | Uma instância cujo pivô fornece a estrutura de referência para o detector de arrasto. O DragFrame é expresso em relação a esta estrutura de referência, que pode ser recuperada através de GetReferenceFrame(). Se a estrutura de referência for nil, a tradução será na direção (ou no plano perpendicular ao) do Axis na space mundial. | nil |
| Orientation | Especifica a rotação YXZ dos eixos de movimento em relação à estrutura de referência (não altera a orientação da estrutura de referência em si). A tradução linear e a rotação axial ocorrerão neste eixo Y reorientado, e a tradução em plano no plano XZ. Alterar este valor atualizará automaticamente Axis e vice-versa. | (0, 0, 0) |
| Axis | O eixo primário de movimento, expresso em relação à estrutura de referência. Alterar este valor atualizará automaticamente Orientation e vice-versa. | (0, 1, 0) |
Resposta ao movimento
A propriedade ResponseStyle especifica como um objeto responde ao movimento proposto, dependendo se o objeto está Anchored ou não.
| Configuração | Comportamento ancorado | Comportamento não ancorado |
|---|---|---|
| Geometric | Tanto dentro da experiência em execução quanto no modo de edição do Estúdio, a posição/orientação de um objeto ancorado será atualizada para refletir exatamente o movimento proposto. | Para um objeto não ancorado, o comportamento é o mesmo que para um objeto ancorado. No entanto, em uma experiência em execução, o objeto será ancorado no início do arrasto e restaurado para não ancorado após a liberação do arrasto. |
| Physical | Um objeto ancorado terá um comportamento padrão de Geometric, pois não é afetado por forças. | Um objeto não ancorado será movido por forças de restrição que tentam trazê-lo para a posição/orientação dada pelo movimento proposto. |
| Custom | O objeto não se moverá de forma alguma, mas o DragFrame ainda será atualizado e você pode responder à manipulação de arrasto da maneira que desejar. | (mesmo que ancorado) |
Limites de eixo e movimento
Por padrão, não há limites para o movimento 3D além das restrições inerentes do DragStyle. Se necessário, você pode aplicar limites mínimos e máximos tanto para tradução quanto para rotação. No entanto, observe que estes não são restrições; eles apenas impedem as tentativas do detector de arrasto de gerar movimento para permanecer dentro dos limites.
| Propriedades | Descrição | Padrão |
|---|---|---|
| Limites para tradução de arrasto em cada dimensão. Se MaxDragTranslation for maior que MinDragTranslation, a tradução será restringida dentro dessa faixa. | (0, 0, 0) | |
| Relevante apenas se o DragStyle estiver definido como RotateAxis. Se MaxDragAngle for maior que MinDragAngle, a rotação será restrita dentro dessa faixa. | 0 |
Permissões de arrasto
A permissão dos jogadores para interagir com uma instância de detector de arrasto pode ser especificada pela propriedade PermissionPolicy. Essa definição é Enum.DragDetectorPermissionPolicy.Everybody por padrão, e também pode ser alterada para suportar controles de permissão por script, como mostrado no exemplo de código.
| Configuração | Descrição |
|---|---|
| Nobody | Nenhum jogador pode interagir com o DragDetector. |
| Everybody | Todos os jogadores podem interagir com o DragDetector. |
| Scriptable | As permissões de arrasto dos jogadores serão determinadas por uma função registrada através de SetPermissionPolicyFunction(). Sob essa configuração, a falha em registrar uma função ou retornar um resultado inválido impedirá todos os jogadores de arrastar. |
DragDetector - Permissão de Arrasto por Script
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)
Resposta física
Supondo que o estilo de resposta do arrastador esteja definido como Physical e seja aplicado a um objeto não ancorado, esse objeto será movido por forças de restrição que tentam trazê-lo para a posição/orientação dada pelo movimento proposto. Você pode personalizar ainda mais a resposta física através das seguintes propriedades:
| Propriedade | Descrição | Padrão |
|---|---|---|
| ApplyAtCenterOfMass | Quando falso, a força de arrasto é aplicada no ponto em que o usuário clica. Quando verdadeiro, a força é aplicada no centro de massa do objeto. | false |
| MaxForce | Força máxima aplicada para o objeto alcançar seu objetivo. | 10000000 |
| MaxTorque | Torque máximo aplicado para o objeto alcançar seu objetivo. | 10000 |
| Responsiveness | Valores mais altos fazem o objeto alcançar seu objetivo mais rapidamente. | 10 |
Entrada de modificação
Alguns modos de DragStyle permitem que os usuários mantenham pressionada uma tecla/botão modificador para manipular o objeto arrastado de maneiras diferentes. Por padrão, o modificador é LeftControl no PC, ButtonR1 no gamepad, ou ButtonL2 em VR. Você pode personalizar esses modificadores através das propriedades KeyboardModeSwitchKeyCode, GamepadModeSwitchKeyCode, ou VRSwitchKeyCode da instância do detector de arrasto.
Replicação
Quando a propriedade RunLocally é falsa (padrão), o cliente interpreta toda a entrada para produzir dados que envia ao servidor para realizar o arrasto. Nesse modo, todos os sinais de evento personalizados e funções registradas devem estar no Scripts do servidor.
Quando a propriedade RunLocally é verdadeira, nenhum evento é replicado para o servidor. Todos os sinais de evento personalizados e funções registradas devem estar nos LocalScripts do cliente e você deve usar eventos remotos para propagar as mudanças necessárias para o servidor.
Respostas de script a cliques e arrastos
Por meio de sinais de eventos, alterações de propriedades, estilo de arrasto Scriptable, e funções personalizadas, scripts podem responder à manipulação de objetos arrastados para acionar a interface do usuário ou tomar decisões lógicas, como ajustar o nível de luz em uma sala com base em um dimmer de interruptor deslizante.
Sinais de eventos
Através dos seguintes sinais de eventos, você pode detectar quando um usuário começa, continua e termina de arrastar um objeto.
| Evento | Descrição |
|---|---|
| DragStart | Dispara quando um usuário começa a arrastar o objeto. |
| DragContinue | Dispara quando um usuário continua arrastando o objeto após o DragStart ser iniciado. |
| DragEnd | Dispara quando um usuário para de arrastar o objeto. |
DragDetector - Sinais de Evento
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)
Mudanças no quadro de arrasto
Além dos sinais de eventos, você pode monitorar mudanças no DragFrame do detector diretamente.
DragDetector - Mudanças no DragFrame
local dragDetector = script.Parent.DragDetector
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
local currentDragTranslation = dragDetector.DragFrame.Position
print(currentDragTranslation)
end)
Estilo de arrasto por script
Se você definir o DragStyle de um detector como Scriptable, você pode fornecer sua própria função que recebe um Ray e retorna um CFrame no espaço mundial. O detector moverá o movimento para que o objeto arrastado vá para essa localização/orientação personalizada.
DragDetector - Estilo de Arrasto por 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)
-- Excluir objeto arrastado da detecção 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)
Função de restrição personalizada
Detectores de arrasto não têm regras de movimento embutidas sobre grades e ajuste, mas você pode registrar funções de restrição personalizadas para editar o DragFrame do detector antes que ele seja aplicado. Por exemplo, você pode manter o movimento em uma grade arredondando posições para múltiplos do incremento da grade ou simular um jogo de xadrez com regras de movimento adequadas a cada peça.
DragDetector - Função de Restrição Personalizada
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)
-- Quando aplicável, remova a função de restrição invocando connection:Disconnect()
Exemplos de uso
Objetos físicos não ancorados
Uma implementação básica de detectores de arrasto é um jogo de equilíbrio de torre onde os jogadores devem cuidadosamente remover peças e tentar manter a torre de pé. Na seguinte estrutura de torre, cada peça tem um DragDetector filho com um DragStyle padrão de TranslatePlane para que os jogadores possam puxar as peças para fora, mas não para cima ou para baixo.
Modelos ancorados com partes ajustáveis
Você pode facilmente criar e compartilhar modelos que são principalmente ancorados, mas que têm uma ou mais partes/modelos filhos que os jogadores podem arrastar. Por exemplo, a seguinte mesa tem duas gavetas que os jogadores podem abrir para inspecionar o que há dentro.
Detectores de arrasto e restrições
Você pode combinar detectores de arrasto com Constraints, por exemplo, uma marionete. Na seguinte configuração, os controles estão ancorados, as partes do corpo estão não ancoradas, e restrições mantêm a marionete unida. Mover os controles com o estilo de arrasto DragStyle TranslateViewPlane faz a marionete dançar, e as partes do corpo individuais também podem ser movidas com detectores de arrasto, tudo isso enquanto o modelo mantém sua integridade.
Interfaces de usuário 3D
Interfaces de usuário 3D são facilmente alcançáveis através de detectores de arrasto, como ajustar o brilho de um SpotLight com base em um dimmer de interruptor deslizante. Você também pode detectar os eixos X e Z individualmente para controlar dois aspectos diferentes de uma interface de usuário 3D, como o Size, Speed, e Color de um ParticleEmitter.
DragDetector - Interface de Usuário 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
-- Ajustar o tamanho e a velocidade das partículas com base no fator X do detector de arrasto
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)
-- Ajustar a cor das partículas com base no fator Z do detector de arrasto
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)