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 manejar colisiones personalizadas, BasePart tiene un conjunto de eventos de colisión y técnicas de filtrado de colisión, para que pueda controlar qué conjuntos 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 las partes, tenga en cuenta lo siguiendo:

  • La propiedad CanTouch de una parte determina si desencadena eventos de colisión. Si se establece en false, ni Touched ni TouchEnded desencadenar.
  • La propiedad CanCollide de una parte afecta si físicamente colisionará con otras partes y hará que las fuerzas actúen sobre ellas. Incluso si CanCollide está desactivado para una parte, puede detectar el tacto y el no-tacto a través de Touched y TouchEnded eventos.
  • Los Touched y TouchEnded eventos solo se disparan como resultado de movimiento físico , no de un Position o CFrame cambios que hacen que una parte se intersecte o deje de interseccionar otra parte.
  • La clase de nivel superior Terrain hereda de BasePart, por lo que puede asignar un grupo de colisión a Terrain para determinar si otros BaseParts chocan con Voxels de Terreno.

Tocado

El evento Touched se dispara cuando un BasePart entra en contacto con otro, o con un Terreno Vóxel. Solo se dispara como resultado de simulación física y no se disparará cuando la parte de Position o CFrame esté configurada explícitamente para que se intersecte con otra parte o Vóxel.

El siguiente patrón de código muestra cómo el evento Touched se puede conectar a una función personalizada onTouched(). Tenga 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 Partes

local part = workspace.Part
local function onTouched(otherPart)
print(part.Name .. " collided with " .. otherPart.Name)
end
part.Touched:Connect(onTouched)

Tenga en cuenta que el evento Touched puede dispararse varias veces en rápida sucesión basada en colisiones físicas sutiles, como cuando un objeto en movimiento "se instala" en una posición de reposo o cuando una colisión implica un modelo de múltiples partes . Para evitar desencadenar más Touched eventos de los que sea necesario, puede implementar un simple sistema de rechazo que impone un período de "recuento" a través de un atributo de instancia .

Colisión de piezas con tiempo de reutilización

local part = workspace.Part
local COOLDOWN_TIME = 1
local function onTouched(otherPart)
if not part:GetAttribute("Touched") then
print(part.Name .. " collided with " .. otherPart.Name)
part:SetAttribute("Touched", true) -- Establecer atributo a true
task.wait(COOLDOWN_TIME) -- Espere la duración del tiempo de reutilización
part:SetAttribute("Touched", false) -- Restablecer atributo
end
end
part.Touched:Connect(onTouched)

TocarTerminado

El evento TouchEnded se dispara cuando los límites de colisión completos de un BasePart salen de los límites de otro BasePart o de un Terreno Vóxelllenado. Solo se dispara como resultado de simulación física y no se disparará cuando la parte Position o CFrame esté configurada explícitamente para que deje de interseccionar otra parte o Vóxel.

El siguiente patrón de código muestra cómo el evento TouchEnded se puede conectar 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 part = workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " is no longer touching " .. otherPart.Name)
end
part.TouchEnded:Connect(onTouchEnded)

Filtro de Colisión

El filtrado de colisiones define qué partes físicas colisionan con otras. Puede configurar el filtrado para numerosos objetos a través de grupos de colisiones o puede controlar colisiones sobre una base de parte a parte con instancias.

Grupos de Colisión

Los grupos de colisión **** te permiten asignar BaseParts a grupos dedicados y especificar si colisionan o no con los de otros grupos. Las partes de los grupos que no colisionan se atraviesan completamente, incluso si ambas partes tienen su propiedad CanCollide configurada como true .

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

Puede configurar fácilmente grupos de colisión a través del Editor de Grupos de Colisión de Studio, accesible haciendo clic en el botón Grupos de Colisión en la pestaña Modelo.

Collision Groups tool indicated in Model tab of Studio

El editor funciona en Vista de lista , lo que favorece el acoplamiento al lado izquierdo o derecho de Studio, o en un Vista de tabla más amplio , que favorece el acoplamiento a la parte superior o inferior.

List View example in Collision Groups Editor

Registrando 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 del grupo predeterminado .

Para crear un nuevo grupo de colisión:

  1. Haga clic en el botón Añadir Grupo a lo largo de la parte superior del panel del editor, ingrese un nuevo nombre de grupo y presione Introducir. El nuevo grupo aparece en ambas columnas de la vista de lista, o en la columna izquierda y la fila superior de la vista de tabla.

    New group added to Collision Groups Editor in List View
  2. Repita el proceso si es necesario, eligiendo un nombre único y descriptivo para cada grupo. Tenga en cuenta que puede 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 .

    Button and field indicated for renaming a group in the Collision Groups Editor

Configurando colisiones de grupo

En la configuración predeterminada, los objetos de todos los grupos colisionan entre sí. Para evitar que los objetos de un grupo colisionen con los objetos de otro grupo, deselecciona la casilla en la fila/columna respectiva.

