การชน

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

การชนเกิดขึ้นเมื่อวัตถุ 3 มิติสองชิ้นสัมผัสกันในโลก 3 มิติ สำหรับการจัดการการชนที่กำหนดเอง BasePart มีชุดของ เหตุการณ์การชน และเทคนิค การกรองการชน เพื่อให้คุณสามารถควบคุมว่าวัตถุทางกายภาพใดชนกับวัตถุอื่น

เหตุการณ์การชน

เหตุการณ์การชน เกิดขึ้น เมื่อ BaseParts สองชิ้นสัมผัสกันหรือหยุดสัมผัสกันในโลก 3 มิติ คุณสามารถตรวจจับการชนเหล่านี้ได้ผ่าน Touched และ TouchEnded ซึ่งเกิดขึ้นไม่ว่าจะมีค่า CanCollide ของแต่ละชิ้นส่วนเป็นอย่างไร เมื่อพิจารณาการจัดการการชนบนชิ้นส่วน ให้สังเกตสิ่งต่อไปนี้:

  • ค่า CanTouch ของชิ้นส่วนจะกำหนดว่ามันจะกระตุ้นเหตุการณ์การชนหรือไม่ หากตั้งค่าเป็น false จะไม่มีการเรียกใช้งาน Touched หรือ TouchEnded
  • ค่า CanCollide ของชิ้นส่วนจะมีผลต่อว่ามันจะ ชนทางกายภาพ กับชิ้นส่วนอื่นหรือไม่และทำให้เกิดแรงกระทำต่อพวกมัน แม้ว่าจะปิดการใช้งาน CanCollide สำหรับชิ้นส่วน คุณยังสามารถตรวจจับการสัมผัสและการไม่สัมผัสได้ผ่านเหตุการณ์ Touched และ TouchEnded
  • เหตุการณ์ Touched และ TouchEnded จะเกิดขึ้นเฉพาะจากการเคลื่อนไหว ทางกายภาพ ไม่ใช่จากการเปลี่ยนแปลง Position หรือ CFrame ที่ทำให้ชิ้นส่วนตัดกันหรือหยุดตัดกันกับชิ้นส่วนอื่น
  • คลาส Terrain ระดับสูงสุดสืบทอดมาจาก BasePart ดังนั้นคุณสามารถกำหนด กลุ่มการชน ให้กับ Terrain เพื่อกำหนดว่าวัตถุ BaseParts อื่นจะชนกับ Terrain ว็อกเซลหรือไม่

Touched

เหตุการณ์ Touched จะเกิดขึ้นเมื่อ BasePart สัมผัสกับอีกชิ้นหนึ่ง หรือกับว็อกเซล Terrain มันจะเกิดขึ้นเฉพาะจาก การจำลองทางกายภาพ และจะไม่เกิดขึ้นเมื่อค่า Position หรือ CFrame ของชิ้นส่วนถูกตั้งค่าอย่างชัดเจนให้ตัดกันกับชิ้นส่วนอื่นหรือว็อกเซล

รูปแบบโค้ดต่อไปนี้แสดงให้เห็นว่าเหตุการณ์ Touched สามารถเชื่อมต่อกับฟังก์ชัน onTouched() ที่กำหนดเองได้อย่างไร โปรดทราบว่าเหตุการณ์จะส่งอาร์กิวเมนต์ otherPart ไปยังฟังก์ชัน ซึ่งบ่งบอกถึงชิ้นส่วนอื่นที่เกี่ยวข้องในการชน

การชนของชิ้นส่วน
local part = workspace.Part
local function onTouched(otherPart)
print(part.Name .. " ชนกับ " .. otherPart.Name)
end
part.Touched:Connect(onTouched)

โปรดทราบว่าเหตุการณ์ Touched อาจเกิดขึ้นหลายครั้งในระยะเวลาสั้น ๆ ขึ้นอยู่กับการชนทางกายภาพที่ละเอียดอ่อน เช่น เมื่อวัตถุที่เคลื่อนที่ "ตั้งอยู่" ในตำแหน่งที่พักหรือเมื่อการชนเกี่ยวข้องกับ โมเดลหลายชิ้นส่วน เพื่อหลีกเลี่ยงการกระตุ้นเหตุการณ์ Touched มากเกินไป คุณสามารถใช้ระบบดีบาวน์ซ์ง่าย ๆ ที่บังคับใช้ "ระยะเวลาพัก" ผ่าน แอตทริบิวต์ ของอินสแตนซ์

