UI 拖动检测器

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

UIDragDetector 实例促进并鼓励与游戏中的 2D 用户界面元素(如滑块、旋转器等)的交互。主要功能包括:

  • 在任何 GuiObject 实例下放置一个 UIDragDetector,使其可以通过所有用户输入进行拖动,而无需编写一行代码。

  • 从多个 DragStyle 选项中选择,定义对象如何响应运动,通过 ResponseStyle,并可选择应用轴、运动限制或拖动边界。

  • 脚本可以响应被拖动对象的操作,以驱动逻辑响应,例如调整设置。

  • UIDragDetectors 在 Studio 的编辑和播放模式下工作,只要您使用 选择移动缩放旋转 工具,以及某些插件或 Studio 的 UI 编辑器工具。

使 UI 元素可拖动

要使任何 GuiObject 实例可拖动,只需将 UIDragDetector 作为直接子项添加。

  1. 资源管理器 窗口中,将鼠标悬停在 GuiObject 实例上,然后单击 ⊕ 按钮。将显示上下文菜单。

  2. 从菜单中插入 UIDragDetector

  3. 默认情况下,该对象现在将在 LayerCollector 界面中可拖动。

自定义 UI 拖动检测器

拖动样式

UIDragDetectors 将光标运动映射到计算建议的 2D 运动和/或旋转。通过 DragStyle 属性,您可以选择不同的映射以满足您的需求。例如,Enum.UIDragDetectorDragStyle.TranslatePlaneLayerCollector 的 2D 平面中产生平移,而 Enum.UIDragDetectorDragStyle.Rotate 通常产生旋转而不是平移。

设置描述
TranslateLine沿检测器的 DragAxis 的 1D 运动。
TranslatePlaneLayerCollector 的平面中的 2D 运动。
Rotate默认情况下,围绕检测器父级 GuiObject 的绝对中心位置旋转。如果设置了 ReferenceUIInstance,则围绕该实例的绝对中心位置旋转。
Scriptable通过 SetDragStyleFunction() 提供的自定义函数计算所需的运动。

拖动方向

默认情况下,2D 运动和相关的 DragStyle 映射到祖先 LayerCollector 的空间。然而,您可能希望在构建不同的 UI 组件时更改 ReferenceUIInstanceDragAxis

设置描述默认
ReferenceUIInstance一个 GuiObject 实例,其局部空间和绝对中心位置是检测器的参考空间和原点。设置此参考会影响 DragUDim2DragRotationDragAxis 的行为等属性。nil
DragAxisVector2 值,定义当 DragStyle 设置为 Enum.UIDragDetectorDragStyle.TranslateLine 时被拖动对象的运动轴。该轴在 UIDragDetector 的局部空间中定义,除非定义了 ReferenceUIInstance,在这种情况下,该轴在该实例的局部空间中定义。(1, 0)

对运动的响应

UIDragDetector.ResponseStyle 属性指定对象的位置值如何通过建议的运动进行更改。自定义响应样式允许您根据需要使用结果的 UIDragDetector.DragUDim2UIDragDetector.DragRotation 值,而无需检测器的父级执行建议的运动。

设置描述
Offset根据检测器父级的 GuiObject.Position 值的 Offset 值移动。这是默认设置。
Scale根据检测器父级的 GuiObject.Position 值的 Scale 值移动。
CustomOffsetUI 元素将完全不移动,但检测器的 DragUDim2Offset 值仍将被更新,检测器的事件仍将触发,允许您根据需要响应拖动操作。
CustomScaleUI 元素将完全不移动,但检测器的 DragUDim2Scale 值仍将被更新,检测器的事件仍将触发,允许您根据需要响应拖动操作。

平移和旋转限制

默认情况下,2D 运动没有限制,除了 DragStyle 的固有限制。如果需要,可以通过以下属性声明最小和最大平移和旋转的限制。此外,您可以定义被拖动对象在指定的 GuiObject(例如 Frame)的边界内如何约束。

