La instancia DragDetector facilita y alienta la interacción con objetos 3D en una experiencia, como abrir puertas y cajones, deslizar una parte alrededor, agarrar y lanzar una bola de boliche, retroceder y disparar una escopeta, y mucho más.Las características clave incluyen:
Coloca un bajo cualquier o para hacerlo arrastrable a través de todos los inputs (ratón, toque, controlador para juegoy VR), todos sin una sola línea de código.
Elige entre varios estilos de arrastrado , define cómo el objeto responde a los movimientos y aplica opcionalmente límites de eje o movimiento .
Los scripts pueden responder a la manipulación de objetos arrastrados para conducir la interfaz de usuario o tomar decisiones lógicas, como ajustar el nivel de luz en una habitación en función de un interruptor de pared deslizante.
Los jugadores pueden manipular piezas o modelos anclados y se quedarán exactamente donde los pongas al lanzamiento.
DragDetectors trabaja en Studio mientras tengas no usando las herramientas Seleccionar , Mover , Escalar o Rotar , lo que facilita probar y ajustar objetos arrastrables mientras se edita.
Hacer objetos arrastrables
Para hacer cualquier parte o modelo arrastrable, simplemente agrega un DragDetector como descendiente directo.
En la ventana Explorador, pasa el mouse sobre el Part, MeshPart o Model y haz clic en el botón ⊕. Se muestra un menú contextual.
Desde el menú, insira un Detector de arrastre .
Por defecto, el objeto ahora será arrastrable en el plano de tierra, pero puedes personalizar su , definir cómo responde a los movimientos y aplicar opcionalmente límites de eje o movimiento .
Personalizar detectores de arrastre
Estilo de arrastrar
DragDetectors mueve el cursor del mapa a líneas y planos virtuales para calcular el movimiento 3D propuesto.A través de la propiedad DragStyle, puedes elegir entre diferentes mapeos para satisfacer tus necesidades.Por ejemplo, TranslatePlane produce traducción en un avión virtual, mientras que RotateAxis produce rotación sobre un eje virtual.
Configuración | Descripción |
---|---|
TranslateLine | 1D de movimiento a lo largo del eje del detector Axis, por defecto, el eje mundial Y . |
TranslatePlane | 2D de movimiento en el avión perpendicular al detector de Axis , por defecto el avión mundial XZ . |
TranslatePlaneOrLine | 2D movimiento en el plano perpendicular al detector Axis y, cuando el modificador está activo, 1D movimiento a lo largo del detector Axis . |
TranslateLineOrPlane | 1D movimiento a lo largo del detector Axis y, cuando el modificador está activo, 2D movimiento en el plano perpendicular al detector Axis . |
TranslateViewPlane | 2D de movimiento en el plano perpendicular a la vista de la cámara.En este modo, el avión se actualiza constantemente, incluso mientras se arrastra, y siempre enfrentará la vista actual de la cámara. |
RotateAxis | Rotación alrededor del detector de Axis , por defecto, el eje mundial Y . |
RotateTrackball | Rotación de la bola de seguimiento, más personalizada a través de las propiedades TrackballRadialPullFactor y TrackballRollFactor. |
BestForDevice | TranslatePlaneOrLine para mouse y controlador para juego; TranslatePlane para toque; 6DOF para VR. |
Scriptable | Calcula el movimiento deseado a través de una función personalizada proporcionada a través de SetDragStyleFunction() . |
Dirección de arrastre
Por defecto, la animación 3D y el mapa asociado DragStyle al espacio mundial.Sin embargo, es posible que desees cambiar el ReferenceInstance , Orientation , o Axis , por ejemplo, al construir detectores de arrastre en modelos con piezas ajustables .
Propiedad | Descripción | Por defecto |
---|---|---|
ReferenceInstance | Una instancia cuyo pivote proporciona el marco de referencia para el detector de arrastre para el detector de arrastre.El DragFrame se expresa en relación con este marco de referencia que se puede recuperar a través de GetReferenceFrame() .Si el marco de referencia es nil , la traducción estará en la dirección de (o en el plano perpendicular a) la propiedad Axis en el espacio mundial. | nil |
Orientation | Specifica la rotación YXZ de los ejes de movimiento relativos al marco de referencia (no cambia la orientación del propio marco de referencia).La traducción lineal y la rotación axial estarán en este eje reorientado Y y la traducción plana en el plano XZ .Cambiar este valor actualiza automáticamente Axis y viceversa. | (0, 0, 0) |
Axis | El eje principal de movimiento, expresado en relación con el marco de referencia. Cambiar este valor actualiza automáticamente Orientation y viceversa. | (0, 1, 0) |
Respuesta a la solicitud
La propiedad ResponseStyle especifica cómo responde un objeto a la moción propuesta, dependiendo de si el objeto es Anchored o no.
Configuración | Comportamiento anclado | Comportamiento sin anclar |
---|---|---|
Geometric | Tanto dentro de la experiencia en ejecución como en el modo de edición de Studio, la posición/orientación de un objeto anclado se actualizará para reflejar exactamente la propuesta de movimiento. | Para un objeto sin anclar, el comportamiento es el mismo que para un objeto anclado.Sin embargo, en una experiencia en ejecución, el objeto se anclará al comienzo del arrastre y se restaurará sin anclar al liberar el arrastre. |
Physical | Un objeto anclado se comportará por defecto como geométrico , ya que no se ve afectado por las fuerzas. | Un objeto sin anclar se moverá por fuerzas de restricción que intentan llevarlo a la posición y/o orientación deseada dada por la propuesta de movimiento. |
Custom | El objeto no se moverá en todos/todas, pero DragFrame aún se actualizará y puedes responder a la manipulación de arrastre como quieras. | (igual que anclado) |
Límites de eje y movimiento
Por defecto, no hay límites para la movilidad 3D más allá de las restricciones inherentes de la DragStyle.Si es necesario, puede aplicar límites mínimos y máximos tanto a la traducción como a la rotación.Tenga en cuenta, sin embargo, que estas no son restricciones no ; simplemente impiden los intentos del detector de arrastrar de generar movimiento para permanecer dentro de los límites.
Propiedades | Descripción | Por defecto |
---|---|---|
Class.DragDetector.MinDragTranslation|MinDragTranslation``Class.DragDetector.MaxDragTranslation|MaxDragTranslation | Límites para arrastrar la traducción en cada dimensión. Si MaxDragTranslation es mayor que MinDragTranslation, la traducción se recortará dentro de ese rango. | (0, 0, 0) |
Class.DragDetector.MinDragAngle|MinDragAngle``Class.DragDetector.MaxDragAngle|MaxDragAngle | Solo es relevante si DragStyle está configurado como RotateAxis .Si MaxDragAngle es mayor que MinDragAngle, la rotación se limitará dentro de ese rango. | 0 |
Arrastrar permisos
El permiso de los jugadores para interactuar con una determinada instancia de detector de arrastre se puede especificar por la propiedad PermissionPolicy.Esto se establece en Enum.DragDetectorPermissionPolicy.Everybody por defecto, y también se puede cambiar para admitir controles de permisos programados como se muestra en el ejemplo de código.
Configuración | Descripción |
---|---|
Nobody | Ningún jugador puede interactuar con el DragDetector. |
Everybody | Todos los jugadores pueden interactuar con el DragDetector. |
Scriptable | Las permisos de arrastrado de los jugadores se determinarán a través de una función registrada a través de SetPermissionPolicyFunction().Bajo esta configuración, el fracaso al registrar una función o devolver un resultado inválido impedirá que todos los jugadores arrastren. |
Detector de arrastre - Permiso de arrastre programado
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)
Respuesta de física
Suponiendo que el estilo de respuesta de un arrastrador se establece en Físico y se aplica a un objeto sin anclar, ese objeto será movido por fuerzas de restricción que intentan llevarlo a la posición/orientación dada por la moción propuesta.Puedes personalizar aún más la respuesta física a través de las siguientes propiedades:
Propiedad | Descripción | Por defecto |
---|---|---|
ApplyAtCenterOfMass | Cuando es falso, se aplica la fuerza de arrastre en el punto en el que el usuario hace clic. Cuando es verdadero, se aplica la fuerza en el centro de masa del objeto. | falso |
MaxForce | Fuerza máxima aplicada al objeto para alcanzar su objetivo. | 10000000 |
MaxTorque | Máximo par aplicado al objeto para alcanzar su objetivo. | 10000 |
Responsiveness | Los valores más altos hacen que el objeto alcance su objetivo más rápidamente. | 10 |
Entrada modificadora
Algunos DragStyle permiten a los usuarios mantener presionada una tecla modificadora para manipular el objeto arrastrado de diferentes maneras.Por defecto, el modificador es LeftControl en la PC, ButtonR1 en el controlador para juegoo ButtonL2 en VR.Puedes personalizar estos modificadores a través de las propiedades KeyboardModeSwitchKeyCode, GamepadModeSwitchKeyCode o VRSwitchKeyCode de la instancia del detector de arrastre.
Replicación
Cuando la propiedad RunLocally es falsa (por defecto), el cliente interpreta toda la entrada para producir datos que envía al servidor para realizar el arrastre.En este modo, todas las señales de evento personalizadas y las funciones registradas deben estar en el servidor Scripts.
Cuando la propiedad RunLocally es verdadera, no se replican eventos al servidor.Todas las señales de evento personalizadas y las funciones registradas deben estar en el cliente LocalScripts y debe utilizar eventos remotos para propagar los cambios necesarios al servidor.
Respuestas de script al hacer clic y arrastrar
A través de señales de evento , cambios de propiedad, Scriptable estilo de arrastrado y funciones personalizadas, los scripts pueden responder a la manipulación de objetos arrastrados para conducir la interfaz de usuario o tomar decisiones lógicas, como ajustar el nivel de luz en una habitación basado en un interruptor de pared deslizante.
Señales de evento
A través de las siguientes señales de evento, puedes detectar cuando un usuario comienza, continúa y termina arrastrando un objeto.
Suceso | Descripción |
---|---|
DragStart | Se activa cuando un usuario comienza a arrastrar el objeto. |
DragContinue | Se enciende cuando un usuario continúa arrastrando el objeto después de que DragStart se haya iniciado. |
DragEnd | Se activa cuando un usuario deja de arrastrar el objeto. |
Detector de arrastrado - Señales 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)
Cambios de marco de arrastrado
Además de las señales de evento , puedes monitorear los cambios en el detector directamente.
Detector de arrastre - Cambios de marco de arrastre
local dragDetector = script.Parent.DragDetector
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
local currentDragTranslation = dragDetector.DragFrame.Position
print(currentDragTranslation)
end)
Estilo de arrastrado programado
Si configuras el detector de DragStyle a Scriptable , puedes proporcionar tu propia función que tome un Ray y devuelva un espacio mundial CFrame .El detector moverá el movimiento para que el objeto arrastrado vaya a esa ubicación/orientación personalizada.
Detector de arrastre - Estilo de arrastre programado
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 arrastrado de la detección 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)
Función de restricción personalizada
Los detectores de arrastrado no tienen reglas de movimiento integradas sobre cuadrículas y ajuste, pero puedes registrar funciones de restricción personalizadas para editar las funciones del detector DragFrame antes de que se aplique.Por ejemplo, puedes mantener el movimiento en una cuadrícula redondeando las posiciones a múltiplos del incremento de la cuadrícula o simular un juego de ajedrez con reglas de movimiento legales para cada pieza.
Detector de arrastrado - Función de restricción 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)
-- When applicable, remove the constraint function by invoking connection:Disconnect()
Uso de ejemplo
Objetos físicos sin anclar
Una implementación básica de detectores de arrastre es un juego de equilibrio de torre en el que los jugadores deben eliminar cuidadosamente las piezas y tratar de mantener la torre en pie.En la siguiente estructura de torre, cada pieza tiene un hijo DragDetector con un predeterminado DragStyle de TranslatePlane para que los jugadores puedan sacar las piezas hacia afuera pero no hacia arriba o hacia abajo.
Modelos anclados con partes ajustables
Puedes crear y compartir modelos fácilmente que estén principalmente anclados, pero que tengan una o más partes/modelos hijos que los jugadores puedan arrastrar.Por ejemplo, el siguiente escritorio tiene dos cajones que los jugadores pueden abrir para inspeccionar lo que hay dentro.
Arrastrar detectores y restricciones
Puedes combinar detectores de arrastre con Constraints, por ejemplo, una marioneta de títeres.En el siguiente escenario, los controladores se anclan, las partes del cuerpo no se anclan y las restricciones mantienen la marioneta unida.Mover los controles con el TranslateViewPlane hace que la marioneta baila, y las partes del cuerpo individuales también se pueden mover con detectores de arrastre, todo mientras el modelo mantiene su integridad.
Interfaces de usuario 3D
Las interfaces de usuario 3D son fácilmente alcanzables a través de detectores de arrastre, como ajustar el brillo de un SpotLight basado en un atenuador de interruptor deslizante.También puedes detectar los ejes X y Z individualmente para controlar dos aspectos diferentes de una interfaz de usuario 3D, como el Size, Speed y Color de un ParticleEmitter.
Detector de arrastrado - Interfaz de usuario 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 el tamaño y la velocidad de las partículas en función del factor X del detector de arrastre
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 el color de las partículas en función del factor Z del detector de arrastre
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)