Una collisione si verifica quando due oggetti 3D entrano in contatto all'interno del mondo 3D. Per una gestione personalizzata delle collisioni, BasePart dispone di un insieme di eventi di collisione e tecniche di filtraggio delle collisioni, in modo da poter controllare quali assemblaggi fisici collidono con altri.
Eventi di collisione
Gli eventi di collisione si verificano quando due BaseParts si toccano o smettono di toccarsi nel mondo 3D. È possibile rilevare queste collisioni tramite gli eventi Touched e TouchEnded, che si verificano indipendentemente dal valore della proprietà CanCollide di ciascuna parte. Quando si considera la gestione delle collisioni sulle parti, si noti quanto segue:
- La proprietà CanTouch di una parte determina se attiva eventi di collisione. Se impostata su false, né Touched né TouchEnded verranno attivati.
- La proprietà CanCollide di una parte influisce sul fatto che essa collida fisicamente con altre parti e provochi forze che agiscono su di esse. Anche se CanCollide è disabilitata per una parte, è possibile rilevare il contatto e la mancanza di contatto tramite gli eventi Touched e TouchEnded.
- Gli eventi Touched e TouchEnded si attivano solo a seguito di movimento fisico, non per cambiare Position o CFrame che fa sì che una parte intersechi o smetta di intersecare un'altra parte.
Touched
L'evento Touched si attiva quando una BasePart entra in contatto con un'altra, o con un voxel di Terrain. Si attiva solo a seguito di simulazione fisica e non si attiva quando la posizione di Position o CFrame è impostata esplicitamente in modo che intersechi un'altra parte o voxel.
Il seguente modello di codice mostra come l'evento Touched può essere connesso a una funzione onTouched() personalizzata. Nota che l'evento invia l'argomento otherPart alla funzione, indicando l'altra parte coinvolta nella collisione.
Part Collision
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " è colliso con " .. otherPart.Name)
end
part.Touched:Connect(onTouched)
Nota che l'evento Touched può attivarsi più volte in rapida successione a causa di collisioni fisiche sottili, come quando un oggetto in movimento "si stabilizza" in una posizione di riposo o quando una collisione coinvolge un modello multi-part. Per evitare di attivare più eventi Touched di quanto necessario, puoi implementare un semplice sistema di debounce che impone un periodo di "raffreddamento" tramite un'attributo istanza.
Part Collision With 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 .. " è colliso con " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Imposta l'attributo su true
task.wait(COOLDOWN_TIME) -- Attendere la durata del raffreddamento
part:SetAttribute("Touched", false) -- Ripristina l'attributo
end
end
part.Touched:Connect(onTouched)
TouchEnded
L'evento TouchEnded si attiva quando i confini di collisione di una BasePart escono dai confini di un'altra BasePart o di un voxel di Terrain riempito. Si attiva solo a seguito di simulazione fisica e non si attiva quando la posizione di Position o CFrame è impostata esplicitamente in modo che smetta di intersecare un'altra parte o voxel.
Il seguente modello di codice mostra come l'evento TouchEnded può essere connesso a una funzione onTouchEnded() personalizzata. Come Touched, l'evento invia l'argomento otherPart alla funzione, indicando l'altra parte coinvolta.
Non-Collision Detection
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " non sta più toccando " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)
Filtraggio delle collisioni
Il filtraggio delle collisioni definisce quali parti fisiche collidono con altre. Puoi configurare il filtraggio per numerosi oggetti tramite gruppi di collisione o puoi controllare le collisioni su base part‑to‑part con istanze di NoCollisionConstraint.
Gruppi di collisione
I gruppi di collisione ti consentono di assegnare BaseParts a gruppi dedicati e specificare se collidono o meno con quelli di altri gruppi. Le parti all'interno di gruppi non-collisione passano completamente attraverso l'una all'altra, anche se entrambe le parti hanno la loro proprietà CanCollide impostata su true.
Puoi facilmente impostare gruppi di collisione tramite l'editor dei Gruppi di Collisione di Studio, accessibile tramite il menu Finestra ⟩ 3D di Studio.
L'editor funziona sia in Elenco View, favorevole al docking sul lato sinistro o destro di Studio, sia in una più ampia Tabella View, che favorisce il docking in alto o in basso.

