Une collision se produit lorsque deux objets 3D entrent en contact dans le monde 3D. Pour une gestion personnalisée des collisions, BasePart dispose d'un ensemble d'événements de collision et de techniques de filtrage de collision, vous permettant de contrôler quels assemblages physiques entrent en collision avec d'autres.
Événements de collision
Les événements de collision se produisent lorsque deux BaseParts se touchent ou cessent de se toucher dans le monde 3D. Vous pouvez détecter ces collisions via les événements Touched et TouchEnded, qui se produisent indépendamment de la valeur de la propriété CanCollide de chaque partie. Lors de la prise en compte de la gestion des collisions sur les parties, notez ce qui suit :
- La propriété CanTouch d'une partie détermine si elle déclenche des événements de collision. Si elle est définie sur false, ni Touched ni TouchEnded ne seront déclenchés.
- La propriété CanCollide d'une partie affecte si elle va physiquement entrer en collision avec d'autres parties et provoquer des forces agissant sur elles. Même si CanCollide est désactivé pour une partie, vous pouvez détecter le contact et le non-contact via les événements Touched et TouchEnded.
- Les événements Touched et TouchEnded ne se déclenchent que suite à un mouvement physique, et non à des changements de Position ou CFrame qui provoquent une intersection ou une cessation d'intersection avec une autre partie.
Touché
L'événement Touched se déclenche lorsqu'une BasePart entre en contact avec une autre, ou avec un voxel de Terrain. Il ne se déclenche que suite à une simulation physique et ne se déclenchera pas lorsque la Position ou la CFrame de la partie est explicitement définie de manière à intercepter une autre partie ou un voxel.
Le modèle de code suivant montre comment l'événement Touched peut être connecté à une fonction personnalisée onTouched(). Notez que l'événement envoie l'argument otherPart à la fonction, indiquant l'autre partie impliquée dans la collision.
local part = workspace.Part
local function onTouched(otherPart)
print(part.Name .. " a heurté " .. otherPart.Name)
end
part.Touched:Connect(onTouched)Notez que l'événement Touched peut se déclencher plusieurs fois en succession rapide en raison de collisions physiques subtiles, comme lorsque un objet en mouvement "se stabilise" dans une position de repos ou lorsqu'une collision implique un modèle multi-part. Pour éviter de déclencher plus d'événements Touched que nécessaire, vous pouvez mettre en œuvre un simple système de debounce qui impose une période de "refroidissement" via un attribut.
local part = workspace.Part
local COOLDOWN_TIME = 1
local function onTouched(otherPart)
if not part:GetAttribute("Touched") then
print(part.Name .. " a heurté " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Définir l'attribut sur true
task.wait(COOLDOWN_TIME) -- Attendre la durée de refroidissement
part:SetAttribute("Touched", false) -- Réinitialiser l'attribut
end
end
part.Touched:Connect(onTouched)TouchEnded
L'événement TouchEnded se déclenche lorsque l'ensemble des limites de collision d'une BasePart sort des limites d'une autre BasePart ou d'un voxel de Terrain rempli. Il ne se déclenche que suite à une simulation physique et ne se déclenchera pas lorsque la Position ou la CFrame de la partie est explicitement définie de manière à cesser d'intercepter une autre partie ou un voxel.
Le modèle de code suivant montre comment l'événement TouchEnded peut être connecté à une fonction personnalisée onTouchEnded(). Comme pour Touched, l'événement envoie l'argument otherPart à la fonction, indiquant l'autre partie impliquée.
local part = workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " ne touche plus " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)Résumés de collision
Touched vous indique qu'une collision s'est produite, mais pas où elle s'est produite, de quelle direction elle est venue, ou à quelle intensité. Pour obtenir des données de contact détaillées du moteur physique, appelez BindToCollisionSummaries() sur une partie. Cela prend un rappel et renvoie un RBXScriptConnection que vous pouvez déconnecter lorsque vous n'avez plus besoin des données. C'est une API distincte de Touched, donc ne l'appelez pas depuis l'intérieur d'un gestionnaire Touched.
Le rappel s'exécute une fois par image, après que l'étape physique soit terminée. Il reçoit une table avec un résumé de chaque collision à laquelle la partie a participé pendant cette image. Chaque résumé décrit un point de contact entre la partie abonnée et une autre partie. Les résumés sont figés et ne peuvent pas être modifiés. Chacun a ces champs :
| Champ | Type | Description |
|---|---|---|
| Time | number | Temps de simulation du sous-étape. |
| Part0 | BasePart | La partie abonnée. |
| Part1 | BasePart | L'autre partie dans la paire. |
| Point | Vector3 | Point de contact moyen, dans l'espace mondial. |
| Normal | Vector3 | Normale unitaire. Elle pointe toujours loin de Part0. |
| RelativeVelocity | Vector3 | Vitesse de Part1 par rapport à Part0 au point de contact, mesurée avant que le solveur ne résolve la collision. |
| Area | number | Aire estimée de la zone de contact. |
Pour obtenir la vitesse d'impact frontale, prenez le produit scalaire de RelativeVelocity et Normal. Pour détecter des impacts glissants ou des glissements, utilisez la composante tangentielle de RelativeVelocity. Si vous souhaitez une valeur plus proche d'une force, combinez la vitesse avec la AssemblyMass des parties.
local part = workspace.Part
local function onCollision(summaries)
for _, summary in summaries do
local impactSpeed = summary.RelativeVelocity:Dot(summary.Normal)
if impactSpeed > 10 then
print("Impact fort à", summary.Point, "avec une vitesse de", impactSpeed)
end
end
end
local connection = part:BindToCollisionSummaries(onCollision)
-- Plus tard, lorsque vous n'avez plus besoin des résumés
connection:Disconnect()Gardez à l'esprit ce qui suit lorsque vous utilisez des résumés de collision :
- Les résumés ne sont générés que sur le propriétaire du réseau qui exécute la simulation physique, qui peut être un client ou le serveur. Ils ne sont pas répliqués. Si d'autres clients doivent connaître une collision, traitez le résumé et envoyez uniquement les données dont ils ont besoin via votre propre événement distant.
- Les parties avec CanCollide définies sur false ne produisent pas de résumés de collision.
- Les parties non convexes complexes peuvent produire plus d'un résumé pour la même paire de parties.
- Les contacts entre deux parties endormies ne sont pas enregistrés.
- Le coût de traitement augmente avec le nombre de parties abonnées, et non avec le nombre total de collisions dans le lieu.
Filtrage de collision
Le filtrage de collision définit quelles parties physiques entrent en collision avec d'autres. Vous pouvez configurer le filtrage pour de nombreux objets via des groupes de collision ou vous pouvez contrôler les collisions sur une base partie-à-partie avec des instances NoCollisionConstraint.
Groupes de collision
Les groupes de collision vous permettent d'assigner des BaseParts à des groupes dédiés et de spécifier s'ils entrent ou non en collision avec ceux d'autres groupes. Les parties au sein de groupes non-collidants passent complètement à travers les autres, même si les deux parties ont leur propriété CanCollide définie sur true. Les groupes de collision sont créés et configurés sur une base Workspace ou WorldModel.
Vous pouvez facilement configurer des groupes de collision via l'éditeur Groupes de Collision de Studio, accessible via le menu Fenêtre ⟩ 3D de Studio.
Enregistrer des groupes
Workspace stocke son propre état configurable des groupes de collision. De plus, tout WorldModel peut choisir d'utiliser ses propres groupes de collision pour les requêtes.
L'éditeur comprend un groupe de collision Par défaut qui ne peut pas être renommé ou supprimé. Tous les BaseParts appartiennent automatiquement à ce groupe par défaut, sauf s'ils sont assignés à un autre groupe, ce qui signifie qu'ils entreront en collision avec tous les autres objets dans le groupe Par défaut.
Pour créer un nouveau groupe de collision :
Par défaut, les groupes sont enregistrés sur Workspace, mais si vous avez au moins un WorldModel dans votre lieu, un menu déroulant de sélection apparaîtra en haut de l'éditeur de groupes de collision. Utilisez le menu déroulant pour configurer des groupes de collision à travers différentes instances de WorldModel.

