Va chạm

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Một va chạm xảy ra khi hai đối tượng 3D tiếp xúc với nhau trong thế giới 3D. Để xử lý va chạm tùy chỉnh, BasePart có một tập hợp các sự kiện va chạm và các kỹ thuật lọc va chạm, vì vậy bạn có thể kiểm soát các lắp ráp vật lý nào va chạm với nhau.

Sự kiện va chạm

Các sự kiện va chạm xảy ra khi hai BaseParts chạm vào nhau hoặc ngừng chạm vào nhau trong thế giới 3D. Bạn có thể phát hiện những va chạm này thông qua các sự kiện TouchedTouchEnded, xảy ra bất kể giá trị thuộc tính CanCollide của bất kỳ phần nào. Khi xem xét việc xử lý va chạm trên các phần, hãy lưu ý những điều sau:

  • Thuộc tính CanTouch của một phần xác định xem nó có kích hoạt các sự kiện va chạm hay không. Nếu được đặt thành false, cả TouchedTouchEnded sẽ không được kích hoạt.
  • Thuộc tính CanCollide của một phần ảnh hưởng đến việc nó có va chạm vật lý với các phần khác và gây ra lực tác động lên chúng hay không. Ngay cả khi CanCollide bị vô hiệu hóa cho một phần, bạn vẫn có thể phát hiện chạm và không chạm thông qua các sự kiện TouchedTouchEnded.
  • Các sự kiện TouchedTouchEnded chỉ được kích hoạt do chuyển động vật lý, không phải từ các thay đổi Position hoặc CFrame khiến một phần giao nhau hoặc ngừng giao nhau với một phần khác.
  • Lớp Terrain cấp cao nhất kế thừa từ BasePart, vì vậy bạn có thể gán một nhóm va chạm cho Terrain để xác định xem các BaseParts khác có va chạm với các voxel Terrain hay không.

Touched

Sự kiện Touched được kích hoạt khi một BasePart tiếp xúc với một phần khác, hoặc với một voxel Terrain. Nó chỉ được kích hoạt do mô phỏng vật lý và sẽ không được kích hoạt khi vị trí Position hoặc CFrame của phần được đặt rõ ràng sao cho nó giao nhau với một phần hoặc voxel khác.

Mẫu mã sau đây cho thấy cách sự kiện Touched có thể được kết nối với một hàm tùy chỉnh onTouched(). Lưu ý rằng sự kiện gửi đối số otherPart đến hàm, chỉ ra phần khác liên quan đến va chạm.

Va chạm phần
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " đã va chạm với " .. otherPart.Name)
end
part.Touched:Connect(onTouched)

Lưu ý rằng sự kiện Touched có thể được kích hoạt nhiều lần liên tiếp nhanh chóng dựa trên các va chạm vật lý tinh tế, chẳng hạn như khi một đối tượng di chuyển "định hình" vào một vị trí nghỉ hoặc khi một va chạm liên quan đến một mô hình nhiều phần. Để tránh kích hoạt nhiều sự kiện Touched hơn mức cần thiết, bạn có thể triển khai một hệ thống debounce đơn giản, áp dụng một khoảng thời gian "cooldown" thông qua một thuộc tính instance.

Va chạm phần với thời gian cooldown
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 .. " đã va chạm với " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Đặt thuộc tính thành true
task.wait(COOLDOWN_TIME) -- Chờ thời gian cooldown
part:SetAttribute("Touched", false) -- Đặt lại thuộc tính
end
end
part.Touched:Connect(onTouched)

TouchEnded

Sự kiện TouchEnded được kích hoạt khi toàn bộ phạm vi va chạm của một BasePart thoát khỏi phạm vi của một BasePart khác hoặc một voxel Terrain đã được lấp đầy. Nó chỉ được kích hoạt do mô phỏng vật lý và sẽ không được kích hoạt khi vị trí Position hoặc CFrame của phần được đặt rõ ràng sao cho nó ngừng giao nhau với một phần hoặc voxel khác.

Mẫu mã sau đây cho thấy cách sự kiện TouchEnded có thể được kết nối với một hàm tùy chỉnh onTouchEnded(). Giống như Touched, sự kiện gửi đối số otherPart đến hàm, chỉ ra phần khác liên quan.

Phát hiện không va chạm
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " không còn chạm vào " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)

Lọc va chạm

Lọc va chạm xác định các phần vật lý nào va chạm với nhau. Bạn có thể cấu hình lọc cho nhiều đối tượng thông qua nhóm va chạm hoặc bạn có thể kiểm soát va chạm trên cơ sở phần‑đến‑phần với các instance NoCollisionConstraint.

Nhóm va chạm

Nhóm va chạm cho phép bạn gán BaseParts vào các nhóm riêng biệt và chỉ định xem chúng có va chạm với những nhóm khác hay không. Các phần trong các nhóm không va chạm sẽ đi xuyên qua nhau hoàn toàn, ngay cả khi cả hai phần đều có thuộc tính CanCollide được đặt thành true.

