Una colisión ocurre cuando dos objetos 3D entran en contacto dentro del mundo 3D. Para un manejo de colisiones personalizado, BasePart tiene un conjunto de eventos de colisión y técnicas de filtrado de colisión, para que puedas controlar qué ensamblajes físicos colisionan con otros.
Eventos de colisión
Los eventos de colisión ocurren cuando dos BaseParts tocan o dejan de tocarse en el mundo 3D. Puedes detectar estas colisiones a través de los eventos Touched y TouchEnded, que ocurren independientemente del valor de la propiedad CanCollide de cualquiera de las partes. Al considerar el manejo de colisiones en partes, ten en cuenta lo siguiente:
- La propiedad CanTouch de una parte determina si activa eventos de colisión. Si se establece en false, ni Touched ni TouchEnded se activarán.
- La propiedad CanCollide de una parte afecta si colisionará físicamente con otras partes y causará fuerzas que actúen sobre ellas. Incluso si CanCollide está deshabilitado para una parte, puedes detectar el toque y la no‑interacción a través de los eventos Touched y TouchEnded.
- Los eventos Touched y TouchEnded solo se activan como resultado de un movimiento físico, no de cambios en Position o CFrame que causen que una parte interseccione o deje de interseccionar otra parte.
Tocado
El evento Touched se activa cuando un BasePart entra en contacto con otro, o con un vóxel de Terrain. Solo se activa como resultado de una simulación física y no se activará cuando la Position o CFrame de la parte se establezca explícitamente de tal manera que interseccione con otra parte o vóxel.
El siguiente patrón de código muestra cómo el evento Touched puede conectarse a una función personalizada onTouched(). Ten en cuenta que el evento envía el argumento otherPart a la función, indicando la otra parte involucrada en la colisión.
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouched(otherPart)
print(part.Name .. " colisionó con " .. otherPart.Name)
end
part.Touched:Connect(onTouched)Ten en cuenta que el evento Touched puede activarse múltiples veces en rápida sucesión debido a colisiones físicas sutiles, como cuando un objeto en movimiento "se asienta" en una posición de reposo o cuando una colisión involucra un modelo de múltiples partes. Para evitar activar más eventos Touched de los necesarios, puedes implementar un sistema de debounce simple que imponga un período de "enfriamiento" a través de un atributo de instancia.
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 .. " colisionó con " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Establecer atributo en verdadero
task.wait(COOLDOWN_TIME) -- Esperar la duración del enfriamiento
part:SetAttribute("Touched", false) -- Reiniciar atributo
end
end
part.Touched:Connect(onTouched)TouchEnded
El evento TouchEnded se activa cuando los límites de colisión completos de un BasePart salen de los límites de otro BasePart o de un vóxel de Terrain lleno. Solo se activa como resultado de una simulación física y no se activará cuando la Position o CFrame de la parte se establezca explícitamente de tal manera que deje de interseccionar con otra parte o vóxel.
El siguiente patrón de código muestra cómo el evento TouchEnded puede conectarse a una función personalizada onTouchEnded(). Al igual que Touched, el evento envía el argumento otherPart a la función, indicando la otra parte involucrada.
local Workspace = game:GetService("Workspace")
local part = Workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " ya no está tocando " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)Filtrado de colisiones
El filtrado de colisiones define qué partes físicas colisionan con otras. Puedes configurar el filtrado para numerosos objetos a través de grupos de colisión o puedes controlar las colisiones de manera parte a parte con instancias de NoCollisionConstraint.
Grupos de colisión
Los grupos de colisión te permiten asignar BaseParts a grupos dedicados y especificar si colisionan o no con aquellos en otros grupos. Las partes dentro de grupos no colisionantes pasan completamente a través de cada una, incluso si ambas partes tienen su propiedad CanCollide establecida en true.
Puedes configurar fácilmente grupos de colisión a través del editor de Grupos de Colisión de Studio, accesible a través del menú Ventana ⟩ 3D de Studio.
El editor funciona en Vista de Lista que favorece el anclaje al lado izquierdo o derecho de Studio, o en una más amplia Vista de Tabla, que favorece el anclaje en la parte superior o inferior.

Registrar grupos
El editor incluye un grupo de colisión Predeterminado que no se puede renombrar ni eliminar. Todos los BaseParts pertenecen automáticamente a este grupo predeterminado a menos que se asignen a otro grupo, lo que significa que colisionarán con todos los demás objetos en el grupo Predeterminado.
Para crear un nuevo grupo de colisión:
Haz clic en el botón Agregar Grupo en la parte superior del panel del editor, ingresa un nuevo nombre de grupo y presiona Enter. El nuevo grupo aparecerá en ambas columnas de la vista de lista, o en la columna izquierda y la fila superior de la vista de tabla.

Repite el proceso si es necesario, eligiendo un nombre único y descriptivo para cada grupo. Ten en cuenta que puedes cambiar el nombre de un grupo durante el desarrollo haciendo clic en su campo, o seleccionándolo y haciendo clic en el botón renombrar.

Configurar colisiones de grupos
Bajo la configuración predeterminada, los objetos en todos los grupos colisionan entre sí. Para evitar que los objetos en un grupo colisionen con objetos en otro grupo, desmarca la casilla en la fila/columna respectiva.
En el siguiente ejemplo, los objetos en el grupo Cubes no colisionarán con objetos en el grupo Doors.

