ตัวตรวจจับการลาก 3D

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

อินสแตนซ์ DragDetector ช่วยอำนวยความสะดวกและกระตุ้นการโต้ตอบกับวัตถุ 3D ในเกม เช่น การเปิดประตูและลิ้นชัก การเลื่อนชิ้นส่วนไปรอบ ๆ การจับและโยนลูกโบว์ลิ่ง การดึงกลับและยิงหนังสติ๊ก และอื่น ๆ อีกมากมาย คุณสมบัติหลักประกอบด้วย:

ทำให้วัตถุสามารถลากได้

เพื่อทำให้ชิ้นส่วนหรือโมเดลใด ๆ สามารถลากได้ เพียงแค่เพิ่ม DragDetector เป็นลูกหลานโดยตรง

  1. ในหน้าต่าง Explorer ให้ชี้ไปที่ Part, MeshPart, หรือ Model และคลิกที่ปุ่ม ⊕ เมนูบริบทจะแสดงขึ้น

  2. จากเมนู ให้แทรก DragDetector

  3. โดยค่าเริ่มต้น วัตถุจะสามารถลากได้ในระนาบพื้น แต่คุณสามารถปรับแต่ง 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
BestForDeviceTranslatePlaneOrLine สำหรับเมาส์และเกมแพด; 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 หากจำเป็น คุณสามารถใช้ขีดจำกัดขั้นต่ำและสูงสุดสำหรับทั้งการแปลและการหมุน อย่างไรก็ตาม โปรดทราบว่าขีดจำกัดเหล่านี้ ไม่ใช่ ข้อจำกัด; มันเพียงแค่ขัดขวางความพยายามของตัวตรวจจับการลากในการสร้างการเคลื่อนไหวเพื่อให้ยังคงอยู่ภายในขีดจำกัด

คุณสมบัติคำอธิบายค่าเริ่มต้น
MinDragTranslation
MaxDragTranslation
ขีดจำกัดการแปลการลากในแต่ละมิติ หาก MaxDragTranslation มากกว่า MinDragTranslation การแปลจะถูกจำกัดภายในช่วงนั้น(0, 0, 0)
MinDragAngle
MaxDragAngle
มีความเกี่ยวข้องเฉพาะเมื่อ 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 (ค่าเริ่มต้น) ไคลเอนต์จะตีความการป้อนข้อมูลทั้งหมดเพื่อผลิตข้อมูลที่ส่งไปยังเซิร์ฟเวอร์เพื่อทำการลาก ในโหมดนี้ สัญญาณเหตุการณ์ที่กำหนดเองทั้งหมดและฟังก์ชันที่ลงทะเบียนต้องอยู่ใน 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)
-- ยกเว้นวัตถุที่ถูกลากจากการตรวจจับ raycast
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 ทำให้หุ่นกระบอกเต้นรำ และส่วนต่าง ๆ ของร่างกายยังสามารถเคลื่อนที่ได้ด้วยตัวตรวจจับการลาก ในขณะที่โมเดลยังคงรักษาความสมบูรณ์

อินเทอร์เฟซผู้ใช้ 3D

อินเทอร์เฟซผู้ใช้ 3D สามารถทำได้ง่าย ๆ ผ่านตัวตรวจจับการลาก เช่น การปรับความสว่างของ SpotLight ตามสวิตช์เลื่อนที่ปรับได้ คุณยังสามารถตรวจจับแกน X และ Z แยกกันเพื่อควบคุมสองแง่มุมที่แตกต่างกันของอินเทอร์เฟซผู้ใช้ 3D เช่น Size, Speed, และ Color ของ ParticleEmitter

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)
©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