Una colisión ocurre cuando dos objetos 3D entran en contacto dentro del mundo 3D. Para el manejo de colisiones personalizado, BasePart tiene un conjunto de eventos de colisión y técnicas de filtrado de colisión, por lo que puedes controlar qué ensamblajes físicos colisionan con otros.
Eventos de colisión
Los eventos de colisión ocurren cuando dos BaseParts se 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 cada parte. Al considerar el manejo de colisiones en partes, ten en cuenta lo siguiente:
- La propiedad CanTouch de una parte determina si desencadena eventos de colisión. Si se establece en false, tanto Touched como TouchEnded no se activarán.
- La propiedad CanCollide de una parte afecta a 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 tocados y no tocados 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 intersecar 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 la simulación física y no se activará cuando la Position o CFrame de la parte se establezca explícitamente de tal manera que interseque 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.
Colisión de Parte
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 basado en 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 varias partes. Para evitar activar más eventos Touched de los necesarios, puedes implementar un simple sistema de debounce que imponga un período de "enfriamiento" a través de un atributo de instancia.
Colisión de Parte Con Enfriamiento
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 como verdadero
task.wait(COOLDOWN_TIME) -- Esperar la duración del enfriamiento
part:SetAttribute("Touched", false) -- Restablecer atributo
end
end
part.Touched:Connect(onTouched)
Tocado Finalizado
El evento TouchEnded se activa cuando completamente el alcance de colisión de un BasePart sale del alcance de otro BasePart o de un vóxel de Terrain lleno. Solo se activa como resultado de la 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 intersecar 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.
Detección de No Colisión
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 en una base parte a parte usando 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 a través de cada una completamente, incluso si ambas partes tienen su propiedad CanCollide establecida en true.
Puedes configurar fácilmente los 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 acoplamiento al lado izquierdo o derecho de Studio, o en una más amplia Vista de Tabla, que favorece el acoplamiento en la parte superior o inferior.

Registrar grupos
El editor incluye un grupo de colisión Predeterminado que no puede ser renombrado o eliminado. 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 Añadir Grupo en la parte superior del panel del editor, ingresa un nuevo nombre de grupo y presiona Enter. El nuevo grupo aparece en ambas columnas de la vista de lista, o en ambas columnas de la izquierda y 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 de un grupo colisionen con objetos de otro grupo, desmarca la casilla en la fila/columna respectiva.
En el siguiente ejemplo, los objetos del grupo Cubes no colisionarán con los objetos del 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.
Asignalos 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, así que colocarlos en un nuevo grupo los elimina de su grupo actual.

Una vez asignado, 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 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 una experiencia de carreras cuyos áreas efectivas están definidas por grandes partes transparentes, puedes asignarlos a un grupo de colisión Checkpoints y luego hacer que ese grupo no sea colisionable con StudioSelectable para que no interfieran cuando estés editando la geometría subyacente del mapa.

Para el código de plugins, se recomienda que asignes "StudioSelectable" como el filtro de grupo de colisión de tus 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.
Recomendación de Selección de Plugin Raycastlocal UserInputService = game:GetService("UserInputService")local Workspace = game:GetService("Workspace")local raycastParams = RaycastParams.new()raycastParams.CollisionGroup = "StudioSelectable" -- Para seguir la convenciónraycastParams.BruteForceAllSlow = true -- Para que partes con CanQuery de "false" puedan ser seleccionadaslocal 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 prevenir 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 Colisión constraint. Las ventajas incluyen:
- No se requieren grupos de colisión y/o scripts de configuración, por lo que puedes crear y compartir fácilmente modelos 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 jugadores de Roblox colisionan entre sí de manera predeterminada. Esto puede llevar a un juego interesante pero no intencionado, como personajes saltando unos sobre otros para alcanzar áreas específicas. Si este comportamiento no es deseable, puedes prevenirlo a través del siguiente Script en ServerScriptService.
Script - Desactivar Colisiones de Personajes
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 añade 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 un evento de colisión, necesitas iterar a través de sus hijos y conectar las funciones personalizadas onTouched() y onTouchEnded() a cada hijo BasePart.
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.
Colisión de Modelo
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, "intersectado con", otherPart.Name, "| Partes del modelo tocando:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignorar instancias del modelo desintersectando consigo mismo
if otherPart:IsDescendantOf(model) then return end
-- Disminuir el conteo de partes del modelo tocando
numTouchingParts -= 1
print(model.Name, "desintersectado de", 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
end
Colisiones de mallas y modelos sólidos
MeshPart y PartOperation (partes unidas por modelado sólido) son subclases de BasePart, por lo que las mallas y las partes 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 mallas y las partes modeladas sólidamente suelen tener geometrías más complejas, poseen una propia propiedad 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 — Proporciona una forma de colisión aproximada que soporta la concavidad, adecuada para objetos complejos con necesidades de interacción semi-detalhadas.
- 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 del rendimiento de las opciones de fidelidad de colisión y cómo mitigarlas, consulta Optimización del rendimiento.