Kolizja występuje, gdy dwa obiekty 3D stykają się w świecie 3D. Dla dostosowanej obsługi kolizji, BasePart ma zestaw zdarzeń kolizji oraz technik filtrowania kolizji, dzięki czemu możesz kontrolować, które fizyczne zespoły kolidują z innymi.
Zdarzenia kolizji
Zdarzenia kolizji zdarzają się, gdy dwa BaseParts dotykają się lub przestają się dotykać w świecie 3D. Możesz wykrywać te kolizje za pomocą zdarzeń Touched i TouchEnded, które występują niezależnie od wartości właściwości CanCollide któregokolwiek z części. Przy rozważaniu obsługi kolizji na częściach, zwróć uwagę na następujące kwestie:
- Właściwość CanTouch części określa, czy wyzwala zdarzenia kolizji. Jeśli jest ustawiona na false, ani Touched, ani TouchEnded nie zostaną wywołane.
- 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żesz wykrywać dotyk i brak dotyku za pomocą zdarzeń Touched i TouchEnded.
- Zdarzenia Touched i TouchEnded wyzwalają się tylko w wyniku ruchu fizycznego, a nie z powodu zmian Position lub CFrame, które powodują, że część wchodzi w interakcję lub przestaje wchodzić w interakcję z inną częścią.
Dotknięcie
Zdarzenie Touched wyzwala się, gdy BasePart stykają się z innym lub z wokselem Terenu. Wyzwala się tylko w wyniku symulacji fizycznej i nie wyzwala się, gdy Position lub CFrame jest jawnie ustawione tak, aby wchodziło w interakcję z inną częścią lub wokselem.
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 kolizję.
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " koliduje z " .. otherPart.Name)
end
part.Touched:Connect(onTouched)Zauważ, że zdarzenie Touched może wyzwalać się wielokrotnie w szybkim tempie w oparciu o subtelne kolizje fizyczne, takie jak gdy poruszający się obiekt "osiada" w pozycji spoczynkowej lub gdy kolizja dotyczy modelu wieloczęściowego. Aby uniknąć wyzwalania większej liczby zdarzeń Touched niż to konieczne, możesz wdrożyć prosty system debouncing, który wymusza okres "cooldown" za pomocą atrybutu instancji.
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 .. " koliduje z " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Ustaw atrybut na true
task.wait(COOLDOWN_TIME) -- Czekaj na czas cooldown
part:SetAttribute("Touched", false) -- Zresetuj atrybut
end
end
part.Touched:Connect(onTouched)TouchEnded
Zdarzenie TouchEnded wyzwala się, gdy całe pole kolizji BasePart opuszcza pole innej BasePart lub wypełnionego wokselu Terenu. Wyzwala się tylko w wyniku symulacji fizycznej i nie wyzwala się, gdy Position lub CFrame jest jawnie ustawione tak, aby przestało wchodzić w interakcję z inną częścią lub wokselem.
Poniższy wzór kodu pokazuje, jak zdarzenie TouchEnded może być połączone z niestandardową funkcją onTouchEnded(). Podobnie jak Touched, zdarzenie przesyła argument otherPart do funkcji, wskazując na drugą część zaangażowaną.
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " już nie dotyka " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)Filtrowanie kolizji
Filtrowanie kolizji definiuje, które fizyczne części kolidują z innymi. Możesz skonfigurować filtrowanie dla wielu obiektów za pomocą grup kolizji lub możesz kontrolować kolizje na podstawie część-do-części za pomocą instancji NoCollisionConstraint.
Grupy kolizji
Grupy kolizji pozwalają przypisać BaseParts do dedykowanych grup i określić, czy kolidują one z obiektami w innych grupach. Części w grupach, które nie kolidują, przechodzą przez siebie całkowicie, nawet jeśli obie części mają właściwość CanCollide ustawioną na true.
Możesz łatwo skonfigurować grupy kolizji za pomocą edytora Grupy Kolizji w Studio, dostępnego przez menu Okno ⟩ 3D.
Edytor działa w trybie Widok Listy, który sprzyja dokowaniu po lewej lub prawej stronie Studio, lub w szerszym trybie Widok Tabeli, który sprzyja dokowaniu na górze lub na dole.

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

Powtórz proces, jeśli to konieczne, wybierając unikalną i opisową nazwę dla każdej grupy. Zauważ, że możesz zmienić nazwę grupy w trakcie 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 wszystkich grupach kolidują ze sobą. Aby zapobiec kolizjom obiektów w jednej grupie z obiektami w innej grupie, odznacz pole w odpowiednim wierszu/kolumnie.
W poniższym przykładzie obiekty w grupie Cubes nie będą kolidować z obiektami w grupie Doors.

