Optimización en Unity

santiandrade

Hola! Os dejo por aquí el último post en mi blog sobre "Optimización en Unity". En él hablo sobre algunas técnicas básicas para hacer nuestro juego más óptimo.

Espero que os guste!

LINK: https://histeriagamedev.wordpress.com/2017/06/16/optimizacion-en-unity/

Saludos!

6
I

Me encanta tu articulo compañero, te animo a hacer un articulo de lo mismo pero con unreal engine 4 de c++, la optimizacion es un poco mas compleja. Sigue asi!
Saludos

1 1 respuesta
santiandrade

#2 Muchas gracias! :)

1 respuesta
kesada7

#3 Muy interesante, incluso algunas cosas tan obvias como evitar llamar una función siempre en Update() si es posible se nos pasa a veces.
Una pregunta que no me ha quedado muy claro lo de los colliders estáticos, si yo tengo un GameObject con su Rigidbody, y tengo otros 2 GameObject como hijos del anterior con colliders, según el artículo debería de asignares también un Rigibody a los hijos? Es que en principio la lógica te de dice que cuanto más Rigibody asignes en el juego más calculos hay que hacer no?

1 2 respuestas
santiandrade

#4 hola! gracias por leerlo! Pues justamente esa duda que comentas también me surgió a mí en su momento y la verdad es que en ningún sitio lo dejan claro del todo. Pero, efectivamente, quiero pensar que en esos casos no sería necesario asignar un Rigidbody a cada hijo, más que nada porque su movimiento siempre va a ir en función del padre, pero no puedo asegurarlo 100% y por eso no quise especificarlo más en el artículo. Al final, cuando tengo dudas de ese tipo, suelo fijarme en ejemplos de proyectos oficiales de Unity (o simplemente de gente que sea buena) y observar lo que ellos hacen en esos casos. Por tanto, creo que podríamos decir que en ese caso que comentas, no sería necesario añadir rigidbodies hijos. Obviamente todo va a depender del caso concreto en sí ;-)

1
TheBullet

#4 En ese caso los colliders de los hijos utilizarán el rigidbody del padre (aunque esté a varios niveles de distancia). Un objeto con rigidbody no debe tener un hijo con rigidbody. Si en algún momento dudas, puedes saber que rigidbody está vinculado al collider utilizando Collider.attachedRigidbody: https://docs.unity3d.com/ScriptReference/Collider-attachedRigidbody.html

2 4 respuestas
kesada7

#6 Vaya gracias por aclarar esa duda, había escrito en los foros oficiales ya que había un tema abierto sobre esto pero nadie había planteado el caso de herencia.
En cuanto a lo de que un GameObject con Rigidbody no debe tener un hijo con Rigidbody habrá excepciones no? Es que me suena una propiedad por la que puedes enlazar Rigidbody ya que sino aunque sean hijos cada Rigidbody va a actuar independientemente de sus valores, es decir por ejemplo si el padre es un Rigidbody kinematic y el hijo no, al hijo le va afectar la gravedad separandolo del padre, pero si están enlazados uno arrastra al otro.

2 respuestas
santiandrade

#6 gracias por la aclaración!

TheBullet

#7 Bueno puedes hacer la prueba, crea un cubo con collider y rigidbody y añade otros cubos iguales como hijos. Verás que cuando le das un golpe al padre los hijos se comportan de manera extraña. Al final es algo de lógica, un rigidbody nunca se debe mover usando transform.position, en el momento que enlazas dos rigidbodies el padre se moverá utilizando las físicas del juego, pero el hijo será arrastrado por el padre de la manera que lo haría si tu modificaras el transform.position (o incluso con peor rendimiento). Creo recordar que esto lo aclaraban en un tutorial oficial de Unity, al menos a mi me suena de haberlo escuchado en uno, pero hará mucho tiempo, así que no sabría decirte en cual.

Puede que haya algún método para vincularlos, pero lo desconozco, en el proyecto en el que estoy trabajando (desde hace mucho xD) no lo he necesitado utilizar, así que ni idea. Pero entiendo que hay otros métodos para hacer esto, si al final están unidos para que quieres que dos rigidbodies utilicen gravedad? Utiliza solo un rigidbody en el objeto principal, y las partes que quieras mover de ese objeto las mueves con código o animaciones. Yo estoy haciendo un juego de naves, y por ejemplo los cañones no tienen rigidbody pero si colliders, los cañones se mueven por código y la nave que es la que tiene el rigidbody arrastra a estos, pero igualmente los colliders de los cañones tienen influencia en las físicas del rigidbody.

