การชนกันเกิดขึ้นเมื่อวัตถุ 3D สองตัวมาสัมผัสกันภายในโลก 3Dสำหรับการจัดการการชนกำหนดเอง BasePart มีชุดของ เหตุการณ์การชน และเทคนิคการกรองการชน ดังนั้นคุณสามารถควบคุมได้ว่าชิ้นส่วนทางกายภาพใดจะชนกับคนอื่น
เหตุการณ์การชนกัน
การชนกัน เหตุการณ์ เกิดขึ้นเมื่อสอง BaseParts สัมผัสหรือหยุดสัมผัสในโลก 3Dคุณสามารถตรวจพบการชนกันเหล่านี้ผ่านเหตุการณ์ Touched และ TouchEnded ซึ่งเกิดขึ้นไม่ว่าค่าความเป็นเจ้าของของส่วนใดส่วนหนึ่งจะเป็น CanCollide หรือไม่เมื่อพิจารณาการจัดการกับชนบนชิ้นส่วน กำลังติดตาม:
- คุณสมบัติของส่วน CanTouch จะกำหนดว่ามันจะกระตุ้นเหตุการณ์การชนหรือไม่ หากตั้งค่าเป็น false ไม่มีทั้ง Touched หรือ TouchEnded จะยิง
- คุณสมบัติของส่วนหนึ่ง CanCollide มีผลต่อว่ามันจะ กายภาพ ชนกับส่วนอื่นและทําให้กําลังกระทํากับพวกเขาแม้ว่า CanCollide จะถูกปิดใช้งานสําหรับส่วนหนึ่ง คุณสามารถตรวจจับการสัมผัสและไม่สัมผัสผ่าน Touched และ TouchEnded เหตุการณ์
- อีเวนต์ และ เพียงจะเกิดขึ้นเป็นผลจากการเคลื่อนไหวทางกายภาพไม่ใช่จากการเปลี่ยนแปลง ภายใน หรือ ภายนอก ที่ทําให้ส่วนหนึ่งชนกับหรือหยุดชนกับส่วนอื่น
สัมผัส
อีเวนต์ Touched จะเกิดขึ้นเมื่อ BasePart มาสัมผัสกับอีกหนึ่งหรือกับ voxel พื้นที่มันจะยิงเฉพาะในผลของ การจำลองทางกายภาพ และจะไม่ยิงเมื่อส่วน Position หรือ CFrame ถูกตั้งค่าโดยเฉพาะเพื่อให้สอดคล้องกับส่วนอื่นหรือวอกเซล
รูปแบบโค้ดต่อไปนี้แสดงวิธีที่อีเวนต์ Touched สามารถเชื่อมต่อกับฟังก์ชันกำหนดเอง onTouched() ได้โปรดทราบว่าอีเวนต์ส่งอาร์กิวเมนต์ otherPart ไปยังฟังก์ชันที่บ่งบอกถึงส่วนอื่นที่มีส่วนร่วมในการชนกัน
การชนกันของส่วน
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " collided with " .. otherPart.Name)
end
part.Touched:Connect(onTouched)
โปรดทราบว่าอีเวนต์ Touched สามารถยิงได้หลายครั้งในช่วงเวลาสั้น ๆ ขึ้นอยู่กับการชนกันทางกายภาพที่แฝงอยู่ เช่น เมื่อวัตถุเคลื่อนที่ "ตั้งลง" ในตำแหน่งสงบหรือเมื่อการชนกันรวมถึงโมเดลหลายส่วน เพื่อหลีกเลี่ยงการเรียกใช้เหตุการณ์ เพิ่มเติมจากที่จำเป็น คุณสามารถใช้ระบบลดความถี่ง่ายๆ ซึ่งบังคับใช้ระยะเวลา "คูลดาวน์" ผ่านคุณสมบัติ ได้
การชนกันส่วนหนึ่งกับคูลดาวน์
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local COOLDOWN_TIME = 1
local function onTouched(otherPart)
if not part:GetAttribute("Touched") then
print(part.Name .. " collided with " .. otherPart.Name)
part:SetAttribute("Touched", true) -- ตั้งค่าคุณสมบัติเป็นจริง
task.wait(COOLDOWN_TIME) -- รอระยะเวลาคูลดาวน์
part:SetAttribute("Touched", false) -- รีเซ็ตคุณสมบัติ
end
end
part.Touched:Connect(onTouched)
สัมผัสจบลงแล้ว
อีเวนต์ TouchEnded จะเกิดขึ้นเมื่อขอบการชนทั้งหมดของ BasePart ออกจากขอบของอีก BasePart หรือวอกเซลที่เติม พื้นที่มันจะยิงเฉพาะในผลของ การจำลองทางกายภาพ และจะไม่ยิงเมื่อส่วน Position หรือ CFrame ถูกตั้งค่าโดยเฉพาะเพื่อหยุดการซ้อนทับกับส่วนอื่นหรือวอกเซล
รูปแบบโค้ดต่อไปนี้แสดงวิธีที่อีเวนต์ TouchEnded สามารถเชื่อมต่อกับฟังก์ชันกำหนดเอง onTouchEnded() ได้เช่น Touched , อีเวนต์ส่งอาร์กิวเมนต์ otherPart ไปยังฟังก์ชันที่ระบุถึงส่วนอื่นที่เกี่ยวข้อง
การตรวจจับไม่ชนกัน
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " is no longer touching " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)
การกรองการชนกัน
การชนกัน การกรอง กำหนดว่าชิ้นส่วนทางกายภาพใดชนกับคนอื่นคุณสามารถกำหนดการกรองสำหรับวัตถุจํานวนมากผ่าน กลุ่มการชนกัน หรือคุณสามารถควบคุมการชนกันบนพื้นฐานของ ส่วนส่วน ด้วย NoCollisionConstraint ตัวอย่าง
กลุ่มการชนกัน
การชนกัน กลุ่ม ช่วยให้คุณสามารถกำหนด BaseParts ให้กับกลุ่มที่กำหนดเองและระบุว่าพวกเขาจะชนกับผู้อื่นในกลุ่มอื่นหรือไม่ชิ้นส่วนภายในกลุ่มที่ไม่ชนกันผ่านกันโดยสิ้นเชิงแม้ว่าทั้งสองชิ้นจะมีค่า CanCollide ของคุณตั้งค่าเป็น true
คุณสามารถตั้งค่ากลุ่มการชนกันได้อย่างง่ายดายผ่าน ตัวแก้ไขกลุ่มการชนกันของ Studio , ซึ่งสามารถเข้าถึงได้โดยคลิกที่ปุ่ม กลุ่มการชนกัน ในแท็บ รูปแบบ ของเครื่องมือ