การชนของชิ้นส่วนพร้อมระยะเวลาพัก
local part = workspace.Part
local COOLDOWN_TIME = 1
local function onTouched(otherPart)
if not part:GetAttribute("Touched") then
print(part.Name .. " ชนกับ " .. otherPart.Name)
part:SetAttribute("Touched", true) -- ตั้งค่าแอตทริบิวต์เป็น true
task.wait(COOLDOWN_TIME) -- รอระยะเวลาพัก
part:SetAttribute("Touched", false) -- รีเซ็ตแอตทริบิวต์
end
end
part.Touched:Connect(onTouched)

TouchEnded

เหตุการณ์ TouchEnded จะเกิดขึ้นเมื่อขอบเขตการชนทั้งหมดของ BasePart ออกจากขอบเขตของ BasePart อื่นหรือว็อกเซล Terrain ที่เต็ม มันจะเกิดขึ้นเฉพาะจาก การจำลองทางกายภาพ และจะไม่เกิดขึ้นเมื่อค่า Position หรือ CFrame ของชิ้นส่วนถูกตั้งค่าอย่างชัดเจนให้หยุดตัดกันกับชิ้นส่วนอื่นหรือว็อกเซล

รูปแบบโค้ดต่อไปนี้แสดงให้เห็นว่าเหตุการณ์ TouchEnded สามารถเชื่อมต่อกับฟังก์ชัน onTouchEnded() ที่กำหนดเองได้อย่างไร เช่นเดียวกับ Touched เหตุการณ์จะส่งอาร์กิวเมนต์ otherPart ไปยังฟังก์ชัน ซึ่งบ่งบอกถึงชิ้นส่วนอื่นที่เกี่ยวข้อง

การตรวจจับการไม่ชน
local part = workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " ไม่ได้สัมผัสกับ " .. otherPart.Name อีกต่อไป)
end
part.TouchEnded:Connect(onTouchEnded)

การกรองการชน

การกรองการชน กำหนด ว่าวัตถุทางกายภาพใดชนกับวัตถุอื่น คุณสามารถกำหนดการกรองสำหรับวัตถุจำนวนมากผ่าน กลุ่มการชน หรือคุณสามารถควบคุมการชนในระดับ ชิ้นส่วนต่อชิ้นส่วน ด้วยอินสแตนซ์ NoCollisionConstraint

กลุ่มการชน

กลุ่มการชน อนุญาต ให้คุณกำหนด BaseParts ให้กับกลุ่มเฉพาะและระบุว่าพวกมันจะชนกับกลุ่มอื่นหรือไม่ ชิ้นส่วนภายในกลุ่มที่ไม่ชนจะผ่านกันไปโดยสมบูรณ์ แม้ว่าชิ้นส่วนทั้งสองจะมีค่า CanCollide ตั้งเป็น true กลุ่มการชนจะถูกสร้างและกำหนดค่าบนพื้นฐานของ Workspace หรือ WorldModel

ในวิดีโอด้านบน วัตถุหมุนอยู่ในกลุ่มการชนที่แตกต่างกันทำให้พวกมันชนกับวัตถุที่มีสีอื่นแต่ไม่ชนกับวัตถุที่มีสีเดียวกัน

คุณสามารถตั้งค่ากลุ่มการชนได้อย่างง่ายดายผ่านตัวแก้ไข กลุ่มการชน ของ Studio ซึ่งสามารถเข้าถึงได้ผ่านเมนู หน้าต่าง ⟩ 3D

ลงทะเบียนกลุ่ม

Workspace เก็บสถานะการกำหนดค่าของกลุ่มการชนของตนเอง นอกจากนี้ WorldModel ใด ๆ สามารถเลือกใช้กลุ่มการชนของตนเองสำหรับการค้นหา

ตัวแก้ไขรวมถึงกลุ่มการชน เริ่มต้น หนึ่งกลุ่มซึ่งไม่สามารถเปลี่ยนชื่อหรือถูกลบได้ BaseParts ทั้งหมดจะอยู่ในกลุ่มเริ่มต้นนี้โดยอัตโนมัติ เว้นแต่จะถูกกำหนดให้กับกลุ่มอื่น ซึ่งหมายความว่าพวกมันจะชนกับวัตถุอื่นทั้งหมดในกลุ่ม เริ่มต้น

