UI 拖动检测器

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

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

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

  • 从多个 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
DragAxisDragStyle 设置为 Enum.UIDragDetectorDragStyle.TranslateLine 时,定义拖动对象的运动轴的 Vector2 值。该轴是在 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定义拖动平移的最大速度,作为检测器所属的第一个祖先 ScreenGuiSurfaceGuiScaleOffset 的组合。
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 增量使其在屏幕上以正 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 是我们在美国及其他国家或地区的注册与未注册商标。