ฟังก์ชันของเครื่องแก้ไขทำงานในรูปแบบ มุมมองรายการ ซึ่งช่วยให้การจัดเรียง ไปทางซ้ายหรือขวาของ Studio หรือในมุมมอง ตาราง ที่กว้างขึ้นซึ่งช่วยให้การจัดเรียงไปทางด้านบนหรือด้านล่าง

ลงทะเบียนกลุ่ม
ตัวแก้ไขรวมถึงกลุ่มการชนการเริ่มต้นหนึ่ง ค่าเริ่มต้น ซึ่งไม่สามารถเปลี่ยนชื่อหรือลบได้ทั้งหมด BaseParts อัตโนมัติเป็นส่วนหนึ่งของกลุ่มเริ่มต้นนี้ยกเว้นถูกกำหนดให้เป็นกลุ่มอื่นหมายความว่าพวกเขาจะชนกับวัตถุอื่น ๆ ทั้งหมดในกลุ่ม เริ่มต้น เพื่อสร้างกลุ่มการชนกลุ่มใหม่:
คลิกปุ่ม เพิ่มกลุ่ม ที่ด้านบนของแผงเครื่องมือเรดเดอร์ใส่ชื่อกลุ่มใหม่และกด Enterกลุ่มใหม่ปรากฏในทั้งสองคอลัมน์ของมุมมองรายการ หรือในทั้งคอลัมน์ซ้ายและแถวบนสุดของมุมมองตาราง
ทำซ้ำขั้นตอนหากจำเป็น เลือกชื่อที่ไม่ซ้ำกันและอธิบายได้สำหรับแต่ละกลุ่มโปรดทราบว่าคุณสามารถเปลี่ยนชื่อกลุ่มในระหว่างการพัฒนาโดยคลิกในฟิลด์ของมันหรือโดยเลือกและคลิกปุ่ม เปลี่ยนชื่อ
กำหนดการชนกลุ่ม
ภายใต้การกำหนดค่าเริ่มต้นวัตถุในทุกกลุ่มจะชนกันเพื่อป้องกันไม่ให้วัตถุในกลุ่มหนึ่งชนกับวัตถุในกลุ่มอื่น ยกเลิกการเลือก กล่องในแถว/คอลัมน์ที่เกี่ยวข้อง
ในตัวอย่างต่อไปนี้วัตถุในกลุ่ม ลูกบาศก์ จะไม่ชนกับวัตถุในกลุ่ม ประตู