ในการสร้างกลุ่มการชนใหม่:

  1. โดยค่าเริ่มต้น กลุ่มจะถูกลงทะเบียนใน Workspace แต่ถ้าคุณมี WorldModel อย่างน้อยหนึ่งตัวในสถานที่ของคุณ เมนูแบบเลื่อนจะปรากฏที่ด้านบนของตัวแก้ไขกลุ่มการชน ใช้เมนูแบบเลื่อนเพื่อกำหนดกลุ่มการชนใน WorldModel ที่แตกต่างกัน

    Workspace แสดงให้เห็นว่าเป็นโลกที่ใช้งานอยู่ในตัวแก้ไขกลุ่มการชน

    สำหรับ WorldModel ใด ๆ คุณสามารถเปิดใช้งาน ใช้กลุ่มการชนของ Workspace เพื่อให้มันใช้กลุ่มการชนของ Workspace สำหรับการค้นหาของมัน

    ช่องทำเครื่องหมายแสดงให้เห็นเพื่อเปิดใช้งานคุณสมบัติ UseWorkspaceCollisionGroups ของ WorldModel
  2. คลิกปุ่ม เพิ่มกลุ่ม ที่ด้านบนของแผงตัวแก้ไข ป้อนชื่อกลุ่มใหม่และกด Enter กลุ่มใหม่จะปรากฏในทั้งสองคอลัมน์ของมุมมองรายการ หรือในทั้งคอลัมน์ซ้ายและแถวด้านบนของมุมมองตาราง

    กลุ่มใหม่ที่เพิ่มเข้ามาในตัวแก้ไขกลุ่มการชนในมุมมองรายการ
  3. ทำซ้ำกระบวนการหากจำเป็น โดยเลือกชื่อที่ไม่ซ้ำกันและมีความหมายสำหรับแต่ละกลุ่ม โปรดทราบว่าคุณสามารถเปลี่ยนชื่อกลุ่มในระหว่างการพัฒนาได้โดยการคลิกในฟิลด์ของมัน หรือโดยการเลือกมันและคลิกปุ่ม เปลี่ยนชื่อ

    ปุ่มและฟิลด์ที่แสดงเพื่อเปลี่ยนชื่อกลุ่มในตัวแก้ไขกลุ่มการชน

กำหนดค่าการชนของกลุ่ม

ภายใต้การกำหนดค่าเริ่มต้น วัตถุในทุกกลุ่มจะชนกัน หากต้องการป้องกันไม่ให้วัตถุในกลุ่มหนึ่งชนกับวัตถุในกลุ่มอื่น ให้ ยกเลิกการเลือก ช่องในแถว/คอลัมน์ที่เกี่ยวข้อง

ในตัวอย่างต่อไปนี้ วัตถุในกลุ่ม Cubes จะ ไม่ ชนกับวัตถุในกลุ่ม Doors

กลุ่มที่กำหนดค่าในมุมมองรายการของตัวแก้ไขกลุ่มการชน

กำหนดวัตถุให้กับกลุ่ม

ในการกำหนดวัตถุให้กับกลุ่มที่คุณได้ ลงทะเบียน ผ่านตัวแก้ไข Studio:

  1. เลือก BaseParts หนึ่งชิ้นหรือมากกว่าที่มีคุณสมบัติเป็นส่วนหนึ่งของกลุ่มการชน

  2. กำหนดให้พวกมันอยู่ในกลุ่มโดยการคลิกปุ่ม ⊕ สำหรับแถวของมัน วัตถุสามารถอยู่ในกลุ่มการชนได้เพียงกลุ่มเดียวในแต่ละครั้ง ดังนั้นการวางพวกมันในกลุ่มใหม่จะทำให้พวกมันถูกลบออกจากกลุ่มปัจจุบัน

    ปุ่มบวกที่แสดงในตัวแก้ไขกลุ่มการชนสำหรับการเพิ่มชิ้นส่วนที่เลือกไปยังกลุ่ม

    เมื่อกำหนดแล้ว กลุ่มใหม่จะสะท้อนอยู่ภายใต้คุณสมบัติ CollisionGroup ของวัตถุ

    กลุ่มการชนที่เลือกแสดงให้เห็นว่าเป็นคุณสมบัติ CollisionGroup ของชิ้นส่วน

