Kolizja występuje, gdy dwa obiekty 3D stykają się w świecie 3D. Dla dostosowanej obsługi kolizji, BasePart posiada zestaw zdarzeń kolizji oraz technik filtracji kolizji, dzięki czemu możesz kontrolować, które fizyczne zbiory kolidują ze sobą.
Zdarzenia kolizji
Zdarzenia kolizji zdarzają się, gdy dwa BaseParts stykają się lub przestają się stykać w świecie 3D. Można wykrywać te kolizje przez zdarzenia Touched i TouchEnded, które występują bez względu na wartość właściwości CanCollide któregokolwiek z obiektów. Przy rozważaniu obsługi kolizji na częściach, należy zwrócić uwagę na następujące:
- Właściwość CanTouch części określa, czy wyzwala zdarzenia kolizji. Jeśli jest ustawiona na false, ani Touched, ani TouchEnded nie będą wywoływane.
- Właściwość CanCollide części wpływa na to, czy będzie ona fizycznie kolidować z innymi częściami i powodować działanie sił na nie. Nawet jeśli CanCollide jest wyłączona dla części, można wykrywać kontakt i brak kontaktu za pośrednictwem zdarzeń Touched i TouchEnded.
- Zdarzenia Touched i TouchEnded wywołują się tylko w wyniku ruchu fizycznego, a nie w wyniku zmian Position lub CFrame, które powodują, że część staje się współdzielona lub przestaje współdzielić się z inną częścią.
Dotknięty
Zdarzenie Touched wyzwa się, gdy BasePart stykają się z innym, lub z voxelem Terenu. Wydarza się tylko w wyniku symulacji fizycznej i nie wywoła się, gdy Position lub CFrame jest wyraźnie ustawione tak, aby stykając się z inną częścią lub voxel.
Poniższy wzór kodu pokazuje, jak zdarzenie Touched może być połączone z niestandardową funkcją onTouched(). Zauważ, że zdarzenie przesyła argument otherPart do funkcji, wskazując na drugą część zaangażowaną w kolizji.
Kolizja Części
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " zderzyło się z " .. otherPart.Name)
end
part.Touched:Connect(onTouched)
Zauważ, że zdarzenie Touched może być wyzwalane wiele razy w szybkim następstwie w oparciu o subtelne kolizje fizyczne, takie jak gdy poruszający się obiekt "osiada" na stabilnej pozycji lub gdy kolizja dotyczy modelu wieloczęściowego. Aby uniknąć wyzwalania więcej zdarzeń Touched niż to konieczne, możesz zaimplementować prosty system debounce, który wymusza okres "chłodzenia" przez atrybut instancji.
Kolizja Części Z Okresem Chłodzenia
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 .. " zderzyło się z " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Ustaw atrybut na true
task.wait(COOLDOWN_TIME) -- Czekaj na czas chłodzenia
part:SetAttribute("Touched", false) -- Zresetuj atrybut
end
end
part.Touched:Connect(onTouched)
TouchEnded
Zdarzenie TouchEnded wyzwala się, gdy cały zakres kolizji BasePart opuszcza zakres innej BasePart lub wypełnionego voxel'a Terenu. Wydarza się tylko w wyniku symulacji fizycznej i nie wyzwala się, gdy Position lub CFrame jest wyraźnie ustawione tak, aby przestać kolidować z inną częścią lub voxel.
Poniższy wzór kodu pokazuje, jak zdarzenie TouchEnded może być połączone z niestandardową funkcją onTouchEnded(). Jak Touched, zdarzenie przesyła argument otherPart do funkcji, wskazując na drugą część zaangażowaną.
Wykrywanie Braku Kolizji
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " nie styka się już z " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)
Filtracja kolizji
Filtracja kolizji definiuje, które części fizyczne kolidują z innymi. Możesz skonfigurować filtrację dla wielu obiektów przez grupy kolizji lub możesz kontrolować kolizje na podstawie część-a-część z instancjami NoCollisionConstraint.
Grupy kolizji
Grupy kolizji pozwalają przypisać BaseParts do dedykowanych grup i określić, czy kolidują one z innymi grupami. Części w grupach, które nie kolidują, przechodzą przez siebie całkowicie, nawet jeśli obie części mają swoją właściwość CanCollide ustawioną na true.
Możesz łatwo skonfigurować grupy kolizji przez edytor Grup Kolizji w Studio, dostępny przez menu Okno ⟩ 3D w Studio.
Edytor działa w Widoku Listy, który sprzyja dokowaniu po lewej lub prawej stronie Studio, lub w szerszym Widoku Tabeli, który sprzyja dokowaniu do góry lub do dołu.