Registrazione dei gruppi
L'editor include un gruppo di collisione Predefinito che non può essere rinominato o eliminato. Tutti i BaseParts appartengono automaticamente a questo gruppo predefinito, a meno che non siano assegnati a un altro gruppo, il che significa che collidono con tutti gli altri oggetti nel gruppo Predefinito.
Per creare un nuovo gruppo di collisione:
Fai clic sul pulsante Aggiungi Gruppo nella parte superiore del pannello dell'editor, inserisci un nuovo nome di gruppo e premi Invio. Il nuovo gruppo appare in entrambe le colonne della vista a elenco, o nella colonna sinistra e nella riga superiore della vista a tabella.

Ripeti il processo se necessario, scegliendo un nome unico e descrittivo per ciascun gruppo. Nota che puoi cambiare il nome di un gruppo durante lo sviluppo facendo clic nel suo campo, o selezionandolo e facendo clic sul pulsante rinomina.

Configurare le collisioni dei gruppi
Con la configurazione predefinita, gli oggetti in tutti i gruppi collidono tra loro. Per impedire che gli oggetti in un gruppo collidano con oggetti in un altro gruppo, deseleziona la casella nella rispettiva riga/colonna.
Nell'esempio seguente, gli oggetti nel gruppo Cubetti non collidono con gli oggetti nel gruppo Porte.

Assegnare oggetti a gruppi
Per assegnare oggetti a gruppi che hai registrato tramite l'editor di Studio:
Seleziona una o più BaseParts che si qualificano come parte di un gruppo di collisione.
Assegna loro il gruppo facendo clic sul pulsante ⊕ per la sua riga. Gli oggetti possono appartenere solo a un gruppo di collisione alla volta, quindi inserirli in un nuovo gruppo li rimuove dal loro gruppo attuale.

Una volta assegnato, il nuovo gruppo è riflesso nella proprietà CollisionGroup dell'oggetto.

Gruppo di collisione StudioSelectable
Gli strumenti in Studio utilizzano il sistema di filtraggio delle collisioni per determinare quali oggetti sono candidati per la selezione quando si fa clic nella finestra di visualizzazione 3D. Gli oggetti il cui gruppo di collisione assegnato non collide con StudioSelectable verranno ignorati.
Ad esempio, se hai checkpoint in un'esperienza di corsa le cui aree efficaci sono definite da grandi parti trasparenti, puoi assegnarli a un gruppo di collisione Checkpoint e poi rendere quel gruppo non-collidabile con StudioSelectable in modo che non intralcino durante la modifica della geometria del piano sottostante.

