อินสแตนซ์ DragDetector ช่วยอำนวยความสะดวกและกระตุ้นการโต้ตอบกับวัตถุ 3D ในประสบการณ์ เช่น การเปิดประตูและลิ้นชัก การเลื่อนชิ้นส่วนไปมา การจับและโยนลูกบอลโบว์ลิ่ง การดึงกลับและยิงหนังยาง และอื่นๆ อีกมากมาย ฟีเจอร์หลักประกอบด้วย:
วาง DragDetector ไว้ใต้ BasePart หรือ Model เพื่อ ทำให้สามารถลากได้ ผ่านการป้อนข้อมูลทั้งหมด (เมาส์ การสัมผัส จอยสติ๊ก และ VR) โดยไม่ต้องเขียนโค้ดซักบรรทัดเดียว
เลือกจากหลาย สไตล์การลาก กำหนดว่าวัตถุ ตอบสนองต่อการเคลื่อนไหว อย่างไร และสามารถกำหนด ข้อจำกัดของแกนหรือลักษณะการเคลื่อนไหว ได้ตามต้องการ
สคริปต์สามารถ ตอบสนองต่อการจัดการวัตถุที่ถูกลาก เพื่อควบคุม UI หรือทำการตัดสินใจเชิงตรรกะ เช่น การปรับระดับแสงในห้องตามสวิตช์ไฟแบบเลื่อน
ผู้เล่นสามารถจัดการส่วนที่ยึดและโมเดลและมันจะอยู่ในตำแหน่งที่คุณวางเมื่อปล่อย
DragDetectors สามารถใช้งานใน Studio ได้ตราบเท่าที่คุณ ไม่ได้ ใช้เครื่องมือ เลือก, เคลื่อนที่, ปรับขนาด, หรือ หมุน ทำให้ทดสอบและปรับปรุงวัตถุที่สามารถลากได้ง่ายขึ้นขณะแก้ไข
ทำให้วัตถุสามารถลากได้
ในการทำให้ชิ้นส่วนหรือโมเดลใดๆ สามารถลากได้ เพียงแค่เพิ่ม DragDetector เป็นทายาทโดยตรง
จากเมนู ให้แทรก DragDetector

