Unity – Reglas basicas al usar Rigibody y colisionadores

Cuando uno empieza a trabajar en Unity, es típico encontrase en problemas que GameObject no colisionan entre ellos o no funciona como debería (y en proyectos grandes, notaremos que se alenté el juego). Por eso mismo dejo aquí unas reglas básicas al usar Rigibody y Colisionadores para evitar problemas y correcta funcionalidad.

  • Un GameObject con Colisionador pero SIN Rigibody se le considera estático. Esto quiere decir que si movemos un objeto con cierta frecuencia hay que agregarle el Rigibody, ya que para que las físicas funcione fluido, se tienen que calcular unos datos para que el impacto entre objetos de mejores resultados, y cuando un objeto no tiene Rigibody, algunos de estos valores son precalculados para un futuro impacto sea mayor rápido las físicas, pero si movemos con frecuencia un objeto sin Rigidoby, estos calculos se harán cada frame en que sea movido y volviéndose en contra la ventaja de precalcular valores. Por lo que si tienes que mover un GameObject con solo Colisionador, hazlo realmente solo cuando sea necesario.
  • Un GameObject con Rigibody siempre hay que moverlo usando el mismo Rigibody y no el Trasnform, solo usar el Transform para “Resetear” o iniciar un GameObject. De ahí usar Velocity, AddForce, AddTorque o MovePosition de las funciones de Rigibody al menos que este asignado como “Kinematic” podemos usar transform.
  • Todos los GameObject hijos con Colisionador donde el GameObject padre tiene Rigibody, estos colisionadores son parte del Rigibody del padre, si un hijo tiene otro Rigibody entonces ya es independiente y este dejara ser afectado por el Rigibody del padre. (Para que los hijos afecten a los padres, requiere uso de joins).
  • Los GameObject con Rigibody procura tenerlos en una escala lo más posible a 1/1.
  • Es mejor usar varios colisionadores primitivos ante los mesh o polygon collider.
  • Si usaras Raycast procura que solo sea con colisionadores primitivos.
  • OnCollisionStay no se llama si el Rigibody ya se encuentra en ‘sleep’ (Ya no se mueve ni rota).
  • No te alejes más 6,000 del origen para que los float no pierdan precision.

Unity – Siempre visible BoxCollider2D en el Editor

Aquí les comparto un código que permite siempre ver el BoxCollider2D en el editor de Unity, simplemente basta con agregarlo a cualquier GameObject que tenga un BoxCollider2D. La ventaja de este script, es que es compatible con la escala y rotación del GameObject.

Unity – Mover la vista de la pestaña ‘scene’ por código

La pestaña de ‘scene’ maneja su propia cámara independiente a lo que vemos en la pestaña de ‘game’, por lo que aquí les comparto un código que permite mover la “cámara” de la pestaña de ‘scene’ por código por el cual podremos hacer que se mueva junto con la cámara principal u otro objeto del juego, simplemente debemos agregar este script al objeto al que deseamos que persiga la pestaña de ‘scene’.

Nota: Este script esta diseñado para ser usado en 2D, pero adaptarlo en 3D no debe ser tanto problema y además que si tienes activado el script, este no te permitirá controlar con el mouse la pestaña de ‘scene’ en modo Play.

Unity – LoadScene modo single VS Additive y ventana de loading

Unity para poder cargar un nuevo nivel o escena (SceneManager.LoadScene apartir de Unity 5.3 y Application.LoadLevel anteriormente). El cual existen dos maneras de hacerlo básicamente, lo que hare será explicar con un poco más de detalle cómo funcionan internamente y así poder sacarle un mayor provecho:

  1. Modo Single (Normal): Este modo es el básico, el cual al ser llamado carga todo el contenido de la nueva escena, después Unity analiza que Assets seguirán siendo utilizados en la nueva escena que ya estaban cargados y de ahí elimina todos los GameObject de la vieja escena y libera de memoria todos aquellos Assets que ya no serán utilizados.
  2. Modo Additive: Este modo carga todo lo de la nueva Escena y no elimina ningun GameObject de la vieja escena y por lo tanto tampoco libera nada de los Assets.

Con esto a lo que quiero llegar es para su uso en la creación de una ventana de loading. Una práctica famosa y sencilla de generar una ventana de Loading, es tener una escena que solo contiene la imagen de “Loading” y cada vez que vayamos a cambiar de escena es llamar esta escena y desde aquí llamar la verdadera escena que nosotros necesitamos, así lograr siempre mostrar una ventana bonita de loading. Sencillo y fácil de implementar, pero tiene una desventaja hacerlo de esta manera. el 99% de los tutoriales y implementación de este tipo usan el modo Single para cargar las escenas, bueno daré un ejemplo de la desventaja:

