Advertisement
  1. Game Development
  2. Physics
Gamedevelopment

Cómo Corregir Problemas de Física Comunes en Tu Juego

by
Length:MediumLanguages:

Spanish (Español) translation by Ricardo Mayén (you can also view the original English article)

Muchos juegos usan motores de física para determinar la manera en que las cosas se mueven y reaccionan. El usar un motor de física puede agregar inmersión, placer para los ojos, y, lo mejor de todo, jugabilidad emergente, pero también puede, si se usa incorrectamente, llevar a resultados poco realistas o problemas que rompan el juego. En este post, explicaré cómo identificar y corregir problemas comunes vistos en juegos de hoy en día.

Examinaremos y resolveremos estos problemas como se ve en Unity, enfocándonos en el motor de física en 3D Nvidia PhysX, pero los principios centrales se pueden aplicar a cualquier otra plataforma y motor de física.

Nota: Puedes encontrar una amplia selección de modelos en 3D para que comiences en el Envato Market.

Demo

Este demo muestra la mayoría de errores mencionados en este artículo tanto en un estado incorrecto o roto, como en un estado corregido:

Escala Normal

Esta es una escena simple con una bola que golpea una pila de barriles. La versión alternativa Escala Incorrecta (10x) muestra cómo la escena cambia a una escala de 10x (ver las marcas de escala en el piso del demo). Presta atención a cómo parece estar en cámara lenta, pero este efecto simplemente es causado por la escala de la escena.

Controlador del Personaje

Esto muestra un juego simple de desplazamiento lateral funcionando como se supone. La "mala" alternativa; Rigidbody & Character Controller Together muestra el mismo juego, pero con un componente de Cuerpo Rígido agregado al personaje. Presta atención a como el Cuerpo Rígido rompe el comportamiento del Controlador del Personaje.

Objetos Con Rebotabilidad

A los barriles se les dispara desde el lado de la escena y son lanzados al aire. Según van cayendo, rebotan en el suelo y se mueven de maneras simples pero majestuosas. La versión rota muestra la misma escena sin rebotabilidad, y se ve mucho más aburrida en comparación.

Sin Modificar Directamente la Transformación de un Cuerpo Rígido.

En este escenario, una bola pesada es empujada hacia arriba sobre una rampa usando Rigidbody.AddForce(). En el segundo escenario, en lugar de usar Rigidbody.AddForce() para subir la bola por la rampa, se usa Transform.position. El resultado de usar Transform.position es que la bola rueda de nuevo para abajo, debido al hecho que el Cuerpo Rígido no está tomando en cuenta el cambio de velocidad del Cuerpo Rígido, pero entonces la modificación de la posición causa que la bola vibre en la rampa.

Errores Comunes

Escala Incorrecta

En la mayoría de los juegos, los jugadores asumirían que la escala del mundo es un reflejo de la escala de la Tierra. Por ejemplo. esperarían que un enemigo que cae de una torre de vigilancia caiga a la misma velocidad a la que percibirían en la Tierra Si el enemigo cae demasiado lento o demasiado rápido, puede sacar de la inmersión—particulamente si el enemigo es de tamaño humano.

Nvidia PhysX en Unity es configurada para usar una unidad por metro. Puedes usar esta característica para revisar si la escala de tus objetos es correcta al simplemente agregar un cubo primitivo Unity. El cubo primitivo mide exactamente un metro cúbico. Si te das cuenta, por ejemplo, que un barril de petróleo en tu escena es dos veces más grande que el cubo, ¡eso significa que tu barril mide dos metros de altura (6.56 pies)!

El corregir la escala es tan simple como darle la escala a cada objeto en la escena. Simplemente selecciona todos los objetos en tu escena y usa la herramienta Scale para hacerlos más grandes o más pequeños. Si ves que tus objetos se mueven demasiado rápido, hazlos más grandes. Si vez que sucede lo opuesto—que los objetos se mueven demasiado lento—deberías hacerlos más pequeños.

Puedes darle el tamaño a tus objetos con más precisión al agruparlos en un objeto nulo, y darle escala a ese objeto. Por ejemplo, el establecer la escala del objeto padre a 1.2 en cada eje incrementará la medida de cada objeto, dentro del objeto en un 20%. También puedes darle escala a los objetos en incrementos usando la herramienta de escala al mantener presionado Ctrl-LMB (Windows) o Cmd-LMB (Os X).