En el siguiente ejemplo, los objetos del grupo Cubes chocarán con los objetos del grupo Doors .

Group configured in List View of Collision Groups Editor

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. Asigna los objetos 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.

    Plus button indicated in Collision Groups Editor for adding selected parts to a group

Una vez asignado, el nuevo grupo se refleja bajo la propiedad CollisionGroup del objeto.

Chosen collision group indicated as the part's CollisionGroup property

Grupo de Colisión StudioSelectable

Las herramientas de Studio usan el sistema de filtrado de colisiones para determinar qué objetos son candidatos a la selección al hacer clic en el ventanilla3D. Se ignorarán los objetos cuyo grupo de colisión asignado no colisiona con StudioSelectable.

Por ejemplo, si tienes puntos de control en una experiencia de carreras cuyas áreas efectivas están definidas por grandes partes transparentes, puedes asignarlos a un grupo de colisiones de puntos de control y luego hacer que ese grupo no sea conflictivo con StudioSelectable para que no se interpongan en el camino cuando estés editando la geometría del mapa subyacente.

Checkpoints group configured to be non-collidable with StudioSelectable group

Para el código del plugin, se recomienda asignar "StudioSelectable" como el filtro de grupo de colisión de su RaycastParams al encontrar partes debajo del cursor. Esto permite que sus complementos coincidan con las mecánicas de selección que los creadores han aprendido a esperar de las herramientas integradas de Studio.

Selección de Plugin Recomendada Raycast

local UserInputService = game:GetService("UserInputService")
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 establecer grupos de colisiones , como entre la rueda de un vehículo y su chasis, considere la restricción No Colisión. Las ventajas incluyen:

  • No se requieren grupos de colisión y/o scripts de configuración, por lo que puede crear y compartir modelos fácilmente con un filtro de colisión personalizado.
  • Las partes conectadas no colisionarán entre sí, pero aún pueden colisionar con otros objetos.

Desactivando Colisiones de Personajes

Los personajes de los jugadores de Roblox chocan entre sí de forma predeterminada. Esto puede llevar a un juego interesante pero no intencional, como personajes que saltan uno encima del otro para llegar a áreas específicas. Si este comportamiento no es deseable, puede evitarlo con las siguientes 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)
-- Proceso de descendientes existentes y nuevos para la configuración física
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- Detecta cuando se añade el personaje del jugador
player.CharacterAdded:Connect(onCharacterAdded)
end)

Colisiones de Modelos

Model Los objetos son contenedores para partes en lugar de heredar de BasePart, por lo que no pueden conectarse directamente a BasePart.Touched o BasePart.TouchEnded eventos. Para determinar si un modelo desencadena un evento de colisión, debe realizar un bucle a través de sus hijos y conectar las funciones personalizadas onTouched() y onTouchEnded() a cada hijo BasePart.

La siguiente muestra de código conecta todos los 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 que se intersectan consigo mismo
if otherPart:IsDescendantOf(model) then return end
-- Aumentar el número de partes del modelo que tocan
numTouchingParts += 1
print(model.Name, "intersected with", otherPart.Name, "| Model parts touching:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- Ignora las instancias del modelo que no se cruza consigo mismo
if otherPart:IsDescendantOf(model) then return end
-- Reducir el número de partes del modelo que se tocan
numTouchingParts -= 1
print(model.Name, "un-intersected from", otherPart.Name, "| Model parts touching:", 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 mallas y las partes modeladas sólidas heredan las mismas eventos de colisión y opciones de filtrado de colisión como partes regulares. Sin embargo, dado que las mallas y las partes modeladas sólidas generalmente tienen geometrías más complejas, tienen una propiedad distintiva CollisionFidelity que determina con qué precisión los límites físicos se alinean con la representación visual para el manejo de colisiones.

La propiedad de fidelidad de colisión tiene las siguientes opciones, en orden de fidelidad e impacto de rendimiento de menor a mayor:

  • Caja Crea una caja delimitadorade colisión límite, ideal para objetos pequeños o no interactivos.
  • Casco Genera un casco convexo, adecuado para objetos con indentaciones o cavidades menos pronunciadas.
  • Por defecto Produce una forma aproximada de colisión que soporta la concavidad, adecuada para objetos complejos con necesidades de interacción semidetallada.
  • PreciseConvexDecomposition Ofrece la fidelidad más precisa pero aún no una representación 1:1 del visual. Esta opción tiene el costo de rendimiento más caro y tarda más en ser calculado por el motor.
Original mesh of castle tower

Para obtener más información sobre el impacto del rendimiento de las opciones de fidelidad de colisión y cómo mitigarlas, consulte Optimización de rendimiento. Para obtener un recorrido detallado sobre cómo elegir una opción de fidelidad de colisión que equilibre sus necesidades de precisión y requisitos de rendimiento, consulte aquí.