UIDragDetector 實例促進並鼓勵與體驗中的 2D 使用者介面元素互動,例如滑桿、旋轉器等。主要功能包括:
將 UIDragDetector 安置在任何 GuiObject 實例之下,即可透過所有使用者輸入使其可拖曳,而無需撰寫一行程式碼。
可選擇多種 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 值將仍然更新,並且檢測器的事件仍然會觸發,允許您以自己喜歡的方式對拖曳操作做出反應。 |
平移和旋轉限制
默認情況下,對於 DragStyle 的固有限制,2D 運動沒有任何限制。如果需要,您可以透過以下屬性聲明最小和最大平移和旋轉的限制。此外,您還可以定義被拖曳物件在指定的 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 行為,否則為 HitPoint,適用於部份在 BoundingUI 之外的 UI 物件。 | Automatic |
速度調整
透過 SelectionModeDragSpeed 和 SelectionModeRotateSpeed,您可以微調檢測器的最大拖曳/旋轉速度。此外,透過 UIDragSpeedAxisMapping,您可以根據檢測器的 SelectionModeDragSpeed 微調 X/Y 維度的拖曳速度。
| 屬性 | 描述 |
|---|---|
| SelectionModeDragSpeed | 定義平移的最大拖曳速度,作為 Scale 和 Offset 的組合,基於 UIDragDetector 所屬的第一個祖先 ScreenGui 或 SurfaceGui。 |
| SelectionModeRotateSpeed | 定義 UIDragDetector 每秒的最大旋轉角度。 |
| UIDragSpeedAxisMapping | 根據檢測器的 SelectionModeDragSpeed 確定 X/Y 維度的拖曳速度。默認值為 XY,即 X 和 Y 軸的速度基於 X 和 Y 的 Scale / Offset 值。 替代方案為 XX 和 YY,意味着 X 和 Y 軸的速度基於 Scale 的 X (XX) 或 Y (YY),同時 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 使其在屏幕上向上移動
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 設置為網格容器。
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)