属性描述默认
MinDragTranslation
MaxDragTranslation
在每个维度上的拖动平移限制,由 UDim2 值定义。如果 MaxDragTranslation 大于 MinDragTranslation,则平移将在该范围内被限制。{0, 0}, {0, 0}
MinDragAngle
MaxDragAngle
仅在 DragStyle 设置为 Enum.UIDragDetectorDragStyle.Rotate 时相关,或者如果通过 SetDragStyleFunction()AddConstraintFunction() 设置的函数定义了旋转值。如果 MaxDragAngle 大于 MinDragAngle,则旋转将在该范围内被限制。0
BoundingBehavior确定 UIDragDetector 实例的边界行为,当其 BoundingUI 被设置时。将其设置为 EntireObject 会将整个拖动的 UI 限制在 BoundingUI 内,而将其设置为 HitPoint 仅根据确切的命中/抓取点及其在平移/旋转后的相应位置限制拖动的 UI。作为便利,Automatic 的默认值模拟了对于完全包含在 BoundingUI 内的 UI 对象的 EntireObject 行为,或者对于部分在 BoundingUI 外部的 UI 对象的 HitPoint 行为。Automatic

速度调整

通过 SelectionModeDragSpeedSelectionModeRotateSpeed,您可以微调检测器的最大拖动/旋转速度。此外,通过 UIDragSpeedAxisMapping,您可以根据检测器的 SelectionModeDragSpeed 微调 X/Y 维度的拖动速度。

属性描述
SelectionModeDragSpeed定义平移的最大拖动速度,作为 ScaleOffset 的组合,适用于检测器所属的第一个祖先 ScreenGuiSurfaceGui
SelectionModeRotateSpeed定义 UIDragDetector 可以旋转的最大角度每秒。
UIDragSpeedAxisMapping根据检测器的 SelectionModeDragSpeed 确定 X/Y 维度的拖动速度。默认值为 XY,意味着 XY 轴的速度分别基于 XYScale/Offset 值。

替代方案为 XXYY,意味着 XY 轴的速度分别基于 X (XX) 或 Y (YY) 轴的 Scale,而 Offset 值仍适用于各自的轴。例如,如果第一个祖先 ScreenGui 的大小为 800×600,且 SelectionModeDragSpeed{0.1, 10}, {0.1, 20},则设置为 XX 将导致 X/Y 拖动速度为 80+10/80+20,而 YY 将导致 60+10/60+20(注意 Offset 值在两种情况下保持不变)。

脚本对点击和拖动的响应

通过 事件信号、属性更改、Scriptable 拖动样式和自定义函数,脚本可以响应被拖动 UI 元素的操作,以驱动各种设置或做出逻辑决策,例如调整音乐和音效音量的滑块。

事件信号

通过以下事件信号,您可以检测用户何时开始、继续和结束拖动对象。

事件描述
DragStart当用户开始拖动对象时触发。
DragContinue当用户在 DragStart 被触发后继续拖动对象时触发。
DragEnd当用户停止拖动对象时触发。

以下滑块将其容器指定为 BoundingUI,以限制其在容器区域内的移动,允许基于比例的 TranslateLine 拖动限制在容器的整个宽度内,而无需额外的脚本。

UIDragDetector - 事件信号透明度变化
-- 层级为 SliderContainer ⟩ Handle ⟩ UIDragDetector ⟩ (此脚本)
local sliderContainer = script.Parent.Parent.Parent
local handle = sliderContainer:FindFirstChild("Handle")
local uiDragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
uiDragDetector.ResponseStyle = Enum.UIDragDetectorResponseStyle.Scale -- 设置按比例拖动
uiDragDetector.DragStyle = Enum.UIDragDetectorDragStyle.TranslateLine -- 限制拖动为线性
uiDragDetector.BoundingUI = sliderContainer
-- 初始设置容器透明度为手柄的 X 比例值
sliderContainer.BackgroundTransparency = 1 - handle.Position.X.Scale
-- 扩大手柄边框以指示抓取开始
uiDragDetector.DragStart:Connect(function(inputPosition)
handle:FindFirstChildWhichIsA("UIStroke").Thickness = 6
end)
-- 根据拖动的比例变化透明度
uiDragDetector.DragContinue:Connect(function(inputPosition)
sliderContainer.BackgroundTransparency = 1 - handle.Position.X.Scale
end)
-- 恢复手柄边框以指示抓取结束
uiDragDetector.DragEnd:Connect(function(inputPosition)
handle:FindFirstChildWhichIsA("UIStroke").Thickness = 4
end)

位置和旋转变化

除了 事件信号 之外,您还可以直接监控检测器的 DragUDim2 和/或 DragRotation 属性的变化。

以下检测器的 DragStyle 设置为 Rotate,允许用户在色调旋转环上拖动手柄,同时通过 Instance:GetPropertyChangedSignal() 检测拖动旋转的变化。