โดยค่าเริ่มต้น วัตถุจะสามารถลากได้ในพื้นดิน แต่คุณสามารถปรับแต่ง DragStyle ของมัน กำหนดว่าวัตถุจะ ตอบสนองต่อการเคลื่อนไหว อย่างไร และสามารถกำหนด ข้อจำกัดของแกนหรือลักษณะการเคลื่อนไหว ได้ตามต้องการ
ปรับแต่งตัวตรวจจับการลาก
สไตล์การลาก
DragDetectors จะทำการแมพการเคลื่อนไหวของเคอร์เซอร์ไปยังเส้นและระนาบเสมือนเพื่อคำนวณการเคลื่อนไหว 3D ที่เสนอ ผ่านคุณสมบัติ DragStyle คุณสามารถเลือกจากการแมพต่างๆ ตามความต้องการของคุณ เพื่อให้ได้ประสิทธิภาพที่ดีที่สุด ตัวอย่างเช่น TranslatePlane จะสร้างการเคลื่อนที่ในระนาบเสมือน ในขณะที่ RotateAxis จะสร้างการหมุนรอบแกนเสมือน
| การตั้งค่า | คำอธิบาย |
|---|---|
| TranslateLine | การเคลื่อนไหว 1D ตามแกน Axis ของตัวตรวจจับ โดยค่าเริ่มต้นคือแกน Y ของโลก |
| TranslatePlane | การเคลื่อนไหว 2D ในระนาบที่ตั้งฉากกับ Axis ของตัวตรวจจับ โดยค่าเริ่มต้นคือระนาบ XZ ของโลก |
| TranslatePlaneOrLine | การเคลื่อนไหว 2D ในระนาบที่ตั้งฉากกับ Axis ของตัวตรวจจับ และเมื่อ ที่ปรับแต่ง ทำงานอยู่ จะมีการเคลื่อนไหว 1D ตามแกน Axis ของตัวตรวจจับ |
| TranslateLineOrPlane | การเคลื่อนไหว 1D ตามแกน Axis ของตัวตรวจจับ และเมื่อ ที่ปรับแต่ง ทำงานอยู่ จะมีการเคลื่อนไหว 2D ในระนาบที่ตั้งฉากกับ Axis ของตัวตรวจจับ |
| TranslateViewPlane | การเคลื่อนไหว 2D ในระนาบที่มีความตั้งฉากกับการมองของกล้อง ในโหมดนี้ ระนาบจะถูกปรับปรุงอย่างต่อเนื่องแม้ในขณะที่ดึงและจะเผชิญหน้ากับมุมมองปัจจุบันของกล้องเสมอ |
| RotateAxis | การหมุนรอบแกน Axis ของตัวตรวจจับ โดยค่าเริ่มต้นคือแกน Y ของโลก |
| RotateTrackball | การหมุนแบบ Trackball ซึ่งสามารถปรับแต่งเพิ่มเติมผ่าน TrackballRadialPullFactor และ TrackballRollFactor |
| BestForDevice | TranslatePlaneOrLine สำหรับเมาส์และจอยสติ๊ก; TranslatePlane สำหรับการสัมผัส; 6DOF สำหรับ VR |
| 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 จะยังคงได้รับการอัปเดตและคุณสามารถ ตอบสนองต่อการจัดการการลาก ตามที่ต้องการได้ | (เช่นเดียวกับที่ยึด) |
ข้อจำกัดของแกนและการเคลื่อนไหว
โดยค่าเริ่มต้น ไม่มีข้อจำกัดในการเคลื่อนไหว 3D นอกจากข้อจำกัดที่เกิดจาก DragStyle ถ้าจำเป็นสามารถตั้งค่าข้อจำกัดขั้นต่ำและสูงสุดทั้งในแง่ของการแปลและการหมุน อย่างไรก็ตาม โปรดทราบว่านี่ไม่ใช่ข้อบังคับ; มันเพียงแต่จะขัดขวางความพยายามของตัวตรวจจับการดึงเพื่อสร้างการเคลื่อนไหวให้อยู่ภายในขอบเขต
| คุณสมบัติ | คำอธิบาย | ค่าเริ่มต้น |
|---|---|---|
| ข้อจำกัดในการแปลการลากในแต่ละมิติ หาก 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 บางโหมดอนุญาตให้ผู้ใช้กดปุ่ม/คีย์ ปรับแต่ง เพื่อจัดการวัตถุที่ลากในรูปแบบที่แตกต่างกัน โดยค่าเริ่มต้น คีย์ปรับแต่งคือ LeftControl บน PC, ButtonR1 บนจอยสติ๊ก หรือ ButtonL2 บน VR คุณสามารถกำหนดคีย์ปรับแต่งเหล่านี้ผ่านคุณสมบัติ KeyboardModeSwitchKeyCode, GamepadModeSwitchKeyCode หรือ VRSwitchKeyCode ของอินสแตนซ์ตัวตรวจจับการลาก
การทำซ้ำ
เมื่อคุณสมบัติ RunLocally เป็น false (ค่าเริ่มต้น) คลient จะตีความการป้อนข้อมูลทั้งหมดเพื่อสร้างข้อมูลที่ส่งไปยังเซิร์ฟเวอร์เพื่อทำการลาก ในโหมดนี้ สัญญาณอีเวนต์ที่กำหนดเองและฟังก์ชันที่ลงทะเบียนทั้งหมดต้องอยู่ใน 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 - สไตล์ Scripted DragStyle
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()
ตัวอย่างการใช้งาน
วัตถุทางกายภาพที่ไม่ยึด
การใช้งานพื้นฐานของตัวตรวจจับการลากคือเกมสมดุลหอคอยที่ผู้เล่นต้องระมัดระวังในการดึงชิ้นส่วนออกและพยายามทำให้หอคอยตั้งตรง ในโครงสร้างหอคอยด้านล่าง ชิ้นส่วนแต่ละชิ้นมี DragDetector เป็นลูกซึ่งมีค่าเริ่มต้น DragStyle เป็น TranslatePlane ดังนั้นผู้เล่นสามารถดึงชิ้นส่วนไปข้างนอกแต่ไม่สามารถดึงขึ้นหรือดึงลงได้
โมเดลที่ยึดที่มีชิ้นส่วนปรับได้
คุณสามารถสร้างและแบ่งปันโมเดลที่ยึดอยู่เป็นหลัก ที่มีชิ้นส่วน/โมเดลที่ลูกอยู่ด้านล่างซึ่งผู้เล่นสามารถลากได้ ตัวอย่างเช่น โต๊ะต่อไปนี้มีลิ้นชักสองลิ้นชักที่ผู้เล่นสามารถเปิดเพื่อดูสิ่งที่อยู่ภายใน
ตัวตรวจจับการลากและข้อบังคับ
คุณสามารถรวมตัวตรวจจับการลากเข้ากับ Constraints เช่น ตัวละครหุ่นกระบอก ในการตั้งค่าต่อไปนี้ที่จับการควบคุมจะถูกยึด ชิ้นส่วนของร่างกายจะไม่ถูกยึด และข้อบังคับจะยึดหุ่นกระบอกไว้ด้วยกัน โดยการเคลื่อนไหวที่จับด้วย DragStyle ที่ TranslateViewPlane จะทำให้หุ่นกระบอกเต้นรำ และชิ้นส่วนร่างกายแต่ละชิ้นยังสามารถเคลื่อนที่ด้วยตัวตรวจจับการลากได้ทั้งหมดในขณะที่โมเดลเก็บความสมบูรณ์ของมันไว้
UI 3D
UI 3D สามารถทำได้ง่ายโดยการใช้ตัวตรวจจับการลาก เช่น การปรับความสว่างของ SpotLight ตามสวิตช์ไฟแบบเลื่อน คุณยังสามารถตรวจสอบแกน X และ Z แยกกันเพื่อควบคุมสองแง่มุมที่แตกต่างกันของ UI 3D เช่น ขนาด, ความเร็ว, และสี ของ ParticleEmitter.
DragDetector - UI 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)