1
kesada7

Bueno actualizo ya que postee en los foros oficiales de unity para preguntar lo de los Rigidbody y confirmo lo que me respondió #6 (no es que no confiara en tu respuesta es que puse la pregunta antes de que me respondieras :P ) Me comentaron efectivamente lo mismo, que en unity así es como se usa los Rigidbody por ejemplo en coches para juegos de carreras.

Aprovecho este hilo para comentar otra curiosidad sobre optimización, (la verdad que si no abrimos un hilo nuevo podríamos usar este mismo para ir comentando cosas de este estilo que nos vayamos encontrando que sean interesantes). He estado buscando que es más eficiente de hacer para animar un objeto por ejemplo rotandolo, si haciéndolo mediante por scripts o con el animator, yo daba por hecho que para hacer animaciones sencillas como cambiar el tamaño, desplazar objetos o rotarlos era más optimo hacerlo por código, pero he leído en dos sitios que es más eficiente usando animaciones. Aunque al parecer la diferencia es mínima. Alguien puede afirmar esto?

Fuentes:
http://answers.unity3d.com/questions/7994/rotating-objects-script-vs-animation-efficiency.html
https://forum.unity3d.com/threads/rotating-objects-script-vs-animation.34948/

1 2 respuestas
TheBullet

#10 Hombre, en uno de los enlaces uno ha hecho una prueba y parece que es ligeramente más rápido. La cosa es si realmente vale la pena... siempre me han parecido bastante engorrosas las animaciones. Está bien lo de optimizar, pero llega un punto en el que no vale la pena por lo poco que ganas.

Hay algunos consejos sobre físicas que puedo dar. Esta captura es una imagen de mi juego muy antigua, no la tengáis en cuenta (próximamente crearé un hilo sobre el juego en el foro).

Ahora los campos de asteroides tienen muchos menos asteroides y son más realistas, pero para entonces eran así.

Los asteroides del fondo eran campos de particulas en 3d, pero habían unos 1000 asteroides, reales y destructibles con físicas.
Cada asteroide tenía los trozos en los que se partia como hijos, cada hijo tenia un mesh collider, así que cuando impactaba se desactivaba el mesh renderer del padre (el asteroide que se veía), se activaban los mesh renderer de los hijos (los trozos) y estos salían volando. Si cada asteroide tenía 30 trozos, son 30 mesh colliders por cada asteroide, es algo imposible de procesar. La solución se puede aplicar a cualquier objeto que necesite varios colliders o use mesh colliders.

Es tan sencillo como desactivar todos los colliders del objeto y tener un trigger collider (una esfera por ejemplo) que rodee una distancia de "seguridad" alrededor del objeto. Cuando algo entre dentro del trigger significará que hay una posible colisión, entonces se activarán los colliders normales para que hayan impactos y se desactivará el trigger. Esto reduce el consumo de físicas un montón.

Estos asteroides tenían un movimiento aleatorio. Cualquier objeto moviendose por físicas gasta recursos, si son 1000 es un problema. Así que hice un sencillo script el cual guardaba la velocidad del asteroide. Cuando el asteroide no aparecía en pantalla el rigidbody se volvia kinematic y la velocidad se ponia a 0. Cuando volvía a aparecer en pantalla se volvia a poner el rigidbody en modo normal y se restauraba la velocidad a la que estaba yendo. Esto creaba la sensación de que todo estaba en movimiento cuando en realidad lo que no salia estaba parado. Aumentaba mucho el rendimiento.

Al final me ha salido un buen tocho xD

2 2 respuestas
santiandrade

#10 gracias por confirmar!! Por cierto, me parece genial que hablemos de optimización por aquí :)

#11 Qué interesante tu propuesta de optimización con el tema de los asterorides... creo que es una solución elegante y muy profesional. Gracias!

kesada7

#11 Ya... la cosa es que en mi cabeza no sé por que daba por hecho que hacerlo por código era más "limpio" y eficiente cuando al parecer es prácticamente lo mismo. Por lo que es genial, eso quiere decir que el animator está muy pulido, y que cada uno puede escoger lo que más cómodo le sea. Por ejemplo para un juego 2D donde quieres que una plataforma en el aire haga un recorrido (que no sea una linea recta, sino por ejemplo haciendo como eses) Pues sería muchísimo más rápido hacerlo con una animación que por código calculando coordenadas.