UIDragDetector - DragRotation 变化
local handle = script.Parent.Parent -- 要拖动的 UI 元素
local uiDragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
uiDragDetector.DragStyle = Enum.UIDragDetectorDragStyle.Rotate -- 设置拖动样式为旋转
local function changeHue()
local currAngle = (math.fmod(handle.Rotation, 360)) / 360
if currAngle < 0 then
currAngle += 1
end
handle.BackgroundColor3 = Color3.fromHSV(currAngle, 1, 1)
end
-- 初始设置色调为手柄旋转
changeHue()
-- 将函数连接到检测器的拖动旋转的 GetPropertyChangedSignal()
uiDragDetector:GetPropertyChangedSignal("DragRotation"):Connect(changeHue)

脚本化拖动样式

如果您将检测器的 UIDragDetector.DragStyle 设置为 Enum.UIDragDetectorDragStyle.Scriptable,您可以提供自己的函数,该函数接受一个 Vector2 的输入位置并返回一个 UDim2(位置)和一个浮点数(旋转)。检测器将根据返回值、DragSpace 属性和 DragRelativity 属性更新对象到计算的位置/旋转。

默认情况下,返回的 UDim2 和浮点数将是检测器父级的局部空间中的 最终 所需位置/旋转。现有的平移/旋转限制仍将适用,以及由指定的 BoundingUI 实例施加的边界限制。

以下示例根据 X 坐标输入的变化拖动 UI 元素,遵循计算出的正弦波。请注意,检测器的 DragSpace 设置为 Enum.UIDragDetectorDragSpace.Relative

UIDragDetector - 拖动遵循正弦波
local frame = script.Parent -- 要拖动的 UI 元素
local uiDragDetector = frame:FindFirstChildWhichIsA("UIDragDetector")
local initialXValue = 0
local maxHeightChange = 200
local pixelsPerRadian = 75 -- 降低此值以增加频率
uiDragDetector.DragStart:Connect(function(inputPosition)
initialXValue = inputPosition.X
end)
local function computeSinWaveCoordinate(inputPosition)
local deltaX = inputPosition.X - initialXValue
-- 负 Y delta 使其在屏幕上随着正 Y 变化而“向上”移动
local deltaY = -math.sin(deltaX / pixelsPerRadian) * maxHeightChange
return UDim2.fromOffset(deltaX, deltaY)
end
uiDragDetector:SetDragStyleFunction(computeSinWaveCoordinate)

自定义约束函数

UIDragDetectors 没有关于网格和对齐的内置运动规则,但您可以注册自定义约束函数,以在应用之前编辑检测器的 UIDragDetector.DragUDim2UIDragDetector.DragRotation。例如,您可以通过将位置四舍五入到特定增量来保持运动在网格上,或定义允许的运动区域。请注意,这在任何现有的平移/旋转限制之前应用。

以下示例利用约束函数将平面拖动限制在基于行和列数量的 X/Y 网格中。请注意,检测器的 ResponseStyle 设置为 Enum.UIDragDetectorResponseStyle.Scale,其 BoundingUI 设置为网格容器。

UIDragDetector - 在网格中拖动,贴合瓷砖
-- 层级为 GridContainer ⟩ Handle ⟩ UIDragDetector ⟩ (此脚本)
local gridContainer = script.Parent.Parent.Parent
local handle = gridContainer:FindFirstChild("Handle") -- 要拖动的 UI 元素
local uiDragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
uiDragDetector.ResponseStyle = Enum.UIDragDetectorResponseStyle.Scale -- 设置按比例拖动
uiDragDetector.DragRelativity = Enum.UIDragDetectorDragRelativity.Relative
uiDragDetector.BoundingUI = gridContainer
local NUM_COLUMNS = 10
local NUM_ROWS = 5
local xScaleIncrement = 1 / NUM_COLUMNS
local yScaleIncrement = 1 / NUM_ROWS
local initialParentPosition = uiDragDetector.Parent.Position
uiDragDetector.DragStart:Connect(function()
initialParentPosition = uiDragDetector.Parent.Position
end)
local function dragToGridOnly(proposedPosition, proposedRotation)
local griddedXScale = math.round(proposedPosition.X.Scale / xScaleIncrement) * xScaleIncrement
local griddedYScale = math.round(proposedPosition.Y.Scale / yScaleIncrement) * yScaleIncrement
return UDim2.fromScale(griddedXScale, griddedYScale), proposedRotation
end
uiDragDetector:AddConstraintFunction(1, dragToGridOnly)
©2026 Roblox Corporation、Roblox、Roblox 标志及 Powering Imagination 是我们在美国及其他国家或地区的注册与未注册商标。