Una collisione si verifica quando due oggetti 3D entrano in contatto all'interno del mondo 3D. Per una gestione personalizzata delle collisioni, BasePart ha 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. Puoi rilevare queste collisioni attraverso gli eventi Touched e TouchEnded, che si verificano indipendentemente dal valore della proprietà CanCollide di ciascun pezzo. Quando consideri la gestione delle collisioni sui pezzi, nota quanto segue:
- La proprietà CanTouch di un pezzo determina se attiva eventi di collisione. Se impostata su false, né Touched né TouchEnded verranno attivati.
- La proprietà CanCollide di un pezzo influisce su se esso colliderà fisicamente con altri pezzi e causerà forze su di essi. Anche se CanCollide è disabilitato per un pezzo, puoi rilevare il contatto e il non contatto attraverso gli eventi Touched e TouchEnded.
- Gli eventi Touched e TouchEnded si attivano solo a seguito di un movimento fisico, non da cambiamenti nella Position o CFrame che causano l'intersezione o la cessazione dell'intersezione con un altro pezzo.
Touched
L'evento Touched si attiva quando un BasePart entra in contatto con un altro, o con un voxel di Terrain. Si attiva solo a seguito di una simulazione fisica e non si attiverà quando la Position o la CFrame del pezzo è impostata esplicitamente in modo tale da intersecare un altro pezzo o voxel.
Il seguente schema di codice mostra come l'evento Touched può essere collegato a una funzione personalizzata onTouched(). Nota che l'evento invia l'argomento otherPart alla funzione, indicando l'altro pezzo coinvolto nella collisione.
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‑pezzo. Per evitare di attivare più eventi Touched del necessario, puoi implementare un semplice sistema di debounce che impone un periodo di "raffreddamento" attraverso un attributo d'istanza.
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) -- Attendi la durata del raffreddamento
part:SetAttribute("Touched", false) -- Ripristina l'attributo
end
end
part.Touched:Connect(onTouched)TouchEnded
L'evento TouchEnded si attiva quando l'intero volume di collisione di un BasePart esce dai confini di un altro BasePart o di un voxel di Terrain riempito. Si attiva solo a seguito di una simulazione fisica e non si attiverà quando la Position o la CFrame del pezzo è impostata esplicitamente in modo tale da smettere di intersecare un altro pezzo o voxel.
Il seguente schema di codice mostra come l'evento TouchEnded può essere collegato a una funzione personalizzata onTouchEnded(). Come Touched, l'evento invia l'argomento otherPart alla funzione, indicando l'altro pezzo coinvolto.
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 attraverso gruppi di collisione oppure puoi controllare le collisioni su base pezzo‑a‑pezzo con istanze di NoCollisionConstraint.
Gruppi di collisione
I gruppi di collisione ti permettono di assegnare BaseParts a gruppi dedicati e specificare se collidono o meno con quelli di altri gruppi. I pezzi all'interno di gruppi non collidenti passano completamente attraverso l'uno e l'altro, anche se entrambi i pezzi hanno la loro proprietà CanCollide impostata su true. I gruppi di collisione vengono creati e configurati su base Workspace o WorldModel.
Puoi facilmente impostare gruppi di collisione attraverso l'editor di Gruppi di Collisione di Studio, accessibile attraverso il menu Finestra ⟩ 3D di Studio.
Registrare gruppi
Workspace memorizza il proprio stato configurabile dei gruppi di collisione. Inoltre, qualsiasi WorldModel può optare per utilizzare i propri gruppi di collisione per le query.
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 collideranno con tutti gli altri oggetti nel gruppo Predefinito.
Per creare un nuovo gruppo di collisione:
Per impostazione predefinita, i gruppi vengono registrati su Workspace, ma se hai almeno un WorldModel nel tuo posto, un menu a discesa di selezione apparirà nella parte superiore dell'editor dei gruppi di collisione. Usa il menu a discesa per configurare i gruppi di collisione attraverso diverse istanze di WorldModel.

Per qualsiasi WorldModel, puoi attivare Usa gruppi di collisione di Workspace per farlo utilizzare i gruppi di collisione di Workspace per le sue query.