Przypisywanie obiektów do grup
Aby przypisać obiekty do grup, które zarejestrowałeś za pomocą edytora Studio:
Wybierz jedną lub więcej BaseParts, które kwalifikują się jako część grupy kolizji.
Przypisz je do grupy, klikając przycisk ⊕ dla jej wiersza. Obiekty mogą należeć tylko do jednej grupy kolizji w danym czasie, 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 CollisionGroup obiektu.

Grupa kolizji StudioSelectable
Narzędzia w Studio używają 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 grze wyścigowej, których efektywne obszary są definiowane przez duże przezroczyste części, możesz przypisać je do grupy kolizji Checkpoints, a następnie ustawić tę grupę jako niekolidującą z StudioSelectable, aby nie przeszkadzały podczas edytowania podstawowej geometrii mapy.

Dla kodu wtyczki zaleca się przypisanie "StudioSelectable" jako filtr grupy kolizji twojego RaycastParams podczas znajdowania części pod kursorem. Umożliwia to twoim wtyczkom dopasowanie mechaniki wyboru, której twórcy nauczyli się oczekiwać od wbudowanych narzędzi Studio.
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- Aby podążać za konwencją
raycastParams.BruteForceAllSlow = true -- Aby części z CanQuery ustawionym na "false" mogły być wybierane
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = Workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = Workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)Filtrowanie część-do-części
Aby zapobiec kolizjom między dwoma konkretnymi częściami bez ustawiania grup kolizji, takich jak między kołem pojazdu a jego podwoziem, rozważ użycie konstrukcji No Collision. Zalety obejmują:
- Nie są wymagane grupy kolizji i/lub skrypty konfiguracyjne, więc możesz łatwo tworzyć i udostępniać modele z dostosowanym filtrowaniem kolizji.
- Połączone części nie będą kolidować ze sobą, ale nadal mogą kolidować z innymi obiektami.
Wyłącz kolizje postaci
Postacie graczy Roblox kolidują ze sobą domyślnie. Może to prowadzić do interesującej, ale niezamierzonej rozgrywki, takiej jak postacie skaczące na siebie, aby dotrzeć do określonych obszarów. Jeśli to zachowanie jest niepożądane, możesz je zablokować za pomocą poniższego Script w ServerScriptService.
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
PhysicsService:RegisterCollisionGroup("Characters")
PhysicsService:CollisionGroupSetCollidable("Characters", "Characters", false)
local function onDescendantAdded(descendant)
-- Ustaw grupę kolizji dla każdego potomka części
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Characters"
end
end
local function onCharacterAdded(character)
-- Przetwórz istniejące i nowe potomki w celu ustawienia fizyki
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Wykryj, kiedy postać gracza zostanie dodana
player.CharacterAdded:Connect(onCharacterAdded)
end)Kolizje modeli
Obiekty Model są kontenerami dla części, a nie dziedziczą z BasePart, więc nie mogą bezpośrednio łączyć się 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ą dzieckiem BasePart.
Poniższy przykład kodu łączy wszystkie BaseParts modelu wieloczęściowego z zdarzeniami kolizji i śledzi całkowitą liczbę kolizji z innymi częściami.
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignoruj instancje modelu wchodzące w interakcję z samym sobą
if otherPart:IsDescendantOf(model) then return end
-- Zwiększ liczbę części modelu dotykających
numTouchingParts += 1
print(model.Name, "wchodzi w interakcję z", otherPart.Name, "| Części modelu dotykające:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignoruj instancje modelu przestających wchodzić w interakcję z samym sobą
if otherPart:IsDescendantOf(model) then return end
-- Zmniejsz liczbę części modelu dotykających
numTouchingParts -= 1
print(model.Name, "przestał wchodzić w interakcję z", otherPart.Name, "| Części modelu dotykające:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
endKolizje siatek i modeli stałych
MeshPart i PartOperation (części połączone przez modelowanie stałe) są podklasami BasePart, więc siatki i części modelowane stałe dziedziczą te same zdarzenia kolizji oraz opcje filtrowania kolizji co zwykłe części. Jednak ponieważ siatki i części modelowane stałe zazwyczaj 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 obsłudze kolizji.
Właściwość CollisionFidelity ma następujące opcje, w kolejności od najniższej do najwyższej dokładności i wpływu na wydajność:
- Box — Tworzy graniczną kolizję w postaci pudełka, idealną dla małych lub nieinteraktywnych obiektów.
- Hull — Generuje wypukły kształt, odpowiedni dla obiektów z mniej wyraźnymi wcięciami lub wnękami.
- Default — Produkuje przybliżony kształt kolizji, który wspiera konkawność, odpowiedni dla złożonych obiektów z półszczegółowymi potrzebami interakcji.
- PreciseConvexDecomposition — Oferuje najwyższą dokładność, ale nadal nie jest 1:1 reprezentacją wizualną. Ta opcja ma najwyższy koszt wydajności i zajmuje więcej czasu na obliczenia przez silnik.

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