กำหนดวัตถุให้กับกลุ่ม
เพื่อกำหนดวัตถุให้กับกลุ่มที่คุณได้ ลงทะเบียน ผ่านตัวแก้ไข Studio:
เลือกหนึ่งหรือมากกว่า BaseParts ที่มีคุณสมบัติเป็นส่วนหนึ่งของกลุ่มการชนกัน
กำหนดให้พวกเขาเป็นสมาชิกของกลุ่มโดยคลิกปุ่ม ⊕ สำหรับเเถวของมันวัตถุสามารถเป็นส่วนหนึ่งของกลุ่มการชนกันเพียงกลุ่มเดียวในแต่ละครั้ง ดังนั้นการวางไว้ในกลุ่มใหม่จะลบพวกเขาออกจากกลุ่มปัจจุบัน
เมื่อได้รับการกำหนดแล้ว กลุ่มใหม่จะสะท้อนภายใต้คุณสมบัติ CollisionGroup ของวัตถุ

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

สำหรับรหัสปลั๊กอินแนะนำให้คุณกำหนด "StudioSelectable" เป็นตัวกรองกลุ่มการชนกระแทกของ RaycastParams เมื่อค้นหาชิ้นส่วนภายใต้เคอร์เซอร์สิ่งนี้ช่วยให้แอปพลิเคชันของคุณสอดคล้องกับเมคานิกส์การเลือกที่ผู้สร้างได้เรียนรู้ที่จะคาดหวังจากเครื่องมือ Studio ที่ติดตั้งไว้
เรย์คาสต์การเลือกปลั๊กอินที่แนะนำ
local UserInputService = game:GetService("UserInputService")local Workspace = game:GetService("Workspace")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)
การกรองส่วนต่อส่วน
เพื่อป้องกันการชนกันระหว่างส่วนที่เฉพาะสองส่วนโดยไม่ตั้งค่า กลุ่มการชนกัน เช่นระหว่างล้อของยานพาหนะและแชสซี พิจารณาข้อจำกัด ไม่มีการชนกันข้อดีรวมถึง:
- ไม่จำเป็นต้องใช้กลุ่มการชนกันและ/หรือสคริปต์การกำหนดค่า ดังนั้นคุณสามารถสร้างและแบ่งปันโมเดลได้อย่างง่ายดายโดยมีการกรองการชนกันที่กำหนดเอง
- ชิ้นส่วนที่เชื่อมต่อกันจะไม่ชนกัน แต่ก็ยังสามารถชนกับวัตถุอื่นได้
ปิดการชนกันของตัวละคร
ตัวละครผู้เล่น Roblox ชนกันโดยอัตโนมัติสิ่งนี้สามารถนำไปสู่การเล่นเกมที่น่าสนใจ แต่ไม่ได้ตั้งใจ เช่น ตัวละครกระโดดบนกันเพื่อไปถึงพื้นที่เฉพาะหากพฤติกรรมนี้ไม่พึงประสงค์ คุณสามารถป้องกันได้โดยใช้ Script ใน ServerScriptService ต่อไปนี้
สคริปต์ - ปิดการชนกันของตัวละคร
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
local CollisionGroupName = "Characters"
PhysicsService:RegisterCollisionGroup(CollisionGroupName)
PhysicsService:CollisionGroupSetCollidable(CollisionGroupName, CollisionGroupName, false)
local function setCollisionGroup(model)
-- ใช้กลุ่มการชนกันกับชิ้นส่วนที่มีอยู่ทั้งหมดในโมเดล
for _, descendant in model:GetDescendants() do
if descendant:IsA("BasePart") then
descendant.CollisionGroup = CollisionGroupName
end
end
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
setCollisionGroup(character)
end)
-- หากผู้เล่นมีตัวละครแล้วใช้กลุ่มการชนกันทันที
if player.Character then
setCollisionGroup(player.Character)
end
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, "intersected with", otherPart.Name, "| Model parts touching:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- เพิกเฉยตัวอย่างของโมเดลที่ไม่ซ้อนทับกับตัวเอง
if otherPart:IsDescendantOf(model) then return end
-- ลดจํานวนส่วนของโมเดลที่สัมผัส
numTouchingParts -= 1
print(model.Name, "un-intersected from", otherPart.Name, "| Model parts touching:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
end
การชนกันระหว่างโมเดลเมชและโมเดลของแข็ง
และ (ชิ้นส่วนที่เชื่อมโยงโดย การโมเดล링แข็ง ) เป็นชั้นย่อยของ ดังนั้นเมชและชิ้นส่วนโมเดลจะมีตัวเลือกการชนกันและการกรองการชนกันเดียวกันกับชิ้นส่วนปกติอย่างไรก็ตาม เนื่องจากชิ้นส่วนที่มีเมชและโมเดลที่ซับซ้อนมักจะมีรูปร่างที่ซับซ้อนมากขึ้น พวกเขาจึงมีคุณสมบัติโดดเด่น CollisionFidelity ซึ่งกำหนดวิธีที่แม่นยำที่ขอบกายภาพสอดคล้องกับการแสดงภาพสำหรับการจัดการการชนกัน
คุณสมบัติ CollisionFidelity มีตัวเลือกต่อไปนี้ตามลำดับความซื่อสัตย์และผลกระทบด้านประสิทธิภาพจากต่ำไปสูง:
- กล่อง — สร้างกล่องความขัดแย้งที่ผูกไว้ เหมาะสำหรับวัตถุขนาดเล็กหรือไม่โต้ตอบ
- ฮัลล์ — สร้างฮัลล์ควบแน่น เหมาะสำหรับวัตถุที่มีรอยย่นหรือช่องว่างน้อย
- ค่าเริ่มต้น — ผลิตรูปทรงการชนที่ใกล้เคียงที่สนับสนุนความเว้าและเหมาะสำหรับวัตถุที่ซับซ้อนที่มีความต้องการการโต้ตอบที่มีรายละเอียดครึ่งหนึ่ง
- การแยกแยะที่แม่นยําของ PreciseConvex — เสนอความถูกต้องสูงสุด แต่ยังไม่ใช่การแทนที่ภาพที่แม่นยํา 1:1ตัวเลือกนี้มีค่าใช้จ่ายในการดำเนินการที่แพงที่สุดและใช้เวลานานกว่าที่เครื่องยนต์จะคำนวณ

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