Trong video trên, các đối tượng quay nằm trong các nhóm va chạm khác nhau đến mức chúng va chạm với các đối tượng có màu khác nhưng không va chạm với các đối tượng có màu của chính chúng

Bạn có thể dễ dàng thiết lập các nhóm va chạm thông qua trình chỉnh sửa Nhóm Va Chạm của Studio, có thể truy cập thông qua menu Cửa Sổ ⟩ 3D của Studio.

Trình chỉnh sửa hoạt động trong chế độ Danh Sách View ưu tiên neo sang bên trái hoặc bên phải của Studio, hoặc trong chế độ Bảng View rộng hơn, ưu tiên neo lên trên hoặc dưới.

Ví dụ Danh Sách View trong Trình Chỉnh Sửa Nhóm Va Chạm

Đăng ký nhóm

Trình chỉnh sửa bao gồm một nhóm va chạm Mặc định mà không thể được đổi tên hoặc xóa. Tất cả các BaseParts tự động thuộc về nhóm mặc định này trừ khi được gán cho một nhóm khác, có nghĩa là chúng sẽ va chạm với tất cả các đối tượng khác trong nhóm Mặc định.

Để tạo một nhóm va chạm mới:

  1. Nhấp vào nút Thêm Nhóm ở trên cùng của bảng điều khiển trình chỉnh sửa, nhập tên nhóm mới và nhấn Enter. Nhóm mới sẽ xuất hiện trong cả hai cột của chế độ xem danh sách, hoặc trong cả hai cột bên trái và hàng trên cùng của chế độ xem bảng.

    Nhóm mới được thêm vào Trình Chỉnh Sửa Nhóm Va Chạm trong Danh Sách View
  2. Lặp lại quy trình nếu cần, chọn một tên duy nhất và mô tả cho mỗi nhóm. Lưu ý rằng bạn có thể thay đổi tên của một nhóm trong quá trình phát triển bằng cách nhấp vào trường của nó, hoặc bằng cách chọn nó và nhấp vào nút đổi tên.

    Nút và trường được chỉ định để đổi tên một nhóm trong Trình Chỉnh Sửa Nhóm Va Chạm

Cấu hình va chạm nhóm

Dưới cấu hình mặc định, các đối tượng trong tất cả các nhóm va chạm với nhau. Để ngăn các đối tượng trong một nhóm va chạm với các đối tượng trong nhóm khác, hãy bỏ chọn ô trong hàng/cột tương ứng.

Trong ví dụ sau, các đối tượng trong nhóm Cubes sẽ không va chạm với các đối tượng trong nhóm Doors.

Nhóm được cấu hình trong Danh Sách View của Trình Chỉnh Sửa Nhóm Va Chạm

Gán đối tượng vào nhóm

Để gán các đối tượng vào các nhóm mà bạn đã đăng ký thông qua trình chỉnh sửa Studio:

  1. Chọn một hoặc nhiều BaseParts đủ điều kiện là một phần của một nhóm va chạm.

  2. Gán chúng vào nhóm bằng cách nhấp vào nút cho hàng của nó. Các đối tượng chỉ có thể thuộc về một nhóm va chạm tại một thời điểm, vì vậy việc đặt chúng vào một nhóm mới sẽ loại bỏ chúng khỏi nhóm hiện tại.

    Nút cộng được chỉ định trong Trình Chỉnh Sửa Nhóm Va Chạm để thêm các phần đã chọn vào một nhóm

Khi đã được gán, nhóm mới sẽ được phản ánh dưới thuộc tính CollisionGroup của đối tượng.

Nhóm va chạm đã chọn được chỉ định là thuộc tính CollisionGroup của phần

Nhóm va chạm StudioSelectable

Các công cụ trong Studio sử dụng hệ thống lọc va chạm để xác định các đối tượng nào là ứng cử viên cho việc chọn khi nhấp vào trong viewport 3D. Các đối tượng có nhóm va chạm được gán không va chạm với StudioSelectable sẽ bị bỏ qua.

Ví dụ, nếu bạn có các điểm kiểm tra trong một trò chơi đua xe mà các khu vực hiệu quả của chúng được xác định bởi các phần trong suốt lớn, bạn có thể gán chúng vào một nhóm va chạm Checkpoints và sau đó làm cho nhóm đó không va chạm với StudioSelectable để chúng không cản trở khi bạn chỉnh sửa hình học bản đồ bên dưới.

Nhóm Checkpoints được cấu hình để không va chạm với nhóm StudioSelectable

Đối với mã plugin, được khuyến nghị rằng bạn gán "StudioSelectable" làm bộ lọc nhóm va chạm của RaycastParams của bạn khi tìm các phần dưới con trỏ. Điều này cho phép các plugin của bạn phù hợp với cơ chế chọn mà các nhà sáng tạo đã học để mong đợi từ các công cụ Studio tích hợp sẵn.

