Colisiones

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

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.
  • La clase de nivel superior Terrain hereda de BasePart, por lo que puedes asignar un grupo de colisión a Terrain para determinar si otros BaseParts colisionan con los vóxeles de Terrain.

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.

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 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.

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 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.

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 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.

En el video anterior, los objetos giratorios están en diferentes grupos de colisión de tal manera que colisionan con objetos de otro color pero no con objetos de su propio color

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.

Ejemplo de Vista de Lista en el Editor de Grupos de Colisión

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:

  1. 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.

    Nuevo grupo agregado al Editor de Grupos de Colisión en Vista de Lista
  2. 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.

    Botón y campo indicados para renombrar un grupo en el Editor de Grupos de Colisión

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.

Grupo configurado en Vista de Lista del Editor de Grupos de Colisión

Asignar objetos a grupos

Para asignar objetos a grupos que has registrado a través del editor de Studio:

  1. Selecciona uno o más BaseParts que califiquen como parte de un grupo de colisión.

  2. 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.

    Botón de más indicado en el Editor de Grupos de Colisión para agregar partes seleccionadas a un grupo

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

Grupo de colisión elegido indicado como la propiedad CollisionGroup de la parte

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.

Grupo de puntos de control configurado para no ser colisionable con el grupo StudioSelectable

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.

Raycast de Selección de Plugin Recomendado
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.

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 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.

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, "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
end

Colisiones 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.
Malla original de torre de castillo

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.

©2026 Roblox Corporation. Roblox, el logotipo de Roblox y "Powering Imagination" son algunas de nuestras marcas registradas y no registradas en los Estados Unidos y otros países.