กลุ่ม StudioSelectable

เครื่องมือใน Studio ใช้ระบบการกรองการชนเพื่อตัดสินใจว่าวัตถุใดเป็นผู้สมัครสำหรับการเลือกเมื่อคลิกในมุมมอง 3 มิติ วัตถุที่มีกลุ่มการชนที่กำหนดไม่ ชน กับ StudioSelectable จะถูกละเว้น

ตัวอย่างเช่น หากคุณมีจุดตรวจในเกมแข่งรถที่พื้นที่มีประสิทธิภาพถูกกำหนดโดยชิ้นส่วนโปร่งใสขนาดใหญ่ คุณสามารถกำหนดให้พวกมันอยู่ในกลุ่มการชน Checkpoints และจากนั้นทำให้กลุ่มนั้นไม่ชนกับ StudioSelectable เพื่อไม่ให้มันขัดขวางเมื่อคุณแก้ไขรูปทรงพื้นฐานของแผนที่

กลุ่ม Checkpoints ที่กำหนดให้ไม่ชนกับกลุ่ม StudioSelectable

สำหรับโค้ดปลั๊กอิน แนะนำให้คุณกำหนด "StudioSelectable" เป็นตัวกรองกลุ่มการชนของ RaycastParams ของคุณเมื่อค้นหาชิ้นส่วนใต้เคอร์เซอร์ สิ่งนี้ช่วยให้ปลั๊กอินของคุณตรงตามกลไกการเลือกที่ผู้สร้างได้เรียนรู้ที่จะคาดหวังจากเครื่องมือใน Studio ที่สร้างขึ้น

การเรย์แคสต์การเลือกปลั๊กอินที่แนะนำ
local UserInputService = game:GetService("UserInputService")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- เพื่อปฏิบัติตามแนวทาง
raycastParams.BruteForceAllSlow = true -- เพื่อให้ชิ้นส่วนที่มี CanQuery เป็น "false" สามารถถูกเลือกได้
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)

การกรองชิ้นส่วนต่อชิ้นส่วน

เพื่อป้องกันไม่ให้เกิดการชนระหว่างชิ้นส่วนสองชิ้นโดยเฉพาะโดยไม่ต้องตั้งค่ากลุ่มการชน กลุ่มการชน เช่น ระหว่างล้อของรถยนต์และตัวถังของมัน ให้พิจารณาใช้ข้อจำกัด No Collision ข้อดีรวมถึง:

  • ไม่จำเป็นต้องมีกลุ่มการชนและ/หรือสคริปต์การกำหนดค่า ดังนั้นคุณจึงสามารถสร้างและแชร์โมเดลที่มีการกรองการชนที่กำหนดเองได้อย่างง่ายดาย
  • ชิ้นส่วนที่เชื่อมต่อกันจะไม่ชนกัน แต่ยังสามารถชนกับวัตถุอื่นได้

ปิดการชนของตัวละคร

ตัวละครของผู้เล่น Roblox จะชนกันโดยค่าเริ่มต้น สิ่งนี้อาจนำไปสู่การเล่นเกมที่น่าสนใจแต่ไม่ตั้งใจ เช่น ตัวละครกระโดดขึ้นไปบนกันเพื่อไปยังพื้นที่เฉพาะ หากพฤติกรรมนี้ไม่ต้องการ คุณสามารถป้องกันได้ผ่าน Script ต่อไปนี้ใน ServerScriptService

สคริปต์ - ปิดการชนของตัวละคร
local Players = game:GetService("Players")
workspace:RegisterCollisionGroup("Characters")
workspace:CollisionGroupSetCollidable("Characters", "Characters", false)
local function onDescendantAdded(descendant)
-- ตั้งค่ากลุ่มการชนสำหรับชิ้นส่วนใด ๆ ที่เป็นลูกหลาน
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Characters"
end
end
local function onCharacterAdded(character)
-- ประมวลผลลูกหลานที่มีอยู่และใหม่สำหรับการตั้งค่าฟิสิกส์
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- ตรวจจับเมื่อมีการเพิ่มตัวละครของผู้เล่น
player.CharacterAdded:Connect(onCharacterAdded)
end)