Raycast chọn plugin được khuyến nghị
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- Để theo quy ước
raycastParams.BruteForceAllSlow = true -- Để các phần có CanQuery là "false" có thể được chọn
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = Workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = Workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)

Lọc phần đến phần

Để ngăn chặn va chạm giữa hai phần cụ thể mà không cần thiết lập nhóm va chạm, chẳng hạn như giữa bánh xe của một phương tiện và khung của nó, hãy xem xét ràng buộc No Collision. Các lợi ích bao gồm:

  • Không cần nhóm va chạm và/hoặc tập lệnh cấu hình, vì vậy bạn có thể dễ dàng tạo và chia sẻ các mô hình với lọc va chạm tùy chỉnh.
  • Các phần kết nối sẽ không va chạm với nhau, nhưng chúng vẫn có thể va chạm với các đối tượng khác.

Vô hiệu hóa va chạm nhân vật

Các nhân vật người chơi Roblox va chạm với nhau theo mặc định. Điều này có thể dẫn đến lối chơi thú vị nhưng không mong muốn, chẳng hạn như các nhân vật nhảy lên nhau để đến các khu vực cụ thể. Nếu hành vi này không mong muốn, bạn có thể ngăn chặn nó thông qua Script sau trong ServerScriptService.

Tập lệnh - Vô hiệu hóa va chạm nhân vật
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
PhysicsService:RegisterCollisionGroup("Characters")
PhysicsService:CollisionGroupSetCollidable("Characters", "Characters", false)
local function onDescendantAdded(descendant)
-- Đặt nhóm va chạm cho bất kỳ phần con nào
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Characters"
end
end
local function onCharacterAdded(character)
-- Xử lý các phần con hiện có và mới cho thiết lập vật lý
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Phát hiện khi nhân vật của người chơi được thêm vào
player.CharacterAdded:Connect(onCharacterAdded)
end)

Va chạm mô hình

Các đối tượng Model là các container cho các phần thay vì kế thừa từ BasePart, vì vậy chúng không thể kết nối trực tiếp với các sự kiện BasePart.Touched hoặc BasePart.TouchEnded. Để xác định xem một mô hình có kích hoạt các sự kiện va chạm hay không, bạn cần lặp qua các con của nó và kết nối các hàm tùy chỉnh onTouched()onTouchEnded() với mỗi con BasePart.

Mẫu mã sau đây kết nối tất cả các BaseParts của một mô hình nhiều phần với các sự kiện va chạm và theo dõi tổng số va chạm với các phần khác.

Va chạm mô hình
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Bỏ qua các trường hợp của mô hình giao nhau với chính nó
if otherPart:IsDescendantOf(model) then return end
-- Tăng số lượng các phần của mô hình đang chạm
numTouchingParts += 1
print(model.Name, "đã giao nhau với", otherPart.Name, "| Số phần của mô hình đang chạm:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Bỏ qua các trường hợp của mô hình không giao nhau với chính nó
if otherPart:IsDescendantOf(model) then return end
-- Giảm số lượng các phần của mô hình đang chạm
numTouchingParts -= 1
print(model.Name, "không còn giao nhau với", otherPart.Name, "| Số phần của mô hình đang chạm:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
end

Va chạm mô hình và rắn

MeshPartPartOperation (các phần được kết hợp bằng mô hình rắn) là các lớp con của BasePart, vì vậy các mô hình và các phần được mô hình rắn thừa hưởng cùng các sự kiện va chạm và các tùy chọn lọc va chạm như các phần thông thường. Tuy nhiên, vì các mô hình và các phần được mô hình rắn thường có hình học phức tạp hơn, chúng có thuộc tính đặc biệt CollisionFidelity xác định mức độ chính xác mà các ranh giới vật lý phù hợp với hình ảnh trực quan cho việc xử lý va chạm.

Thuộc tính CollisionFidelity có các tùy chọn sau, theo thứ tự độ chính xác và tác động đến hiệu suất từ thấp đến cao:

  • Hộp — Tạo một hộp va chạm bao quanh, lý tưởng cho các đối tượng nhỏ hoặc không tương tác.
  • Vỏ — Tạo ra một vỏ lồi, phù hợp cho các đối tượng có các lỗ hổng hoặc hốc ít rõ ràng hơn.
  • Mặc định — Tạo ra một hình dạng va chạm gần đúng hỗ trợ độ lõm, phù hợp cho các đối tượng phức tạp với nhu cầu tương tác bán chi tiết.
  • Phân tích Lồi Chính Xác — Cung cấp độ chính xác cao nhất nhưng vẫn không phải là một đại diện 1:1 của hình ảnh. Tùy chọn này có chi phí hiệu suất cao nhất và mất nhiều thời gian hơn để động cơ tính toán.
Mô hình gốc của tháp lâu đài

Để biết thêm thông tin về tác động đến hiệu suất của các tùy chọn độ chính xác va chạm và cách giảm thiểu chúng, hãy xem Tối ưu hóa hiệu suất.

©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.