DragDetector インスタンスは、体験の中で 3D オブジェクトとの相互作用を促進し、奨励します。たとえば、ドアや引き出しを開けたり、部品をスライドさせたり、ボウリングのボールをつかんで投げたり、スリングショットを引いて発射したりすることができます。主な機能は以下の通りです。
任意の BasePart または Model の下に DragDetector を配置することで、ドラッグ可能にすることができ、マウス、タッチ、ゲームパッド、VR など、すべての入力に対応し、コードの記述なしで実現できます。
複数のドラッグスタイルから選択し、オブジェクトが動きにどのように反応するかを定義し、オプションで軸または動きの制限を適用できます。
スクリプトは、ドラッグされたオブジェクトの操作に反応することができ、スライドする壁スイッチの調光に基づいて部屋の明るさを調整するなどの論理的な決定を促進できます。
プレイヤーは、固定された部品やモデルを操作でき、リリース時にその場に固定されます。
DragDetectors は、Select、Move、Scale、または Rotate ツールを使用していない限り、Studio で機能します。これにより、ドラッグ可能なオブジェクトを編集しながらテストしやすくなります。
オブジェクトをドラッグ可能にする
任意の部品やモデルをドラッグ可能にするには、単に DragDetector を直接の子孫として追加します。
メニューから DragDetector を挿入します。