Asignar objetos a grupos
Para asignar objetos a grupos que has registrado a través del editor de Studio:
Selecciona uno o más BaseParts que califiquen como parte de un grupo de colisión.
Asígnalos al grupo haciendo clic en el botón ⊕ para su fila. Los objetos solo pueden pertenecer a un grupo de colisión a la vez, por lo que colocarlos en un nuevo grupo los elimina de su grupo actual.

Una vez asignados, el nuevo grupo se refleja en la propiedad CollisionGroup del objeto.

Grupo de colisión StudioSelectable
Las herramientas en Studio utilizan el sistema de filtrado de colisiones para determinar qué objetos son candidatos para la selección al hacer clic en el viewport 3D. Los objetos cuyo grupo de colisión asignado no colisiona con StudioSelectable serán ignorados.
Por ejemplo, si tienes puntos de control en un juego de carreras cuyas áreas efectivas están definidas por grandes partes transparentes, puedes asignarlas a un grupo de colisión Checkpoints y luego hacer que ese grupo no colisione con StudioSelectable para que no interfieran cuando estés editando la geometría del mapa subyacente.

Para el código de plugins, se recomienda que asignes "StudioSelectable" como el filtro de grupo de colisión de tu RaycastParams al encontrar partes bajo el cursor. Esto permite que tus plugins coincidan con la mecánica de selección que los creadores han aprendido a esperar de las herramientas integradas de Studio.
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- Para seguir la convención
raycastParams.BruteForceAllSlow = true -- Para que las partes con CanQuery de "false" puedan ser seleccionadas
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = Workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = Workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)Filtrado de parte a parte
Para evitar colisiones entre dos partes específicas sin configurar grupos de colisión, como entre la rueda de un vehículo y su chasis, considera la No Collision constraint. Las ventajas incluyen:
- No se requieren grupos de colisión y/o scripts de configuración, por lo que puedes crear y compartir modelos fácilmente con filtrado de colisión personalizado.
- Las partes conectadas no colisionarán entre sí, pero aún pueden colisionar con otros objetos.
Desactivar colisiones de personajes
Los personajes de los jugadores de Roblox colisionan entre sí por defecto. Esto puede llevar a jugabilidad interesante pero no intencionada, como personajes saltando unos sobre otros para alcanzar áreas específicas. Si este comportamiento es indeseable, puedes prevenirlo a través del siguiente Script en ServerScriptService.
local PhysicsService = game:GetService("PhysicsService")
local Players = game:GetService("Players")
PhysicsService:RegisterCollisionGroup("Characters")
PhysicsService:CollisionGroupSetCollidable("Characters", "Characters", false)
local function onDescendantAdded(descendant)
-- Establecer grupo de colisión para cualquier parte descendiente
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Characters"
end
end
local function onCharacterAdded(character)
-- Procesar descendientes existentes y nuevos para la configuración de física
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Detectar cuando se agrega el personaje del jugador
player.CharacterAdded:Connect(onCharacterAdded)
end)Colisiones de modelos
Los objetos Model son contenedores para partes en lugar de heredar de BasePart, por lo que no pueden conectarse directamente a los eventos BasePart.Touched o BasePart.TouchEnded. Para determinar si un modelo activa eventos de colisión, necesitas recorrer sus hijos y conectar las funciones personalizadas onTouched() y onTouchEnded() a cada BasePart hijo.
El siguiente ejemplo de código conecta todas las BaseParts de un modelo de múltiples partes a eventos de colisión y rastrea el número total de colisiones con otras partes.
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- Ignorar instancias del modelo intersecando consigo mismo
if otherPart:IsDescendantOf(model) then return end
-- Aumentar el conteo de partes del modelo tocando
numTouchingParts += 1
print(model.Name, "intersectó con", otherPart.Name, "| Partes del modelo tocando:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignorar instancias del modelo no intersectando consigo mismo
if otherPart:IsDescendantOf(model) then return end
-- Disminuir el conteo de partes del modelo tocando
numTouchingParts -= 1
print(model.Name, "no intersectó más con", otherPart.Name, "| Partes del modelo tocando:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
endColisiones de malla y modelo sólido
MeshPart y PartOperation (partes unidas por modelado sólido) son subclases de BasePart, por lo que las partes de malla y modeladas sólidamente heredan los mismos eventos de colisión y opciones de filtrado de colisión que las partes regulares. Sin embargo, dado que las partes de malla y modeladas sólidamente suelen tener geometrías más complejas, tienen una propiedad distintiva CollisionFidelity que determina cuán precisamente los límites físicos se alinean con la representación visual para el manejo de colisiones.
La propiedad CollisionFidelity tiene las siguientes opciones, en orden de fidelidad e impacto en el rendimiento de menor a mayor:
- Caja — Crea una caja de colisión delimitadora, ideal para objetos pequeños o no interactivos.
- Casco — Genera un casco convexo, adecuado para objetos con indentaciones o cavidades menos pronunciadas.
- Predeterminado — Produce una forma de colisión aproximada que admite concavidad, adecuada para objetos complejos con necesidades de interacción semi-detalladas.
- Descomposición Convexa Precisa — Ofrece la fidelidad más precisa pero aún no es una representación 1:1 de lo visual. Esta opción tiene el costo de rendimiento más alto y toma más tiempo para que el motor lo calcule.

Para más información sobre el impacto en el rendimiento de las opciones de fidelidad de colisión y cómo mitigarlas, consulta Optimización del rendimiento.