Pour tout WorldModel, vous pouvez activer Utiliser les groupes de collision de l'espace de travail pour le faire utiliser les groupes de collision de Workspace pour ses requêtes.

Cliquez sur le bouton Ajouter un groupe en haut du panneau de l'éditeur, entrez un nouveau nom de groupe et appuyez sur Entrée. Le nouveau groupe apparaît dans les deux colonnes de la vue liste, ou dans la colonne de gauche et la ligne supérieure de la vue tableau.

Répétez le processus si nécessaire, en choisissant un nom unique et descriptif pour chaque groupe. Notez que vous pouvez changer le nom d'un groupe pendant le développement en cliquant dans son champ, ou en le sélectionnant et en cliquant sur le bouton renommer.

Configurer les collisions de groupe
Sous la configuration par défaut, les objets de tous les groupes entrent en collision les uns avec les autres. Pour empêcher les objets d'un groupe d'entrer en collision avec des objets d'un autre groupe, décochez la case dans la ligne/colonne respective.
Dans l'exemple suivant, les objets du groupe Cubes ne entreront pas en collision avec les objets du groupe Portes.

Assigner des objets à des groupes
Pour assigner des objets à des groupes que vous avez enregistrés via l'éditeur de Studio :
Sélectionnez une ou plusieurs BaseParts qui qualifient comme partie d'un groupe de collision.
Assignez-les au groupe en cliquant sur le bouton ⊕ pour sa ligne. Les objets ne peuvent appartenir qu'à un seul groupe de collision à la fois, donc les placer dans un nouveau groupe les retire de leur groupe actuel.

Une fois assigné, le nouveau groupe est reflété sous la propriété CollisionGroup de l'objet.