El jugador está en el “Nivel 1” y lo pasa, llamamos la escena de Loading que solo contiene la imagen de ‘Loading’, Unity LIBERA de memoria todos los Assets que ya no son necesarios (Excepto de los GameObject que aun estén por “DontDestroyOnLoad”) y después llama cargar “Nivel 2” y tiene que cargar todos los Assets que usa este Nivel, el cual es muy probable que la mayoría son Assets que ya eran usados en el “Nivel 1”. Aquí el problema es que estaremos generando un Loading más grande de lo que realmente se necesitaría.

Como solucionar el problema:

Sabiendo cómo funciona el loading, realmente la clave está en que cuando del “Nivel 1” carguemos la escena de “Loading” lo hagamos usando el modo Additive, de esta manera solo agregara y mostrara la escena de Loading en pantalla, pero Unity no liberara ningun Asset  de memoria, entonces al cargar de manera Single al “Nivel 2”, Unity solo tendrá que cargar los Assets que hacen faltan y solo liberara la memoria de los Assets que de verdad ya no serán utilizados.

Resultado: Bueno, esto dependerá de las escenas, Assets y dispositivo, pero eh logrado reducir hasta un 70% del tiempo de “Loading”.

Update con pausas sin congelar Unity en el intento

La función de ‘Update’ de Unity es uno de los primeros que empezamos a utilizar dentro de Unity ya que permite hacer una acción en cada frame o cada ciclo de juego.

Durante mis clases, eh tenido varios alumnos que preguntan si es posible hacer algo como un ‘Sleep’ en medio de una ejecución de ‘Update’. La respuesta a esta pregunta es un simple no, oh al menos en el Update de Unity. Usando los Coroutine de Unity es posible simular un Update, pero con posibilidad de tener pausas y no congelar Unity en el intento.

En cualquier script que deseamos tener un Update con pausas (yield) podemos lograrlo a partir de este template.


Void Start()

{

StartCoroutine(StartUpdateYield());

}



IEnumerator StartUpdateYield ()

{

    while(true)

         yield UpdateYield();

}



IEnumerator UpdateYield()

{

//Todo tu codigo, y para pausar solo usas cuando necesites

//yield return new //null o WaitForSeconds

}

Con esto es fácil hacer tareas como, avanza 5 pasos, espera 2 segundos, gira 180°, espera 4 segundos, avanza 5 pasos, espera 2 segundos, gira 180° segundos, espera 4 segundos (y se repitiera infinitamente).

Como recuperar la ultima escena cuando crashea Unity

Aveces por un error grande como un ciclo infinito o por extrañas razones aveces puede congelarse y cerrarse Unity con algunos cambios en nuestra escena que no han sido guardados. Existe una manera de poder recuperar esta escena.

Cuando crashe Unity y no habiamos guardado los cambios de nuestra escena, lo primero que hay que hacer despues de haber gritado al cielo es no volver abrir Unity.

Seguido nos vamos a la carpeta de nuestro proyecto y abrimos la carpeta ‘Temp’

En las nuevas versiones ahora se encuentra una carpeta llamado ‘_BackupScenes’ y ahí habrá archivos llamado ‘X.backup’,  cambia la extensión a ‘X.unity’.

Por ultimo lo copiamos a cualquier ubicación de nuestra carpeta de de ‘Asset’ y podemos volver abrir Unity y abrimos la escena, y sera nuestra ultima escena con los ultimos cambios echos.

Unity viejos: Buscamos el archivo llamado “__EditModeScene”, le cambiamos el nombre a “MiEscena.unity” o cualquier nombre, pero lo importante es que se le agregue el “.Unity” y mueve a la carpeta de assets y abre Unity.

Optimizar FOR

Este es un pequeño tip para optimizar los FOR como en C++ y C#.

Los FOR son muy usado principalmente para recorrer listas o arreglos y su manera popular de trabajar es:


For(int i=0; i<Arreglo.size(); i++)

Es la manera más popular de encontrarlo y sencillo de aprender de usar un FOR, pero una vez que es completamente entendido y manejado, existe una manera sencilla de optimizar el código, pero que en un principio a simple vista puede ser extraño y más difícil de entender.

En C++


For(int i=Arreglo.size(); i-- ; )

En C#

int Size= Arreglo.size();
For(int i=0; i<Size; i++ )

De esta manera evitamos llamar la función obtener el tamaño y aparte evitamos la variable temporal que esta comparación debe generar. Ahora este método solo es útil siempre cuando no importa tener que trabajar en orden con el arreglo.

Como reducir tamaño del build en Unity para mobiles

Sonido:

Al agregar archivo de audio para el proyecto en Unity, siempre usa puro sonidos en modo MONO, es decir que solo tiene un canal y por lo tanto se va escuchar exactamente igual como en el lado izquierdo y lado derecho. Ya que la mayoría de los celulares solo tienen una bocina y aunque tuvieran más de uno, suelen estar juntas y sonidos con efecto estereo se pierde. Si una persona juega tu juego y tiene audífonos puesto, simplemente se oirá igual en ambos lados, así que no habrá problema.

