การชนกัน

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

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

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

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

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

สัมผัส

อีเวนต์ 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 , ซึ่งสามารถเข้าถึงได้โดยคลิกที่ปุ่ม กลุ่มการชนกัน ในแท็บ รูปแบบ ของเครื่องมือ

Collision Groups tool indicated in Model tab of Studio

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

List View example in Collision Groups Editor

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

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

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

    New group added to Collision Groups Editor in List View
  2. ทำซ้ำขั้นตอนหากจำเป็น เลือกชื่อที่ไม่ซ้ำกันและอธิบายได้สำหรับแต่ละกลุ่มโปรดทราบว่าคุณสามารถเปลี่ยนชื่อกลุ่มในระหว่างการพัฒนาโดยคลิกในฟิลด์ของมันหรือโดยเลือกและคลิกปุ่ม เปลี่ยนชื่อ

    Button and field indicated for renaming a group in the Collision Groups Editor

กำหนดการชนกลุ่ม

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

ในตัวอย่างต่อไปนี้วัตถุในกลุ่ม ลูกบาศก์ จะไม่ชนกับวัตถุในกลุ่ม ประตู

Group configured in List View of Collision Groups Editor

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

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

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

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

    Plus button indicated in Collision Groups Editor for adding selected parts to a group

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

Chosen collision group indicated as the part's CollisionGroup property

กลุ่มการชนกันที่เลือกได้ในสตูดิโอ

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

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

Checkpoints group configured to be non-collidable with StudioSelectable group

สำหรับรหัสปลั๊กอินแนะนำให้คุณกำหนด "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ตัวเลือกนี้มีค่าใช้จ่ายในการดำเนินการที่แพงที่สุดและใช้เวลานานกว่าที่เครื่องยนต์จะคำนวณ
Original mesh of castle tower

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