Usando un Cuerpo Rígido y un Controlador de Personaje Juntos

He visto esto unas cuantas veces, y de hecho tiene sentido que suceda con frequencia. El desarrollador asume que un Control de Personaje es necesario para controlar su avatar, pero ellos quieren que el avatar sea afectado por la gravedad y otros objetos en el ambiente.

El problema es que un Controlador de Personaje es diseñado para controles más clásicos, como aquellos que se encuentran típicamente en un juego plataformero o de disparos de primera persona. Un Rigidbody es simplemente un objeto no deformable que se ve afectado por la gravedad y otras fuerzas físicas (tales como otros objetos que chocan con él). Estos son dos componentes muy separados, con usos previstos diferentes.

Elije un Controlador de Personaje solamente cuando quieras el control total sobre cómo se mueve el jugador. Por otro lado, si quieres que tu personaje sea dirigido por el motor de física, usa un Cuerpo Rígido. Al agregar un Cuerpo Rígido a un personaje, probablemente querrás limitar la rotación de manera que el jugador no se caiga.

Modificar Directamente la Transformación de un Cuerpo Rígido

A diferencia de un Controlador de Personaje, no es buena práctica determinar la posición o rotación de un cuerpo rígido, o escalar un objeto de cuerpo rígido constantemente (para el control del jugador y demás). En su lugar deberías usar los métodos AddForce() y AddTorque() encontrados en la clase Rigidbody. Está bien establecer directamente la posición y rotación de un Cuerpo Rígido si, por ejemplo, estás generando el objeto por vez primera, o si estás reiniciando la escena. En esa situación todo estará bien, siempre y cuando el Cuerpo Rígido no se cruce con otros objetos.

Esto importa porque, cuando un cuerpo rígido se mueve a una posición exacta o un estado rotacional, podría pasar a través de un objeto. El motor de física entonces tiene que corregir esta situación y la mayoría del tiempo el motor de física no se ejecuta al mismo tiempo que el mensaje de Update() de Unity. El resultado final es un comportamiento tembloroso siempre que hay una intersección, y es posible que el cuerpo rígido pueda pasar a través de objetos enteramente.

Otro efecto secundario negativo que puede ocurrir cuando, digamos, se mueve un cuerpo rígido a lo largo de un eje para el movimiento del jugador es que internamente el cuerpo rígido es simulado y luego aplica su posición. El actualizar la posición luego mueve el cuerpo rígido sin tomar en cuenta el cambio de velocidad y demás. Si el cuerpo rígido viene dando vueltas en una pendiente, estará moviendo el cuerpo rígido hacia abajo, mientras tu código que altera la posición, moverá el rigidbody hacia arriba de la pendiente.

Objetos que Dan Vueltas Por Siempre

Digamos que estás desarrollando un juego de golf. Hay un problema en cómo la bola no deja de girar, y de alguna manera se las arregla para continuar dando vueltas por siempre, siempre y cuando no haya una especie de hoyo o zanja en su camino. La razón por la que esto pasa es debido a que en la vida real, la bola sería desacelerada por el césped sobre el cual corre (entre otras cosas), ya que tiene que empujar las pequeñas briznas hacia abajo, el césped es esencialmente como una rampa constante. Esto se llama resistencia de rodamiento. Unity no puede simular este comportamiento con exactitud, así que en su lugar se deben usar fuerzas de detención artificiales.

En Unity la mejor fuerza que se puede usar para evitar que un objeto ruede para siempre es el "arrastre angular". Cambiar el arrastre angular en la bola de golf es la manera de solucionar este problema. El valor exacto depende en realidad del comportamiento que estás buscando. Sin embargo, puedes notar que un valor de arrastre angular de 1.0 puede que no sea suficiente en algunos casos.

Objetos Sin Rebotabilidad

Casi todo objeto en el mundo rebota luego de un impacto. El material de física interno predeterminado de Unity no tiene rebote en lo absoluto. Lo cual significa que cada objeto no rebotará a menos que anules el material de física predeterminado o que apliques un material de física a los objetos en tu escena con un valor de rebote superior a 0.