การชนของโมเดล

วัตถุ Model เป็นที่เก็บสำหรับชิ้นส่วนแทนที่จะสืบทอดจาก BasePart ดังนั้นพวกมันจึงไม่สามารถเชื่อมต่อกับเหตุการณ์ BasePart.Touched หรือ BasePart.TouchEnded ได้โดยตรง เพื่อกำหนดว่าว่าโมเดลจะกระตุ้นเหตุการณ์การชนหรือไม่ คุณต้องวนรอบลูกหลานของมันและเชื่อมต่อฟังก์ชัน onTouched() และ onTouchEnded() ที่กำหนดเองกับแต่ละ BasePart

ตัวอย่างโค้ดต่อไปนี้เชื่อมต่อ BaseParts ทั้งหมดของโมเดลหลายชิ้นส่วนกับเหตุการณ์การชนและติดตามจำนวนการชนทั้งหมดกับชิ้นส่วนอื่น

การชนของโมเดล
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- ละเว้นกรณีที่โมเดลตัดกันกับตัวเอง
if otherPart:IsDescendantOf(model) then return end
-- เพิ่มจำนวนชิ้นส่วนของโมเดลที่สัมผัส
numTouchingParts += 1
print(model.Name, "ตัดกันกับ", otherPart.Name, "| ชิ้นส่วนของโมเดลที่สัมผัส:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- ละเว้นกรณีที่โมเดลไม่ตัดกันกับตัวเอง
if otherPart:IsDescendantOf(model) then return end
-- ลดจำนวนชิ้นส่วนของโมเดลที่สัมผัส
numTouchingParts -= 1
print(model.Name, "ไม่ตัดกันกับ", otherPart.Name, "| ชิ้นส่วนของโมเดลที่สัมผัส:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
end

การชนของเมชและโมเดลแข็ง

MeshPart และ PartOperation (ชิ้นส่วนที่เชื่อมต่อกันโดย การสร้างแบบแข็ง) เป็นซับคลาสของ BasePart ดังนั้นเมชและชิ้นส่วนที่สร้างแบบแข็งจึงสืบทอดเหตุการณ์การชนและตัวเลือกการกรองการชนเดียวกันกับชิ้นส่วนปกติ อย่างไรก็ตาม เนื่องจากเมชและชิ้นส่วนที่สร้างแบบแข็งมักมีรูปทรงเรขาคณิตที่ซับซ้อนมากขึ้น พวกมันจึงมีคุณสมบัติ CollisionFidelity ที่โดดเด่นซึ่งกำหนดว่าขอบเขตทางกายภาพจะตรงกับการแสดงผลทางสายตาอย่างไรสำหรับการจัดการการชน

คุณสมบัติ CollisionFidelity มีตัวเลือกดังต่อไปนี้ โดยเรียงตามความแม่นยำและผลกระทบต่อประสิทธิภาพจากต่ำไปสูง:

  • กล่อง — สร้างกล่องการชนที่มีขนาดพอเหมาะ เหมาะสำหรับวัตถุขนาดเล็กหรือไม่โต้ตอบ
  • ฮัลล์ — สร้างฮัลล์นูน เหมาะสำหรับวัตถุที่มีรอยบุ๋มหรือโพรงน้อย
  • เริ่มต้น — สร้างรูปร่างการชนที่ประมาณการซึ่งรองรับความโค้ง เหมาะสำหรับวัตถุที่ซับซ้อนที่มีความต้องการการโต้ตอบที่มีรายละเอียดปานกลาง
  • การแยกที่แม่นยำ — เสนอความแม่นยำสูงสุดแต่ยังไม่ใช่การแสดงผล 1:1 ของการแสดงผล ตัวเลือกนี้มีค่าใช้จ่ายด้านประสิทธิภาพที่แพงที่สุดและใช้เวลานานกว่าในการคำนวณของเอนจิน
เมชต้นฉบับของหอคอยปราสาท

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับผลกระทบด้านประสิทธิภาพของตัวเลือกความแม่นยำของการชนและวิธีการบรรเทา ให้ดูที่ การเพิ่มประสิทธิภาพด้านประสิทธิภาพ

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