¿Porque? Bueno, un archivo de audio grabado en estéreo tiene el doble de información aunque sonara igual el sonido como en el lado izquierdo y lado derecho. Un ejemplo, una música de fondo puede pesar 4MB en modo estéreo y en modo Mono pesaría 2MB. El cual implica la mitad de espacio que usara en tu build final, mitad de RAM en uso, mitad en tiempo de carga solo de este archivo, con este espacio puedes ahora tener 2 canciones de la misma duración con la misma cantidad de recursos.

Para ahorrarse problemas sería mejor si pasáramos el archivo ya mono a Unity, pero si no, podemos indicarle a Unity que nos ayude con esta parte, al seleccionar el archivo de audio, hasta arriba tiene la opción de “Force to Mono” habilitamos y listo.

sonidos

Texturas e imágenes:

La primera regla al trabajar con texturas es siempre cuestionarnos si el tamaño de las texturas realmente son necesarias de ese tamaño, eso que quiere decir, ¿es necesario que la taza que solo sale en una vez en el primer nivel, es un adorno y su textura es de 512 x 512? Algo que le cuesta mucho a los desarrolladores es el sacrificar calidad. Siempre hay que hacer que tenga la mejor calidad los objetos que más serán vistos y con mayor frecuencia el usuario interactuara con ellos, de disminuimos y le reducimos calidad en proporción a lo frecuente y importante que es el objeto, regresando al ejemplo de la taza, si la taza solo sale una vez, su propósito es solamente de relleno y aparte el usuario nunca se acercara a este, podemos bajarle el tamaño de textura a unos 128 x 128 o inclusive a unos 64 x 64. Este tipo de objetos nunca los evalúes desde el Editor abarcando toda tu pestaña de escena. Siempre hazlo desde la perspectiva y distancia que tendrá la cámara en juego. ¿Que si te fijas muy bien, si se alcanza a notar? Ok, y el jugador por las mecánicas de tu juego, ¿tendrá que tener fija su mirada por donde estará la taza? Esto serán las cosas que tenemos que cuestionar y analizar para determinar la calidad de objeto ya sea Sprite o un modelo 3D.

“Generate MipMaps”: Esta opción esta al seleccionar imágenes que se usaran como Sprite. Este hay que deshabilitarlo cuando el sprite vaya ser usado en el UI o sabemos que no jugaremos con las escalas del sprite. ¿Porque? Bueno, esto es porque los MipMaps son copias de menor calidad que Unity genera de manera automática para que en caso de escalar, no tenga que calcular como se vería la imagen. El problema de esta opción es que crece un 30% del peso final de tus texturas. Nota, en objetos 3D esto siempre tiene que estar activado.

mipmap

Estos tips pueden ayudar mucho en el tamaño del build final como en el consumo de RAM del juego.

Consejos para aprender programación

Cuando uno se va metiendo en el mundo de programación, a veces es difícil meterse, ya que la programación es tan variado y siempre puedes encontrar algo nuevo que aprender. Pero entonces, ¿Como uno puede ingresar al mundo de la programación? Dejo aquí unos pequeños consejos, pero pueden guiar a cualquier programador.

Programa, programa y programa.

Una vez entendido que son variables, if, for, while, switch y funciones. Programa y programa, la verdad no hay mejor manera. Ponte un meta, uno básico por ejemplo es hacer una calculadora y avanza paso por paso, te topas con un problema o error, solucionarlo y avanza. A lo mejor puede tomarte 1 día,   2 o más la primera vez y no te sientas tonto por esto, estarás aprendiendo y así empezamos todos.

Divide tu meta en pasos.

Nunca trates de programar todo de un golpe, siempre hazlo por pequeños pasos y submetas. En el caso de una calculadora, ok, primero haz un botón, luego que imprima un “Hola” al presionar el botón, después duplicarlo y posicionar como seria los botones de la calculadora, seguido de que al presionar un botón de un numero este lo imprima, después que al presionar un segundo botón, ya se combine con lo que ya estaba escrito, después que si presiono otro botón como suma, obtener y almacenar el numero escrito. Así consecutivamente y probando en cada paso y solucionando problemas como surjan. Esto es más fácil de ir arreglando y a la larga más rápido.

Explícaselo al ‘Pato’.

Cuando no entiendas que sucede algo que no funcione correctamente, primero levántate, despéjate un rato, luego ve por un pato de bañera, un juguete que aun contengas o un peluche y explícale que hace tu código (No le digas tus problemas, explica que hace tu código línea por línea) aunque te sientas un tonto, te sorprenderá como al explicar un código puedes encontrar muchos errores desde lógica a dedo.