Rejestracja grup
Edytor zawiera jedną Domyślną grupę kolizji, której nie można zmienić ani usunąć. Wszystkie BaseParts automatycznie przynależą do tej domyślnej grupy, chyba że przypisane do innej grupy, co oznacza, że będą kolidować ze wszystkimi innymi obiektami w grupie Domyślnej.
Aby stworzyć nową grupę kolizji:
Kliknij przycisk Dodaj Grupę na górze panelu edytora, wprowadź nową nazwę grupy i naciśnij Enter. Nowa grupa pojawia się w obu kolumnach widoku listy lub w obu lewej kolumnie i górnym wierszu widoku tabeli.

Powtórz proces w razie potrzeby, wybierając unikalną i opisową nazwę dla każdej grupy. Należy pamiętać, że można zmienić nazwę grupy podczas rozwoju, klikając w jej pole lub wybierając ją i klikając przycisk zmień nazwę.

Konfiguracja kolizji grup
Podczas domyślnej konfiguracji obiekty w każdej grupie kolidują ze sobą. Aby zapobiec kolizji obiektów w jednej grupie z obiektami w innej grupie, odznacz pole w odpowiednim wierszu/kolumnie.
W następującym przykładzie obiekty w grupie Kostki nie będą kolidować z obiektami w grupie Drzwi.

Przypisywanie obiektów do grup
Aby przypisać obiekty do grup, które zarejestrowałeś rejestrując przez edytor Studio:
Wybierz jeden lub więcej BaseParts, które kwalifikują się do bycia częścią grupy kolizji.
Przypisz je do grupy, klikając przycisk ⊕ w jej wierszu. Obiekty mogą przynależeć tylko do jednej grupy kolizji w danym momencie, więc umieszczenie ich w nowej grupie usuwa je z ich bieżącej grupy.

Po przypisaniu nowa grupa jest odzwierciedlana w właściwości obiektu CollisionGroup.

Grupa kolizji StudioSelectable
Narzędzia w Studio korzystają z systemu filtrowania kolizji, aby określić, które obiekty są kandydatami do wyboru podczas klikania w widoku 3D. Obiekty, których przypisana grupa kolizji nie koliduje z StudioSelectable, będą ignorowane.
Na przykład, jeśli masz punkty kontrolne w doświadczeniu wyścigowym, a ich efektywne obszary są definiowane przez duże przezroczyste części, możesz przypisać je do grupy kolizji Punkty kontrolne, a następnie uczynić tę grupę nie kolidującą z StudioSelectable, aby nie przeszkadzały w edytowaniu geometry mapy.