デフォルトでは、オブジェクトは地面の平面内でドラッグ可能になりますが、DragStyle をカスタマイズし、動きにどのように反応するかを定義し、オプションで軸または動きの制限を適用できます。
ドラッグ検出器をカスタマイズする
ドラッグスタイル
DragDetectors は、カーソルの動きを仮想の線や平面にマッピングし、提案された 3D の動きを計算します。DragStyle プロパティを通じて、ニーズに合ったさまざまなマッピングから選択できます。たとえば、TranslatePlane は仮想平面内での移動を生成し、RotateAxis は仮想軸の周りの回転を生成します。
| 設定 | 説明 |
|---|---|
| TranslateLine | デテクタの Axis に沿った1Dの動き。デフォルトはワールドの Y 軸です。 |
| TranslatePlane | デテクタの Axis に垂直な平面内での2Dの動き。デフォルトはワールドの XZ 平面です。 |
| TranslatePlaneOrLine | デテクタの Axis に垂直な平面内での2Dの動きと、モディファイアがアクティブな場合はデテクタの Axis に沿った1Dの動き。 |
| TranslateLineOrPlane | デテクタの Axis に沿った1Dの動きと、モディファイアがアクティブな場合はデテクタの Axis に垂直な平面内での2Dの動き。 |
| TranslateViewPlane | カメラの視点に垂直な平面内での2Dの動き。このモードでは、平面はドラッグ中も常に更新され、カメラの現在の視点を常に向きます。 |
| RotateAxis | デテクタの Axis の周りの回転。デフォルトはワールドの Y 軸です。 |
| RotateTrackball | トラックボール回転。さらに、TrackballRadialPullFactor および TrackballRollFactor プロパティを通じてカスタマイズされます。 |
| BestForDevice | マウスおよびゲームパッドには TranslatePlaneOrLine、タッチには TranslatePlane、VRには 6DOF。 |
| Scriptable | カスタム関数を通じて提供された SetDragStyleFunction() によって、希望の動きを計算します。 |
ドラッグ方向
デフォルトでは、3D の動きと関連する DragStyle はワールド空間にマッピングされます。ただし、調整可能な部品を持つモデルにドラッグ検出器を組み込む場合などでは、ReferenceInstance、Orientation、または Axis を変更することがあります。
| プロパティ | 説明 | デフォルト |
|---|---|---|
| ReferenceInstance | ドラッグ検出器の基準フレームを提供するピボットを持つインスタンス。 DragFrameは、この基準フレームに対して相対的に表現され、GetReferenceFrame() を通じて取得できます。基準フレームが nil の場合、翻訳はワールド空間内の Axis プロパティが示す方向(またはその平面)になります。 | nil |
| Orientation | 基準フレームに対する動きの軸のYXZ回転を指定します(基準フレーム自体の向きは変更しません)。線形翻訳と軸回転はこの再配置されたY軸上で行われ、平面内での翻訳は XZ 平面になります。この値を変更すると、 Axis が自動的に更新され、逆も同様です。 | (0, 0, 0) |
| Axis | 基準フレームに対して表現される主な動きの軸。この値を変更すると Orientation が自動的に更新され、逆も同様です。 | (0, 1, 0) |
動きへの反応
ResponseStyle プロパティは、オブジェクトが提案された動きにどのように反応するかを指定します。これはオブジェクトが Anchored かどうかによります。
| 設定 | アンカーありの動作 | アンカーなしの動作 |
|---|---|---|
| Geometric | 実行中の体験とStudio編集モードの両方で、固定されたオブジェクトの位置/向きは提案された動きを正確に反映するように更新されます。 | アンカーなしのオブジェクトでは、動作は固定されたオブジェクトと同じですが、実行中の体験では、ドラッグの開始時にオブジェクトがアンカーされ、ドラッグを解除するとアンカーなしに戻ります。 |
| Physical | 固定されたオブジェクトはGeometricの動作がデフォルトになります。これは力の影響を受けないためです。 | アンカーなしのオブジェクトは、提案された動きによって与えられた位置や向きに持っていくことを試みる制約力によって移動されます。 |
| Custom | オブジェクトは全く移動しませんが、DragFrame は依然として更新され、ドラッグ操作に反応することができます。 | (固定されたオブジェクトと同じ) |
軸と移動制限
デフォルトでは、DragStyle の固有の制限を除いて、3D の動きには制限がありません。必要に応じて、移動と回転の両方に最小および最大の制限を適用できます。ただし、これらは制約ではなく、制限の範囲内に保つためにドラッグ検出器の動き生成を妨げるだけです。
| プロパティ | 説明 | デフォルト |
|---|---|---|
| 各次元のドラッグ移動を制限します。MaxDragTranslation が MinDragTranslation より大きい場合、移動はその範囲内に制限されます。 | (0, 0, 0) | |
| DragStyle が RotateAxis に設定されている場合のみ関連します。MaxDragAngle が MinDragAngle より大きい場合、回転はその範囲内に制限されます。 | 0 |
ドラッグ許可
プレイヤーが特定のドラッグ検出器インスタンスと相互作用する権限は、PermissionPolicy プロパティによって指定できます。デフォルトでは Enum.DragDetectorPermissionPolicy.Everybody に設定されており、コードサンプルに示すようにスクリプトされた権限制御をサポートするように変更することもできます。
| 設定 | 説明 |
|---|---|
| Nobody | プレイヤーは DragDetector と相互作用できません。 |
| Everybody | すべてのプレイヤーが DragDetector と相互作用できます。 |
| Scriptable | プレイヤーのドラッグ許可は、SetPermissionPolicyFunction() を介して登録された関数によって決定されます。この設定では、関数の登録に失敗するか、無効な結果が返されると、すべてのプレイヤーがドラッグできなくなります。 |
DragDetector - スクリプトによるドラッグ許可
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)
物理応答
ドラッグの 応答スタイル が Physical に設定されており、固定されていないオブジェクトに適用される場合、そのオブジェクトは、提案された動きによって与えられた位置/向きに移動しようとする制約力によって移動します。以下のプロパティを通じて物理的応答をさらにカスタマイズできます。
| プロパティ | 説明 | デフォルト |
|---|---|---|
| ApplyAtCenterOfMass | false の場合、ドラッグ力はユーザーがクリックした点に適用されます。true の場合、力はオブジェクトの重心に適用されます。 | false |
| MaxForce | オブジェクトが目標に到達するために適用される最大力。 | 10000000 |
| MaxTorque | オブジェクトが目標に到達するために適用される最大トルク。 | 10000 |
| Responsiveness | 値が大きいほど、オブジェクトは目標により迅速に到達します。 | 10 |
修飾子入力
一部の DragStyle モードでは、ユーザーが 修飾子 キー/ボタンを押し続けて、ドラッグされたオブジェクトをさまざまに操作できます。デフォルトでは、修飾子は PC では LeftControl、ゲームパッドでは ButtonR1、VR では ButtonL2 です。ドラッグ検出器インスタンスの KeyboardModeSwitchKeyCode、GamepadModeSwitchKeyCode、または VRSwitchKeyCode プロパティを介して、これらの修飾子をカスタマイズできます。
レプリケーション
RunLocally プロパティが false (デフォルト) の場合、クライアントはすべての入力を解釈してデータを生成し、それをサーバーに送信してドラッグを実行します。このモードでは、すべてのカスタムイベント信号と登録された関数はサーバーの Scripts に存在する必要があります。
RunLocally プロパティが true の場合、イベントはサーバーにレプリケートされません。すべてのカスタムイベント信号と登録された関数はクライアントの LocalScripts に存在し、必要な変更をサーバーに伝播するために リモートイベント を使用する必要があります。
クリックおよびドラッグ操作へのスクリプト応答
イベント信号、プロパティ変更、Scriptable ドラッグスタイル、およびカスタム関数を通じて、スクリプトはドラッグされたオブジェクトの操作に応答して UI を駆動したり、部屋のスライドする壁のスイッチ調光器に基づいて明るさの調整などの論理的決定を行うことができます。
イベント信号
以下のイベント信号を通じて、ユーザーがオブジェクトのドラッグを開始、継続、および終了するときに検出できます。
| イベント | 説明 |
|---|---|
| DragStart | ユーザーがオブジェクトのドラッグを開始したときに発火します。 |
| DragContinue | ユーザーが DragStart が開始された後、オブジェクトのドラッグを続けるときに発火します。 |
| DragEnd | ユーザーがオブジェクトのドラッグを停止したときに発火します。 |
DragDetector - イベント信号
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)
ドラッグフレームの変更
イベント信号に加えて、検出器の DragFrame の変更を直接監視できます。
DragDetector - DragFrame の変更
local dragDetector = script.Parent.DragDetector
dragDetector:GetPropertyChangedSignal("DragFrame"):Connect(function()
local currentDragTranslation = dragDetector.DragFrame.Position
print(currentDragTranslation)
end)
スクリプトによるドラッグスタイル
検出器の DragStyle を Scriptable に設定すると、Ray を受け取り、ワールド空間の CFrame を返す自分の関数を提供できます。検出器は、ドラッグされたオブジェクトがそのカスタム位置/向きに移動するように動きを調整します。
DragDetector - スクリプトによるドラッグスタイル
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)
-- ドラッグされたオブジェクトをレイキャスト検出から除外する
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)
カスタム制約関数
ドラッグ検出器には、グリッドやスナッピングに関する組み込みの動きのルールはありませんが、ドラッグフレームが適用される前に検出器の DragFrame を編集するカスタム制約関数を登録できます。たとえば、ポジションをグリッドのインクリメントの倍数に丸めることで動きをグリッド上に維持したり、チェスのゲームのルールに従ってそれぞれのピースの動きをシミュレートしたりできます。
DragDetector - カスタム制約関数
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)
-- 適用可能な場合、 connection:Disconnect() を呼び出して制約関数を削除します。
使用例
固定されていない物理オブジェクト
ドラッグ検出器の基本的な実装は、プレイヤーが慎重にピースを取り除き、塔を立てておくバランスゲームです。以下の塔の構造では、それぞれのピースがデフォルトの DragStyle として TranslatePlane を持つ子 DragDetector を持っているため、プレイヤーはピースを外側に引っ張ることができますが、上下には引っ張ることができません。
調整可能な部分を持つ固定モデル
主に固定されているが、プレイヤーがドラッグできる 1 つ以上の子パーツ/モデルを持つモデルを簡単に作成して共有できます。たとえば、以下のデスクには、プレイヤーが中を調べるために開けられる 2 つの引き出しがあります。
ドラッグ検出器と制約
ドラッグ検出器を Constraints と組み合わせることができます。たとえば、マリオネットの人形のように。以下の設定では、制御ハンドルは固定されており、胴体部分は固定されておらず、制約がマリオネットを保持しています。TranslateViewPlane DragStyle を使用してハンドルを移動させると、マリオネットが踊り、個々の胴体部分もドラッグ検出器で移動することができ、モデルの整合性を維持します。
3D ユーザーインターフェース
3D ユーザーインターフェースは、ドラッグ検出器を使用して簡単に実現でき、スライドスイッチの調光器に基づいて SpotLight の明るさを調整することができます。また、X 軸と Z 軸を個別に検出して、Size、Speed、および Color のように、3D ユーザーインターフェースの 2 つの異なる側面を制御できます。
DragDetector - 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
-- ドラッグ検出器の X 要素に基づいてパーティクルのサイズと速度を調整
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)
-- ドラッグ検出器の Z 要素に基づいてパーティクルの色を調整
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)