B75vnDaIgAAXGDV.jpg large

Lee teorías y algoritmos.

Nunca hay tiempo para programar de todo y tener experiencia en varios aspectos, pero es muy útil si lees teorías, algoritmos o técnicas que usaron otros para resolver problemas. Entender cuál es la teoría para llevar a cabo un problema, aunque no te enfrentes al mismo, tener mucha referencias, puedes usarlas para resolver otros problemas.

No tengas miedo de usar otros códigos y re usarlos.

La comunidad de programadores, es de los mejores ejemplos donde la ayuda mutua logra grandes cosas. Busca códigos en San Google, rehúsa los código que ya hayas usado. En la programación es mucho usar código ya existente para avanzar y resolver problemas, no hay nada de malo, es muy útil y además nadie sabe todo y menos en algo tan extenso como la programación. Eso sí, entiende aunque no sea línea por línea, pero si la lógica y concepto de lo que has copiados, porque muchas veces encontraras más que nada ejemplos, y tendrás que modificar para tus necesidades y unirlo a lo que ya tienes.

¿Pagina que recomiendo?

Yo recomiendo la pagina Code.org, el cual esta destinada a fomentar y enseñar desde entender como es la lógica que se requiere para llevar acabo a la programación a través de ejercicios que van con interfaces muy clic, arrastra y suelta, hasta pequeños códigos para darnos idea. Los cuales mientras estudias un lenguaje de programación recomiendo que prueben los tutoriales y juegos de Code.

Que es el Lerp y como usarlo correctamente

Lerp o Interpolaciòn lineal, es la linea continua que se genera entre un punto inicial y un punto final. Y se puede sacar cualquier punto de esta recta linea, solo necesitamos un porcentaje donde 0% es el punto inicial y 100% es el punto final. En otras palabras podemos obtener cualquier coordenadas que se encuentre entre estos 2 puntos.

LerpExample

NOTA: en programacion 0% – 100% se representa con 0 – 1

Esto en videojuegos se utiliza para hacer mover un objecto cuando deseamos que vaya de un punto A a un punto B. Pero generalmente suele usarse de una manera incorrecta. Codigo base en Unity: Ejemplo:


float Speed = 5f;
transform.position = Vector3.Lerp.html(transform.position, Destiny, Speed * Time.deltatime);

 

¿Porque es incorrecto esto? Bueno imaginemos que estoy en (0,0,0) y deseo ir a (10,0,0).

Frame 1: El Lerp me devolverá un punto entre el inicio y el final, más o menos como a 0.01f (Speed( que es 5f) * Time.deltatime (Que puede ser como un 0.02f)), esto me moverá a  (0.1, 0, 0) porque es el 1% de 10 que es la distancia a recorrer en X.

Han pasado varios frames después en el que ya voy a mitad del destino, es decir mi GameObject va en(5, 0, 0), sigo pidiendo el punto a 0.01, pero ahora no entre (0, 0, 0) y (10, 0, 0), si no de (5, 0, 0) y (0,0,0), es decir el 1% de 5 que es la distancia en X, sera 0.05, ¡ya la mitad de lo que empece en el primer frame a moverme!, esto genera que el movimiento tenga una velocidad uniforme y se vaya desacerando y tarde algo en llegar al destino. Muchos no lo notan y solo piensan que no es preciso y lo “solucionan” que si esta ya a cierta distancia, ya “llego”.

¿Como usar correctamente Lerp?

Ya entendiendo la teoría y el problema, tenemos siempre que conservar el punto inicio y avanzar a un ritmo. Esto podemos hacer así.


float rateTiempo = 1f/TiempoEnHacer;
float rateVelocity = 1f/ Vector3.Distance(startPos, endPos) * Velocidad;
float t = 0.0f;

if(t <= 1f)
{
 t += Time.deltaTime * rate;
 transform.position = Vector3.Lerp(startPos, endPos, t);
}

‘rate’ solo tenemos que sustituir por ‘rateTiempo’ o ‘rateVelocity’ según si necesitamos que recorra eso siempre en un tiempo exacto o se mueva a una velocidad. Y ‘startPos’ son las coordenadas del punto inicial y ‘endPos’ son las coordenadas donde deseamos terminar.

De esta manera, siempre la distancia es la misma y la velocidad constante. Ahora existen 2 rate en este caso, la  ‘rateTiempo’ cuando deseas que haga el recorrido en un cierto intervalo de tiempo o ‘rateVelocity’ para hacer el recorrido a una velocidad, cualquiera de las 2 se sustituye por ‘rate’ dentro del if.

La misma teoría se aplica para la rotación, Vectores 2, 3, 4 o incluso solo un lerp entre 2 números.

Aquí dejo un paquete de Unity que contiene una escena con un pequeño ejemplo Ejemplo Lerp.