W kodzie wtyczek, zaleca się przypisanie "StudioSelectable" jako filtra grupy kolizji dla Twojego RaycastParams podczas znajdowania części pod kursorem. Pozwala to Twoim wtyczkom na dopasowanie do mechaniki wyboru, której twórcy spodziewali się od wbudowanych narzędzi Studio.
Zalecany Raycast do Selekcji Wtyczkilocal UserInputService = game:GetService("UserInputService")local Workspace = game:GetService("Workspace")local raycastParams = RaycastParams.new()raycastParams.CollisionGroup = "StudioSelectable" -- Aby stosować się do konwencjiraycastParams.BruteForceAllSlow = true -- Aby umożliwić wybór części z wartością 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)
Filtracja część-a-część
Aby zapobiec kolizjom pomiędzy dwiema konkretnymi częściami bez ustawiania grup kolizji, takich jak pomiędzy kołem pojazdu a jego podwoziem, rozważ zastosowanie braku kolizji. Zalety obejmują:
- Nie są wymagane grupy kolizji i/lub skrypty konfiguracyjne, więc możesz łatwo tworzyć i dzielić się modelami z dostosowaną filtracją kolizji.
- Połączone części nie będą ze sobą kolidować, ale mogą nadal kolidować z innymi obiektami.
Wyłącz kolizje postaci
Postacie graczy Roblox kolidują ze sobą domyślnie. Może to prowadzić do ciekawych, ale niezamierzonych scenariuszy, takich jak postacie skaczące na sobie, aby dotrzeć do konkretnych obszarów. Jeśli takie zachowanie nie jest pożądane, możesz temu zapobiec za pomocą poniższego Script w ServerScriptService.
Skrypt - Wyłącz Kolizje Postaci
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
PhysicsService:RegisterCollisionGroup("Postacie")
PhysicsService:CollisionGroupSetCollidable("Postacie", "Postacie", false)
local function onDescendantAdded(descendant)
-- Ustaw grupę kolizji dla każdego elementu potomnego
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Postacie"
end
end
local function onCharacterAdded(character)
-- Przetwórz istniejące i nowe potomne dla konfiguracji fizycznej
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Wykryj, gdy postać gracza jest dodana
player.CharacterAdded:Connect(onCharacterAdded)
end)
Kolizje modeli
Obiekty Model są kontenerami dla części, a nie dziedziczą z BasePart, więc nie mogą być bezpośrednio połączone z zdarzeniami BasePart.Touched lub BasePart.TouchEnded. Aby określić, czy model wyzwala zdarzenia kolizji, musisz przejść przez jego dzieci i połączyć niestandardowe funkcje onTouched() i onTouchEnded() z każdą dziejącą się BasePart.
Poniższy przykład kodu łączy wszystkie BaseParts wieloczęściowego modelu z zdarzeniami kolizji i śledzi całkowitą liczbę kolizji z innymi częściami.
Kolizja Modelu
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignoruj instancje modelu stykające się z samym sobą
if otherPart:IsDescendantOf(model) then return end
-- Zwiększ liczbę stykających się części modelu
numTouchingParts += 1
print(model.Name, "styka się z", otherPart.Name, "| Liczba stykających się części modelu:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignoruj instancje modelu nie stykające się z samym sobą
if otherPart:IsDescendantOf(model) then return end
-- Zmniejsz liczbę stykających się części modelu
numTouchingParts -= 1
print(model.Name, "nie styka się z", otherPart.Name, "| Liczba stykających się części modelu:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
end
Kolizje siatek i modeli solidnych
Obiekty MeshPart oraz PartOperation (części połączone przez modelowanie solidne) są podklasami BasePart, więc siatki i części modelowane solidnie dziedziczą te same zdarzenia kolizji oraz opcje filtracji kolizji jak zwykłe części. Jednakże, ponieważ siatki i części modelowane solidnie zwykle mają bardziej złożoną geometrię, mają charakterystyczną właściwość CollisionFidelity, która określa, jak dokładnie fizyczne granice pasują do wizualnej reprezentacji w zakresie obsługi kolizji.
Właściwość CollisionFidelity ma następujące opcje, w kolejności wierności i wpływu na wydajność od najniższej do najwyższej:
- Box — Tworzy ograniczającą kolizję, idealną dla małych lub nieinteraktywnych obiektów.
- Hull — Generuje wypukły worek, odpowiedni dla obiektów z mniej wyraźnymi wgłębieniami lub komorami.
- Default — Produkuje przybliżony kształt kolizji, który wspiera konkawność, odpowiedni dla złożonych obiektów z pół-dokładnymi potrzebami interakcji.
- PreciseConvexDecomposition — Oferuje najwyższą precyzję wierności, lecz nadal nie jest 1:1 reprezentacją wizualną. Ta opcja ma najwyższe koszty wydajności i wymaga dłuższego czasu obliczeń przez silnik.

Aby uzyskać więcej informacji na temat wpływu wydajności na opcje wierności kolizji i jak je zminimalizować, zobacz Optymalizacja wydajności.