+1 a tu solución con los colliders de los asteroides mediante un trigger de seguridad! Lo de moverlos solo cuando aparecen en cámara se hace con Raycast o existe otra función para obtener los object que salen por cámara? He leído algo sobre optimización en juegos 3D con grandes escenarios como por ejemplo mundos abiertos al estilo gta5 en el que lo que hacen es prácticamente lo que tu mencionas, "trabajar" solo lo que se muestra por pantalla y lo demás lo va cargando según se mueve tu personaje, (esto a los que han jugado alguna vez a minecraft se aprecia como el mundo se va incluso generando a la vez que avanzas y exploras más) e incluso cosas que se muestran por pantalla no las trabaja al 100% hasta que no se acerca el jugador (lo que tu haces aquí con los triggers de seguridad) por ejemplo si un edificio o una nave está muy lejos apenas se va apreciar los detalles del modelo por lo que podrías bajar la calidad del mesh renderer para que la gráfica tenga que calcular menos vértices, y una vez el modelo 3D ya está lo suficientemente cerca de la cámara poner el modelo 3D a la máxima calidad.

PD: se ve interesante tu juego, me mola mucho la idea de juegos en el espacio... has hecho tu todo el arte y los modelos 3D? como lo llevas de avanzado? tienes un prototipo o demo jugable? Espero verlo pronto!

1 1 respuesta
TheBullet

#13 Yo también pensaba que era más rápido por código. Si tienes dudas siempre puedes hacer una prueba con un montón de objetos, quizás en móvil rinde distinto. A mi personalmente siempre me gusta más hacerlo por código, no me acaba de gustar la herramienta de animación de Unity.

Para el tema de desactivar y activar cosas cuando los ve la cámara se utiliza OnBecameVisible() y OnBecameInvisible(): https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnBecameVisible.html
Lo de aumentar la calidad según la distancia se llama LOD (Level of Detail). Hay un componente en Unity llamado LOD Group que lo hace: https://docs.unity3d.com/es/current/Manual/LevelOfDetail.html

Los modelos y la mayoría de arte es comprado. El juego estaría ahora mismo en pre-aplha, el funcionamiento básico está hecho y me falta mejorar algunas cosas, como las batallas, que ahora mismo son un poco repetitivas. Ahora estoy haciendo un sistema de pathfinding que funcione en el espacio tridimensional para poder añadir batallas y asaltos a estaciones espaciales y que las naves puedan navegar entre edificios (no como ahora, que son tontas y chocan xD). A parte falta contenido a saco, me está costando más tiempo de lo que había previsto.
Puedes ver muchos gifs del juego en twitter: https://twitter.com/Isolated_Games
Y si quieres ver de que va el juego un poco puedes pasarte por IndieDB, aunque de momento solo he puesto dos artículos: http://www.indiedb.com/games/between-the-stars
Aquí acaba el offtopic de spam :p

2 1 respuesta
santiandrade

#14 Ya conocía tu juego del foro de Stratos, te estás currando un proyecto de la hostia. Ánimo y a seguir así con él ;-)

1 respuesta
TheBullet

#15 Gracias ^^

6 meses después
B

#7 un ejemplo de excepción: Una nave espacial con su Rigidbody principal en el cuerpo... le pones 3 motores hijos, cada uno con su propio Rigidbody... conectas los Rigidbodys de los hijos al del padre mediante "Fixed Joint".

Esto permite afinar la distribución de la masa de la nave, por ejemplo, agregando masa a los Rigibodys hijos (masa de los motores)... también permite aplicar las fuerzas de empuje de cada motor justo en la posición real del motor (fuerzas a los Rigidbodys hijos)... equivalente a un AddForceAtPosition pero con más ventajas añadidas.

Otro ejemplo de excepción: en el caso del juego de coches que estoy desarrollando... lo uso para afinar la distribución de pesos, simulación de inercias del tanque de gasolina y otros varios...

En ambos casos los hijos pueden tener Rigidbodys... (aunque no es necesario emparentarlos ya que los conecta el motor de física... pueden estar emparentados).

2

Usuarios habituales