⚙️ Físicas en Unity 3D
Una guía completa y exhaustiva sobre el sistema de físicas en Unity 6, componentes, mecanismos y mejores prácticas para crear simulaciones realistas.
📋 Índice de Contenidos
🎮 Introducción al Sistema de Físicas en Unity
El sistema de físicas de Unity es un motor de simulación basado en PhysX, que calcula las interacciones realistas entre objetos en el mundo 3D. Sin agregar código, un objeto con Rigidbody será atraído por la gravedad y reaccionará a las colisiones.
¿Por qué importa la física?
- Realismo: Los objetos se mueven de forma creíble y predecible
- Gameplay: Las mecánicas de juego dependen de la física (saltos, colisiones, gravedad)
- Optimización: PhysX está altamente optimizado para producción
- Control: Puedes ajustar cada aspecto para tu juego específico
🔧 Componentes Principales del Sistema de Físicas
Para que la física funcione en Unity necesitas al menos dos componentes trabajando juntos:
Función: Controla el movimiento y la física de un GameObject.
Requiere: Un Collider para interactuar.
Propiedades clave:
- Mass (Masa)
- Drag (Resistencia al aire)
- Angular Drag (Resistencia rotacional)
- Gravity (Afectado por gravedad)
- Constraints (Restricciones)
Función: Define la forma del objeto para detectar colisiones.
Tipos: Box, Sphere, Capsule, Mesh, Wheel, Terrain.
Propiedades clave:
- Is Trigger (Disparador)
- Material (Physics Material)
- Offset (Desplazamiento)
- Size (Tamaño)
Estados del Rigidbody
| Estado | Descripción | Casos de Uso |
|---|---|---|
| Dynamic | Simulación física completa. Afectado por fuerzas y colisiones. | Objetos móviles (pelotas, cajas, enemigos) |
| Kinematic | Se mueve por scripts, pero los objetos dinámicos rebotan en él. | Plataformas móviles, puertas |
| Static | No se mueve. Más eficiente que dinámico. | Piso, paredes, obstáculos fijos |
📐 Tipos de Colliders en Unity 3D
Cada tipo de collider está optimizado para diferentes formas y casos de uso:
Forma: Cubo/Rectángulo.
Uso: Cajas, paredes, plataformas.
Ventaja: Muy rápido, ideal para objetos geométricos simples.
CPU: ⭐⭐⭐ | Precisión: ⭐⭐⭐
Forma: Esfera.
Uso: Bolas, explosiones, projectiles.
Ventaja: Perfecto para cálculos de distancia y detección esférica.
CPU: ⭐⭐⭐ | Precisión: ⭐⭐
Forma: Cilindro con semiesferas.
Uso: Personajes, enemigos humanoides.
Ventaja: Excelente para movimiento sin atascarse en esquinas.
CPU: ⭐⭐⭐ | Precisión: ⭐⭐⭐
Forma: Geometría exacta del modelo 3D.
Uso: Terrenos complejos, escenarios.
Advertencia: Más costoso. Usar con moderación.
CPU: ⭐ | Precisión: ⭐⭐⭐⭐⭐
Forma: Rueda especializada.
Uso: Vehículos, coches, motos.
Ventaja: Simulación realista de suspensión y agarre.
CPU: ⭐⭐ | Precisión: ⭐⭐⭐⭐
Forma: Mapa de altitud.
Uso: Terrenos amplios, montañas.
Ventaja: Optimizado para grandes áreas.
CPU: ⭐⭐⭐ | Precisión: ⭐⭐⭐
Compound Colliders (Colliders Compuestos)
Para objetos complejos, puedes combinar múltiples colliders primitivos en objetos hijo:
GameObject Player
├─ Capsule Collider (cuerpo)
├─ Box Collider (brazos)
└─ Sphere Collider (cabeza)
Ventaja: Mayor precisión que Mesh Collider, mejor rendimiento que un Mesh único.
🎨 Physics Materials: Fricción y Rebote
Los Physics Materials definen cómo se comportan las superficies cuando entran en contacto con otros objetos.
Propiedades Principales
- Dynamic Friction: Fricción mientras se desliza (0 = hielo, 1 = pegajoso)
- Static Friction: Fricción en reposo
- Bounciness: Rebote (0 = sin rebote, 1 = rebote máximo)
- Friction Combine: Cómo se combinan fricciones
- Bounce Combine: Cómo se combinan rebotes
Ejemplos de Valores
| Material | Fricción | Rebote |
| Hielo | 0.05 | 0.0 |
| Asfalto | 0.7 | 0.2 |
| Pelota de Tenis | 0.5 | 0.8 |
| Goma | 1.0 | 0.3 |
| Acero | 0.4 | 0.9 |
Modos de Combinación
Al colisionar dos materiales, se combinan usando uno de estos modos:
Average
Promedio de ambos valores. Es el más realista.
Multiply
Multiplicación. Resulta en valores más bajos.
Minimum
Usa el valor más pequeño (más pegajoso/menos rebote).
Maximum
Usa el valor más grande (más resbaladizo/más rebote).
🔗 Joints: Articulaciones y Restricciones
Los Joints conectan dos Rigidbodies y crean comportamientos de movimiento restringido. Son esenciales para ragdolls, cadenas, y mecanismos.
Comportamiento: Fija rígidamente dos Rigidbodies en su posición relativa.
Uso: Objetos unidos, partes de máquinas conectadas.
Parámetro importante: Breaking Force (fuerza necesaria para romper la articulación).
// Fixed Joint en código
Rigidbody rb1 = obj1.GetComponent<Rigidbody>();
Rigidbody rb2 = obj2.GetComponent<Rigidbody>();
FixedJoint joint = obj1.AddComponent<FixedJoint>();
joint.connectedBody = rb2;
joint.breakForce = 1000f;
Comportamiento: Actúa como un resorte elástico entre dos Rigidbodies.
Uso: Cuerdas, cables, suspensiones de vehículos.
Parámetros:
- Spring: Resistencia del resorte (más alto = más fuerte)
- Damper: Amortiguamiento (reduce oscilaciones)
- Min/Max Distance: Distancia de reposo
Comportamiento: Permite rotación en un eje (como una puerta).
Uso: Puertas, brazos mecánicos, palancas.
Configuración: Define el eje de rotación (X, Y, o Z) y límites de rotación.
// Hinge Joint - Puerta
HingeJoint hinge = doorGameObject.AddComponent<HingeJoint>();
hinge.axis = Vector3.up; // Rotación en eje Y
hinge.limits = new JointLimits() {
min = 0,
max = 90,
bounciness = 0
};
Comportamiento: Joint extendido de bola y encaje para ragdolls.
Uso: Esqueletos de ragdoll, articulaciones humanas (brazos, piernas, cuello).
Ventaja: Permite rotación compleja en múltiples ejes.
Parámetros: Swing Limits (rotación frontal), Twist Limits (rotación axial).
Comportamiento: El joint más flexible. Configurable en todos los grados de libertad.
Uso: Comportamientos personalizados, joints especializados.
Complejidad: Alta. Permite bloquear/desbloquear 6 grados de libertad (3 rotaciones + 3 traslaciones).
Nota: Más costoso computacionalmente que otros joints.
Comportamiento: Bola y encaje como una articulación de cadera.
Uso: Articulaciones esféricas, caderas, hombros.
Característica: Permite rotación en todos los ejes con límites específicos.
💪 Aplicación de Fuerzas y Movimiento
Existen múltiples formas de mover un Rigidbody. Cada una tiene su propósito:
⚡ AddForce()
Aplica una fuerza continuada que se acumula.
rigidbody.AddForce(Vector3.forward * 10);
// Acelera gradualmente
Casos: Saltos, empujes, explosiones.
🎯 Velocity
Establece la velocidad directamente.
rigidbody.velocity = Vector3.forward * 5;
// Velocidad instantánea
Casos: Knockback, movimiento de proyectiles.
🌪️ AddTorque()
Aplica fuerza rotacional.
rigidbody.AddTorque(Vector3.right * 5);
// Rotación gradual
Casos: Pelotas girando, objetos rotatorios.
📍 MovePosition()
Movimiento cinemático interpolado.
rigidbody.MovePosition(transform.position + Vector3.forward);
Casos: Personajes, plataformas móviles.
Force Modes (Modos de Fuerza)
Cuando usas AddForce(), puedes especificar cómo se aplica la fuerza:
| Force Mode | Fórmula | Uso |
|---|---|---|
| Force (Default) | acceleration = Force / Mass | Fuerzas reales (viento, gravedad, empujes) |
| Acceleration | Aceleración pura sin considerar masa | Cuando quieres que todos los objetos se aceleren igual |
| Velocity | Cambio de velocidad directo | Movimiento suave del personaje |
| Impulse | Aplicada en un frame | Explosiones, saltos instantáneos |
void FixedUpdate() {
rigidbody.AddForce(Vector3.forward * 10);
}
💥 Detección de Colisiones
Unity ofrece tres formas de detectar colisiones:
Se ejecuta cuando dos colliders comienzan a tocarse.
Requiere: Ambos con Collider, al menos uno con Rigidbody.
void OnCollisionEnter(Collision collision) {
Debug.Log("¡Colisión!");
}
Se ejecuta cuando un objeto entra en un Trigger.
Requiere: Collider con "Is Trigger" activado.
void OnTriggerEnter(Collider collider) {
Debug.Log("¡Entró!");
}
Lanza un rayo invisible para detectar colisiones.
Uso: Armas, visión de IA, terreno.
RaycastHit hit;
if (Physics.Raycast(pos, dir, out hit)) {
Debug.Log(hit.collider.name);
}
Collision Detection Methods
El Rigidbody tiene opciones para detectar colisiones de diferente manera:
⚡ Optimización del Sistema de Físicas
La física puede ser costosa. Aquí están las mejores prácticas para optimizar:
❌ Evitar: Mesh Colliders para objetos dinámicos.
✅ Hacer: Usar Box, Sphere, Capsule Colliders.
Los colliders primitivos son 10-100x más rápidos.
❌ Evitar: Rigidbody dinámico para objetos que no se mueven.
✅ Hacer: Dejar como Static o usar Kinematic solo si es necesario.
Los objetos Static no se recalculan cada frame.
En Edit > Project Settings > Physics:
- Define qué layers pueden colisionar entre sí
- Ejemplo: Enemigos no necesitan colisionar con Enemigos
- Reduce cálculos innecesarios
Para objetos complejos:
- Usa múltiples colliders primitivos en objetos hijo
- Mejor que un único Mesh Collider
- Más rápido + mejor precisión
Cada Rigidbody dinámico cuesta CPU:
- Limita la cantidad en escena (máx ~100 en 60 FPS)
- Usa Kinematic para objetos que no necesitan física completa
- Destruye/Poolea objetos cuando sea posible
En Edit > Project Settings > Time:
- Fixed Timestep: Por defecto 0.02s (50 FPS)
- Aumenta a 0.03s-0.05s para juegos menos exactos
- Reduce llamadas a FixedUpdate()
Congela ejes innecesarios:
- Personaje 2D: Congela Z y rotaciones
- Objeto que no rota: Congela todas las rotaciones
- Reduce cálculos matemáticos
🎮 Ejemplos Prácticos
Ejemplo 1: Movimiento de Personaje
// Personaje con salto
public class PlayerController : MonoBehaviour {
private Rigidbody rb;
public float moveSpeed = 5f;
public float jumpForce = 5f;
void Start() {
rb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
// Movimiento horizontal
float x = Input.GetAxis("Horizontal");
rb.velocity = new Vector3(x * moveSpeed, rb.velocity.y, 0);
// Salto
if (Input.GetKeyDown(KeyCode.Space)) {
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
}
Ejemplo 2: Física Realista de Auto
// Suspensión y tracción
public class CarPhysics : MonoBehaviour {
private Rigidbody rb;
public WheelCollider[] wheels;
public float motorForce = 3000;
public float brakeTorque = 3000;
void FixedUpdate() {
float accel = Input.GetAxis("Vertical") * motorForce;
float brake = Input.GetKey(KeyCode.Space) ? brakeTorque : 0;
foreach (WheelCollider wheel in wheels) {
wheel.motorTorque = accel;
wheel.brakeTorque = brake;
}
}
}
Ejemplo 3: Ragdoll
// Activar/Desactivar ragdoll
void EnableRagdoll() {
// Desactivar animador
animator.enabled = false;
// Activar todos los Rigidbodies
Rigidbody[] allBodies = GetComponentsInChildren<Rigidbody>();
foreach (Rigidbody body in allBodies) {
body.isKinematic = false;
}
// El esqueleto ahora simulará física
}
Ejemplo 4: Projectile con Física
// Bala/Flecha realista
public class Projectile : MonoBehaviour {
private Rigidbody rb;
public void Launch(Vector3 direction, float force) {
rb = GetComponent<Rigidbody>();
rb.velocity = direction * force;
// Rotar según dirección de movimiento
transform.rotation = Quaternion.LookRotation(direction);
}
void OnTriggerEnter(Collider collision) {
if (collision.CompareTag("Enemy")) {
Destroy(gameObject);
}
}
}
📚 Tabla de Referencia Rápida
| Componente/Método | Descripción | Rendimiento |
|---|---|---|
| Rigidbody | Controla física de un objeto | ⭐⭐⭐ |
| Box Collider | Collider cúbico | ⭐⭐⭐⭐⭐ |
| Sphere Collider | Collider esférico | ⭐⭐⭐⭐⭐ |
| Capsule Collider | Collider cilíndrico | ⭐⭐⭐⭐⭐ |
| Mesh Collider | Collider de geometría exacta | ⭐⭐ (Evitar si es posible) |
| Physics.Raycast | Detecta colisiones con rayo | ⭐⭐⭐⭐ |
| AddForce | Aplica fuerza acumulativa | ⭐⭐⭐⭐⭐ |
| Velocity | Establece velocidad directa | ⭐⭐⭐⭐⭐ |
| FixedJoint | Fija dos cuerpos | ⭐⭐⭐ |
| SpringJoint | Crea elasticidad | ⭐⭐ |
| HingeJoint | Articulación de rotación | ⭐⭐⭐ |
| CharacterJoint | Articulación compleja | ⭐⭐ |
✅ Mejores Prácticas
✅ HACER
- Usar Colliders primitivos
- Aplicar fuerzas en FixedUpdate()
- Usar Raycasts para detección
- Limitar objetos dinámicos
- Usar Constraints para optimizar
- Perfilar rendimiento regularmente
- Documentar valores de física
❌ EVITAR
- Mesh Colliders en objetos dinámicos
- Cambiar transform directamente
- Aplicar fuerzas en Update()
- Demasiados joints complejos
- Continuous Collision para todo
- Ignorar la matriz de colisiones
- Física sin propósito
🔧 Solución de Problemas
A: Problemas comunes:
- El piso NO tiene Collider
- El Rigidbody tiene "Is Kinematic" activado
- La velocidad del objeto es demasiado alta (usa Continuous Collision)
- El Collider es demasiado pequeño (Check "Edit Collider" en Inspector)
A: Soluciones:
- Aplica fuerzas en FixedUpdate(), no Update()
- Usa MovePosition() para movimiento suave
- Verifica el Fixed Timestep (Project Settings > Time)
- Asegúrate de que el Capsule Collider tenga altura correcta
A: Esto es "jitter":
- Aumenta Solver Iterations en Physics Settings
- Reduce Force Scale y Penetration per Iteration
- Asegúrate de que los Colliders no se solapan
- Revisa que la masa sea realista (no muy pequeña)
A: Problemas de joints:
- Verifica que ambos Rigidbodies existan y estén configurados
- Asegúrate que el Connected Body no sea nulo
- Aumenta Solver Iterations si es inestable
- Para ragdolls: configura Character Joints correctamente
🎓 Conclusión
El sistema de físicas de Unity es poderoso pero requiere comprensión. Recuerda:
- Rigidbody + Collider = Sistema base (no una sin la otra)
- FixedUpdate() = Única forma correcta de aplicar fuerzas
- Primitivos = Más rápidos que Mesh Colliders
- Physics Materials = Control total del comportamiento
- Joints = Crear comportamientos complejos
- Optimización = Esencial para juegos en producción
La clave está en entender la diferencia entre qué hace la física automáticamente vs qué necesita ser controlado por código.
- Experimenta con diferentes valores en Physics Settings
- Crea un pequeño prototipo: Una bola rodando en una rampa
- Construye un ragdoll simple para entender Character Joints
- Perfila tu juego para identificar cuellos de botella de física