Groupe StudioSelectable
Les outils dans Studio utilisent le système de filtrage de collision pour déterminer quels objets sont candidats à la sélection lors d'un clic dans la vue 3D. Les objets dont le groupe de collision assigné ne entre pas en collision avec StudioSelectable seront ignorés.
Par exemple, si vous avez des points de contrôle dans un jeu de course dont les zones effectives sont définies par de grandes parties transparentes, vous pouvez les assigner à un groupe de collision Points de Contrôle et ensuite faire en sorte que ce groupe ne soit pas collidable avec StudioSelectable afin qu'ils ne gênent pas lorsque vous éditez la géométrie de la carte sous-jacente.

Pour le code de plugin, il est recommandé d'assigner "StudioSelectable" comme filtre de groupe de collision de vos RaycastParams lors de la recherche de parties sous le curseur. Cela permet à vos plugins de correspondre aux mécaniques de sélection que les créateurs ont appris à attendre des outils intégrés de Studio.
local UserInputService = game:GetService("UserInputService")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- Pour suivre la convention
raycastParams.BruteForceAllSlow = true -- Pour que les parties avec CanQuery de "false" puissent être sélectionnées
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)Filtrage partie-à-partie
Pour empêcher les collisions entre deux parties spécifiques sans configurer des groupes de collision, comme entre la roue d'un véhicule et son châssis, envisagez la contrainte No Collision. Les avantages incluent :
- Les groupes de collision et/ou les scripts de configuration ne sont pas nécessaires, vous pouvez donc facilement créer et partager des modèles avec un filtrage de collision personnalisé.
- Les parties connectées ne vont pas entrer en collision les unes avec les autres, mais elles peuvent toujours entrer en collision avec d'autres objets.
Désactiver les collisions de personnage
Les personnages joueurs de Roblox entrent en collision les uns avec les autres par défaut. Cela peut conduire à un gameplay intéressant mais non intentionnel, comme des personnages sautant les uns sur les autres pour atteindre des zones spécifiques. Si ce comportement est indésirable, vous pouvez l'empêcher via le script suivant dans ServerScriptService.
local Players = game:GetService("Players")
workspace:RegisterCollisionGroup("Personnages")
workspace:CollisionGroupSetCollidable("Personnages", "Personnages", false)
local function onDescendantAdded(descendant)
-- Définir le groupe de collision pour toute partie descendante
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Personnages"
end
end
local function onCharacterAdded(character)
-- Traiter les descendants existants et nouveaux pour la configuration physique
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Détecter quand le personnage du joueur est ajouté
player.CharacterAdded:Connect(onCharacterAdded)
end)Collisions de modèle
Les objets Model sont des conteneurs pour des parties plutôt que d'hériter de BasePart, donc ils ne peuvent pas se connecter directement aux événements BasePart.Touched ou BasePart.TouchEnded. Pour déterminer si un modèle déclenche des événements de collision, vous devez parcourir ses enfants et connecter les fonctions personnalisées onTouched() et onTouchEnded() à chaque enfant BasePart.
Le modèle de code suivant connecte toutes les BaseParts d'un modèle multi-part aux événements de collision et suit le nombre total de collisions avec d'autres parties.
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignorer les instances du modèle s'interceptant elles-mêmes
if otherPart:IsDescendantOf(model) then return end
-- Augmenter le compte des parties du modèle touchant
numTouchingParts += 1
print(model.Name, "s'est intersecté avec", otherPart.Name, "| Parties du modèle touchant :", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignorer les instances du modèle cessant de s'intercepter
if otherPart:IsDescendantOf(model) then return end
-- Diminuer le compte des parties du modèle touchant
numTouchingParts -= 1
print(model.Name, "s'est désintersecté de", otherPart.Name, "| Parties du modèle touchant :", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
endCollisions de maillage et de modèle solide
Les MeshPart et PartOperation (parties jointes par modélisation solide) sont des sous-classes de BasePart, donc les maillages et les parties modélisées solides héritent des mêmes événements de collision et options de filtrage de collision que les parties régulières. Cependant, comme les maillages et les parties modélisées solides ont généralement des géométries plus complexes, elles ont une propriété distinctive CollisionFidelity qui détermine à quel point les limites physiques s'alignent précisément avec la représentation visuelle pour la gestion des collisions.
La propriété CollisionFidelity a les options suivantes, par ordre de fidélité et d'impact sur les performances, du plus bas au plus élevé :
- Boîte — Crée une boîte de collision englobante, idéale pour les objets petits ou non interactifs.
- Coque — Génère une coque convexe, adaptée aux objets avec moins d'indentations ou de cavités prononcées.
- Par défaut — Produit une forme de collision approximative qui supporte la concavité, adaptée aux objets complexes avec des besoins d'interaction semi-détaillés.
- Décomposition Convexe Précise — Offre la fidélité la plus précise mais pas une représentation 1:1 de la visuelle. Cette option a le coût de performance le plus élevé et prend plus de temps pour que le moteur calcule.

Pour plus d'informations sur l'impact des performances des options de fidélité de collision et comment les atténuer, voir optimisation des performances.