Clicca sul pulsante Aggiungi Gruppo lungo la 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 elenco, o in entrambe la colonna sinistra e la riga superiore della vista 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
Sotto la configurazione predefinita, gli oggetti in tutti i gruppi collidono tra loro. Per impedire agli oggetti in un gruppo di collidere con oggetti in un altro gruppo, deseleziona la casella nella rispettiva riga/colonna.
Nell'esempio seguente, gli oggetti nel gruppo Cubi non collideranno con gli oggetti nel gruppo Porte.

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

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

Gruppo 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 nel viewport 3D. Gli oggetti il cui gruppo di collisione assegnato non collida con StudioSelectable verranno ignorati.
Ad esempio, se hai checkpoint in un gioco di corse le cui aree efficaci sono definite da grandi pezzi trasparenti, puoi assegnarli a un gruppo di collisione Checkpoint e poi rendere quel gruppo non collidabile con StudioSelectable in modo che non ostacolino quando stai modificando la geometria della mappa sottostante.

Per il codice del plugin, è consigliato assegnare "StudioSelectable" come filtro del gruppo di collisione dei tuoi RaycastParams quando trovi pezzi sotto il cursore. Questo consente ai tuoi plugin di abbinare le meccaniche di selezione che i creatori hanno imparato a aspettarsi dagli strumenti integrati di Studio.
local UserInputService = game:GetService("UserInputService")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- Per seguire la convenzione
raycastParams.BruteForceAllSlow = true -- In modo che i pezzi con CanQuery di "false" possano essere selezionati
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)Filtraggio pezzo-a-pezzo
Per prevenire collisioni tra due pezzi specifici senza impostare gruppi di collisione, come tra la ruota di un veicolo e il suo telaio, considera il No Collision vincolo. I vantaggi includono:
- Non sono richiesti gruppi di collisione e/o script di configurazione, quindi puoi facilmente creare e condividere modelli con filtraggio delle collisioni personalizzato.
- I pezzi connessi non collidono tra loro, ma possono comunque collidere con altri oggetti.
Disabilitare le collisioni dei personaggi
I personaggi dei giocatori di Roblox collidono tra loro per impostazione predefinita. Questo può portare a gioco interessante ma indesiderato, come personaggi che saltano l'uno sopra l'altro per raggiungere aree specifiche. Se questo comportamento è indesiderato, puoi prevenirlo attraverso il seguente Script in ServerScriptService.
local Players = game:GetService("Players")
workspace:RegisterCollisionGroup("Personaggi")
workspace: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 pezzi piuttosto che ereditare da BasePart, quindi non possono collegarsi direttamente agli eventi BasePart.Touched o BasePart.TouchEnded. Per determinare se un modello attiva eventi di collisione, devi scorrere i suoi figli e collegare le funzioni personalizzate onTouched() e onTouchEnded() a ciascun BasePart figlio.
Il seguente esempio di codice collega tutti i BaseParts di un modello multi‑pezzo agli eventi di collisione e tiene traccia del numero totale di collisioni con altri pezzi.
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignora le istanze del modello che si intersecano con se stesse
if otherPart:IsDescendantOf(model) then return end
-- Aumenta il conteggio dei pezzi del modello che toccano
numTouchingParts += 1
print(model.Name, "si è intersecato con", otherPart.Name, "| Pezzi del modello che toccano:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignora le istanze del modello che smettono di intersecarsi con se stesse
if otherPart:IsDescendantOf(model) then return end
-- Diminuisci il conteggio dei pezzi del modello che toccano
numTouchingParts -= 1
print(model.Name, "non si è più intersecato con", otherPart.Name, "| Pezzi del modello che toccano:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
endCollisioni di mesh e modelli solidi
MeshPart e PartOperation (pezzi uniti tramite modellazione solida) sono sottoclassi di BasePart, quindi le mesh e i pezzi modellati solidi ereditano gli stessi eventi di collisione e opzioni di filtraggio delle collisioni come i pezzi normali. Tuttavia, poiché le mesh e i pezzi modellati solidi di solito hanno geometrie più complesse, hanno una distintiva 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 delimitante, 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 fedeltà ma non una rappresentazione 1:1 del visivo. Questa opzione ha il costo di prestazioni più elevato e richiede più tempo per essere calcolata dal motore.

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