Per il codice dei plugin, è consigliabile assegnare "StudioSelectable" come filtro del gruppo di collisione del tuo RaycastParams quando si trovano parti sotto il cursore. Questo consente ai tuoi plugin di corrispondere alla meccanica di selezione che i creatori hanno imparato a aspettarsi dagli strumenti integrati di Studio.
Raccolta consiglia del pluginlocal UserInputService = game:GetService("UserInputService")local Workspace = game:GetService("Workspace")local raycastParams = RaycastParams.new()raycastParams.CollisionGroup = "StudioSelectable" -- Per seguire la convenzioneraycastParams.BruteForceAllSlow = true -- Così le parti con CanQuery di "false" possono essere selezionatelocal mouseLocation = UserInputService:GetMouseLocation()local mouseRay = Workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)local filteredSelectionHit = Workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)
Filtraggio part-to-part
Per evitare collisioni tra due parti specifiche senza impostare gruppi di collisione, come tra la ruota di un veicolo e il suo telaio, prendi in considerazione la No Collision constraint. I vantaggi includono:
- Non sono necessari gruppi di collisione e/o script di configurazione, quindi puoi facilmente creare e condividere modelli con filtraggio collisioni personalizzato.
- Le parti collegate non collidano tra loro, ma possono comunque collidere con altri oggetti.
Disabilitare collisioni dei personaggi
I personaggi dei giocatori di Roblox collidono tra loro per impostazione predefinita. Ciò può portare a un gameplay interessante ma indesiderato, come personaggi che saltano sopra l'uno sull'altro per raggiungere aree specifiche. Se questo comportamento è indesiderato, puoi prevenire ciò tramite il seguente Script in ServerScriptService.
Script - Disabilita Collisioni dei Personaggi
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
PhysicsService:RegisterCollisionGroup("Personaggi")
PhysicsService:CollisionGroupSetCollidable("Personaggi", "Personaggi", false)
local function onDescendantAdded(descendant)
-- Imposta il gruppo di collisione per qualsiasi parte discendente
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Personaggi"
end
end
local function onCharacterAdded(character)
-- Elabora i discendenti esistenti e nuovi per la configurazione fisica
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Rileva quando il personaggio del giocatore viene aggiunto
player.CharacterAdded:Connect(onCharacterAdded)
end)
Collisioni dei modelli
Gli oggetti Model sono contenitori per parti e non ereditano da BasePart, quindi non possono connettersi direttamente agli eventi BasePart.Touched o BasePart.TouchEnded. Per determinare se un modello attiva eventi di collisione, è necessario eseguire un ciclo tra i suoi figli e connettere le funzioni onTouched() e onTouchEnded() personalizzate a ciascuna BasePart.
Il seguente esempio di codice collega tutte le BaseParts di un modello multi-part a eventi di collisione e tiene traccia del numero totale di collisioni con altre parti.
Collisione del Modello
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignora le istanze del modello che intersecano se stesse
if otherPart:IsDescendantOf(model) then return end
-- Aumenta il conteggio delle parti del modello in contatto
numTouchingParts += 1
print(model.Name, "intersecato con", otherPart.Name, "| Parti del modello in contatto:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignora le istanze del modello che non intersecano più se stesse
if otherPart:IsDescendantOf(model) then return end
-- Diminuisci il conteggio delle parti del modello in contatto
numTouchingParts -= 1
print(model.Name, "non più intersecato da", otherPart.Name, "| Parti del modello in contatto:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
end
Collisioni di mesh e modelli solidi
MeshPart e PartOperation (parti unite tramite modellazione solida) sono sottoclassi di BasePart, quindi mesh e parti modellate solidamente ereditano gli stessi eventi di collisione e opzioni di filtraggio delle collisioni come le parti normali. Tuttavia, poiché le mesh e le parti modellate solitamente hanno geometrie più complesse, presentano una particolare proprietà CollisionFidelity che determina quanto precisamente i confini fisici si allineano con la rappresentazione visiva per la gestione delle collisioni.
La proprietà CollisionFidelity ha le seguenti opzioni, in ordine di fedeltà e impatto sulle prestazioni dal più basso al più alto:
- Box — Crea una scatola di collisione limitata, ideale per oggetti piccoli o non interattivi.
- Hull — Genera un involucro convesso, adatto per oggetti con indentazioni o cavità meno pronunciate.
- Default — Produce una forma di collisione approssimativa che supporta la concavità, adatta per oggetti complessi con esigenze di interazione semi-dettagliate.
- PreciseConvexDecomposition — Offre la massima precisione ma non rappresenta comunque in modo 1:1 il visivo. Questa opzione ha il costo di prestazioni più elevato e richiede più tempo per essere elaborata dal motore.

Per ulteriori informazioni sull'impatto delle prestazioni delle opzioni di fedeltà delle collisioni e su come mitigarle, vedere Ottimizzazione delle prestazioni.