UIDragDetector 實例促進並鼓勵與遊戲中的 2D 使用者介面元素互動,例如滑桿、旋轉器等。主要功能包括:
在任何 GuiObject 實例下放置一個 UIDragDetector,使其能夠通過所有使用者輸入進行拖曳,而無需編寫一行代碼。
從幾個 DragStyle 選項中選擇,定義物件如何對運動做出反應,通過 ResponseStyle,並可選擇應用軸、運動限制或拖曳邊界。
腳本可以對拖曳物件的操作做出反應,以驅動邏輯響應,例如調整設置。
UIDragDetectors 在 Studio 的編輯和播放模式下工作,只要您不使用 選擇、移動、縮放 或 旋轉 工具,或某些插件或 Studio 的 UI 編輯工具。
使 UI 元素可拖曳
要使任何 GuiObject 實例可拖曳,只需將 UIDragDetector 作為直接子項添加。
從菜單中插入 UIDragDetector。

默認情況下,該物件現在將在 LayerCollector 界面中可拖曳。
自定義 UI 拖曳檢測器
拖曳樣式
UIDragDetectors 將游標運動映射以計算建議的 2D 運動和/或旋轉。通過 DragStyle 屬性,您可以從不同的映射中選擇以滿足您的需求。例如,Enum.UIDragDetectorDragStyle.TranslatePlane 在 LayerCollector 的 2D 平面中產生平移,而 Enum.UIDragDetectorDragStyle.Rotate 通常產生旋轉而不是平移。
| 設置 | 描述 |
|---|---|
| TranslateLine | 沿檢測器的 DragAxis 的 1D 運動。 |
| TranslatePlane | 在 LayerCollector 的平面中的 2D 運動。 |
| Rotate | 默認情況下,圍繞檢測器的父 GuiObject 的絕對中心位置進行旋轉。如果設置了 ReferenceUIInstance,則旋轉將圍繞該實例的絕對中心位置進行。 |
| Scriptable | 通過 SetDragStyleFunction() 提供的自定義函數計算所需的運動。 |
拖曳方向
默認情況下,2D 運動和相關的 DragStyle 映射到祖先 LayerCollector 的空間。然而,您可能希望在構建不同的 UI 元件時更改 ReferenceUIInstance 或 DragAxis。
| 設置 | 描述 | 默認值 |
|---|---|---|
| ReferenceUIInstance | 一個 GuiObject 實例,其本地空間和絕對中心位置是檢測器的參考空間和原點。設置此參考會影響屬性,例如 DragUDim2、DragRotation 和 DragAxis 的行為。 | nil |
| DragAxis | Vector2 值,定義當 DragStyle 設置為 Enum.UIDragDetectorDragStyle.TranslateLine 時被拖曳物件的運動軸。該軸在 UIDragDetector 的本地空間中定義,除非定義了 ReferenceUIInstance,在這種情況下,該軸在該實例的本地空間中定義。 | (1, 0) |
對運動的響應
UIDragDetector.ResponseStyle 屬性指定物件的位置值如何通過建議的運動進行更改。自定義響應樣式允許您根據需要使用結果的 UIDragDetector.DragUDim2 和 UIDragDetector.DragRotation 值,而無需檢測器的父項執行建議的運動。
| 設置 | 描述 |
|---|---|
| Offset | 根據檢測器父項的 GuiObject.Position 值的 Offset 值移動。這是默認設置。 |
| Scale | 根據檢測器父項的 GuiObject.Position 值的 Scale 值移動。 |
| CustomOffset | UI 元素將完全不移動,但檢測器的 DragUDim2 的 Offset 值仍將被更新,並且檢測器的事件仍將觸發,允許您根據需要對拖曳操作做出響應。 |
| CustomScale | UI 元素將完全不移動,但檢測器的 DragUDim2 的 Scale 值仍將被更新,並且檢測器的事件仍將觸發,允許您根據需要對拖曳操作做出響應。 |
平移與旋轉限制
默認情況下,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 | 確定當其 BoundingUI 被設置時,UIDragDetector 實例的邊界行為。將其設置為 EntireObject 將整個拖曳 UI 限制在 BoundingUI 內,而將其設置為 HitPoint 僅根據確切的命中/抓取點及其在平移/旋轉後的相應位置限制拖曳的 UI。作為方便,Automatic 的默認值模擬了對於完全包含在 BoundingUI 中的 UI 物件的 EntireObject 行為,否則對於部分在 BoundingUI 外的 UI 物件的 HitPoint 行為。 | Automatic |
速度調整
通過 SelectionModeDragSpeed 和 SelectionModeRotateSpeed,您可以微調檢測器的最大拖曳/旋轉速度。此外,通過 UIDragSpeedAxisMapping,您可以根據檢測器的 SelectionModeDragSpeed 微調 X/Y 維度的拖曳速度。
| 屬性 | 描述 |
|---|---|
| SelectionModeDragSpeed | 定義作為 Scale 和 Offset 的組合的平移最大拖曳速度,該組合來自檢測器所屬的第一個祖先 ScreenGui 或 SurfaceGui。 |
| SelectionModeRotateSpeed | 定義 UIDragDetector 可以旋轉的每秒最大角度。 |
| UIDragSpeedAxisMapping | 根據檢測器的 SelectionModeDragSpeed 確定 X/Y 維度的拖曳速度。默認為 XY,這意味著 X 和 Y 軸的速度分別基於 X 和 Y 的 Scale/Offset 值。 替代方案為 XX 和 YY,這意味著 X 和 Y 軸的速度分別基於 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 拖曳限制在容器的全寬內,而無需額外的腳本。
-- 階層為 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() 檢測拖曳旋轉的變更。
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。
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.DragUDim2 和 UIDragDetector.DragRotation。例如,您可以通過將位置四捨五入到特定增量來保持運動在網格上,或定義允許的運動區域。請注意,這是在任何現有的平移/旋轉限制之前應用的。
以下示例利用約束函數將平面拖曳限制在基於行和列數的 X/Y 網格中。請注意,檢測器的 ResponseStyle 設置為 Enum.UIDragDetectorResponseStyle.Scale,其 BoundingUI 設置為網格容器。
-- 階層為 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)