Una de las mejores maneras de resolver este problema es al crear tus propios material de física predeterminado y asignarlo en el Physics Manager encontrado al clicar Edit>Project Settings> Physics.

Cuerpos Rígidos que Se Hunden Parcialmente en la Geometría

La mayoría de motores de física tienen una clase de parámetro que dicta qué tanto pueden ser interpenetrantes o intersectantes hasta que se empujen lejos uno del otro. Este parámetro se llama Min Penetration For Penalty en Unity. De manera predeterminada este valor es de 0.01 (metros), lo que significa que, de manera predeterminada, los objetos pueder estar cruzandose hasta por 1 centímetro (casi 0.4 pulgadas) antes de ser separados.

Deberías establecer la Min Penetration For Penalty a un valor en el cual es apenas notable que los objetos se están cruzando. El establecer el valor a algo minúsculo, tal como de 0.0001 puede resultar en cuerpos rígidos temblorosos.

Cómo Prevenir Errores

Escribir Código para los Cuerpos Rígidos (para Programadores)

Si no eres un programador, no tienes que preocuparte sobre el siguiente escenario. Cuando se escribe código que mueve, rota, o escala cuerpos rígidos, es importante mantener esto en el bucle FixedUpdate. Escribir este código en el bucle Update guiará potencialmente a resultados inestables, puesto que la función Update puede ser convocada a 1000 Hz, mientras que el motor de física y la función FixedUpdate se convocan, cada una de manera predeterminada, a 50 Hz.

Puedes cambiar la frecuencia en los pasos de la física al cambiar el parámetro Fixed Timestep, encontrado en Edit > Project Settings > Time. El valor determina cuanto tiempo se espera, en segundos, entre cada actualización o paso de física. Puedes averiguar la frecuencia en Hertz al dividir 1 por el valor (por ejemplo, una espera de 0.01 segundos significa 1/0.01 = 100 Hz). Según más frecuentes los pasos sean, más exacta y estable será la simulación. Sin embargo, el configurar la frecuencia más alta de lo que el CPU puede tolerar, resultará en una simulación muy inestable. Trata de mantener la frecuencia del la Actualización Fija entre 30 y 100 Hz.

Mientras trabajaba en una pared de ladrillos destructible, me topé con un problema por ladrillos que aparecían después que una porción de la pared había sido destruida. Corregí este problema al colocar el código problemático en una Co-rutina, y colocar la siguiente línea antes de destruir el objeto.


Al esperar un marco, garantizaría que la lógica estuviera sincronizada en el Update time en lugar del FixedUpdate time. Parece que esto significa que la función Destruir se ejecuta en sincronización con el bucle de actualización.

Tip Extra de Unity: ¡No Uses los Materiales de Recursos de Física Estándares!

El paquete de Materiales de Física, el cual viene como parte de los Recursos Estándares de Unity, es en realidad casi completamente inútil. Hay cinco materiales de física contenidos en el paquete, y todos son poco realistas en alguna manera.

Cada material tiene una fricción dinámica y estática idéntica. En el mundo real, los objetos que están de pie tienen levemente más fricción que cuando ellos se mueven. El coeficiente de fricción del material de la goma es de 1.0, el cual no es similar a cualquier otra goma encontrada en el mundo real. Y por si eso no suena lo suficientemente tonto, cada material tiene 0 "rebotabilidad" (excluyendo a los materiales rebotadores). Todo esto significa que los materiales ni siquiera son una representación cercana de su contraparte en la vida real.

Es mejor crear tus propios materiales de física cuando sea necesario. Han muchos sitios que comparte propiedades físicas de materiales—siendo las importantes la fricción dinámica, la fricción estática, y la restitución o rebotabilidad.

Conclusión

Muy pocos problemas relacionados a la física son de hecho difíciles de corregir. Si hay una clase de error relacionado a la física que parece difícil de rastrear, prueba ralentizar el tiempo para ver qué es lo que pasa. Si vez que el problema comienza alrededor de cierta línea de código, puedes usar Debug.Break para pausar el editor e inspeccionar lo que está ocurriendo. Te invito a que comentes acá si tienes alguna pregunta o si necesitas ayuda.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.