Aprende Unity [1]

Hola bienvenido al comienzo de esta hermosa capacitación que le voy a brindar de manera gratuita. Si aún no sabe como es la forma de esta capacitación, le invito a leer el post anterior AQUÍ. Bien, pasaremos a ver el temario de lo que veremos en el día de hoy.

Temario

Propiedades

Las propiedades son muy útiles para mantener el principio de encapsulamiento que rige en la programación orientada a objetos(POO).

Operador Ternario

Sirve mucho para reducir líneas de código, es un condicional simple en una sola línea de código.

Estáticos

Variables y métodos estáticos, son valores o acciones accesibles desde cualquier sitio.

Sin aún no ha visto el video de práctica, aquí se lo dejaré. Si ya ha visto el video simplemente lo puede saltear o verlo nuevamente si lo desea.

Ahora daremos comienzo a la teoría. ¿Esta preparado? Espero que si. Acomódese bien y comenzamos.

TEORÍA

PROPIEDADES

Bueno antes de comenzar vamos a repasar el resumen que he dejado más arriba. 
«Las propiedades son muy útiles para mantener el principio de encapsulamiento que rige en la programación orientada a objetos(POO).»

Para comenzar debemos conocer algunos de los principios del paradigma orientado a objetos, el cual es utilizado por Unity. Puntualmente debemos saber que nos dice el principio de encapsulamiento. Antes de eso veremos que nos dice wikipedia al respecto de la POO.

programación orientada a objetos

Los objetos son entidades que tienen un determinado «estado», «comportamiento (método)» e «identidad»:

  • La identidad es una propiedad de un objeto que lo diferencia del resto; dicho con otras palabras, es su identificador (concepto análogo al de identificador de una variable o una constante).

Un objeto contiene toda la información que permite definirlo e identificarlo frente a otros objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al poder tener valores bien diferenciados en sus atributos. A su vez, los objetos disponen de mecanismos de interacción llamados métodos, que favorecen la comunicación entre ellos. Esta comunicación favorece a su vez el cambio de estado en los propios objetos. Esta característica lleva a tratarlos como unidades indivisibles, en las que no se separa el estado y el comportamiento.

Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados por la propiedad de conjunto. Esta propiedad destaca que una clase requiere de métodos para poder tratar los atributos con los que cuenta. El programador debe pensar indistintamente en ambos conceptos, sin separar ni darle mayor importancia a alguno de ellos. Hacerlo podría producir el hábito erróneo de crear clases contenedoras de información por un lado y clases con métodos que manejen a las primeras por el otro. De esta manera se estaría realizando una «programación estructurada camuflada» en un lenguaje de POO.

La programación orientada a objetos difiere de la programación estructurada tradicional, en la que los datos y los procedimientos están separados y sin relación, ya que lo único que se busca es el procesamiento de unos datos de entrada para obtener otros de salida. La programación estructurada anima al programador a pensar sobre todo en términos de procedimientos o funciones, y en segundo lugar en las estructuras de datos que esos procedimientos manejan. En la programación estructurada solo se escriben funciones que procesan datos. Los programadores que emplean POO, en cambio, primero definen objetos para luego enviarles mensajes solicitándoles que realicen sus métodos por sí mismos.

Fuente :»es.wikipedia.org»

Principio de encapsulamiento

Significa reunir todos los elementos que pueden considerarse pertenecientes a una misma entidad, al mismo nivel de abstracción. Esto permite aumentar la cohesión (diseño estructurado) de los componentes del sistema. Algunos autores confunden este concepto con el principio de ocultación, principalmente porque se suelen emplear conjuntamente.

Fuente :»es.wikipedia.org»

explicación

Bueno ahora que ya sabemos a grandes rasgos de qué trata la programación orientada a objetos y el principio o característica de encapsulamento de dicho paradigma, es hora de darle nuestra explicación.
Pasaremos a explicar el cómo y porqué utilizar este principio y cómo las propiedades son una parte fundamental para respetarlo.

Imaginemos que cada clase es un objeto independientemente que esto no es real, ya que un objeto es una instancia (creación) de una clase, pero para simplificar el ejemplo vamos a suponer que así es. 
Si cada objeto tiene todas sus partes abiertas (métodos y variables) cualquiera puede entrar y alterarlo causando daños en su funcionamiento. Entonces lo que debemos hacer es controlar ese acceso, no darle libertad a cualquier para acceder sino sólo compartir la información que necesita el otro objeto de mi.

Vamos a poner un ejemplo, si tenemos sin protección al personaje, es posible que por un fallo de la interfaz de usuario o de un enemigo haga que el personaje se comporte de manera errónea. Al intentar solucionar ese comportamiento indebido, lo primero que iremos a ver es si el personaje posee algún error, incluso es posible que hagamos cambios en su código incluso cuando ahí no radica nuestro error.
Ahora viene el gran problema, puede pasar que rompas el código del personaje intentado solucionar ese problema, o en el mejor caso solo desperdicie valioso tiempo intentando llegar al error. Usted dirá que es fácil encontrar el error, simplemente se ven las referencias y se detectará que el enemigo provoca el error. A simple vista esto parece estar en lo correcto pero a medida que el proyecto crece y las referencias aumentan, esto se vuelve cada vez más insostenible, solucionar un bug le lleva cada vez más tiempo. 

Tal vez usted me dirá que lo realiza rápido para probarlo, que luego lo va arreglar cuando el proyecto comience a crecer. Lamento informarle que esta manera de pensar es un error, ya que te tomará más tiempo reestructurar su código cuando el proyecto ya haya crecido , en vez de hacerlo desde un principio.
Como ya podrá ver nuestra forma de pensar, le aconsejamos que se plantee el encapsulamiento de métodos y variables desde el inicio del proyecto.

Bueno ahora pasaremos a explicar el porqué las propiedades son un punto fundamental para aplicar este principio. Nosotros debemos tener todas nuestras variables en privadas(private) o en caso de herencia en protegidas (protected). Se preguntará y ¿cómo hago para compartir la información con los otros objetos? Para eso es qué existen las propiedades, lo que hace es definir si la propiedad es sólo de lectura o sólo de escritura o ambas. Luego se define que hacer cuando lees la propiedad, puede ser que le des el valor de una variable privada o un cálculo que realices con una variable privada,etc. eso lo debe decidir usted, lo mismo sucede cuando se escribe una propiedad , puede asignarla directamente a una variable privada o llamar a un método privado, hacer un cálculo matemático, entre otras cosas que puede llegar a utilizar.

¿Cómo utilizar las propiedades?

Le daré un par de ejemplos para que vea cómo Unity utiliza las propiedades.

public class Personaje : MonoBehaviour
{
    int experiencia;
    public int Experiencia
    {
        get { return experiencia; }
        set { experiencia = value; }
    }
    public int Nivel
    {
        get { return experiencia / 1000; }
        set { experiencia = value * 1000; }
    }
    public int Vida { get; set; }
}

Como podemos ver la variable experiencia no está declarada como pública, por lo tanto no puede ser accedida por un objeto externo. Sin embargo, la experiencia es una variable que se necesita tanto para ser obtenida como modificada por varios objetos externos, como por ejemplo los enemigos o la interfaz de usuario.
Entonces para esto creamos una propiedad pública (es muy importante que la propiedad sea pública) la cual devuelve en valor entero pero puede devolver cualquier tipo permitido por Unity, ya que como mencionamos anteriormente no es está necesariamente ligada a una variable. 

Ahora una vez creada la propiedad debemos decir si es posible la lectura o la escritura. Puede ser una u otra o ambas. Con el get (lectura) y el set (escritura). En cuanto a la práctica debes manejar desde los objetos externos como si una propiedad fuera una variable pública (en caso de que esté acostumbrado a la practica de colocar variables públicas). 
No acostumbres a colocar la escritura dentro de las propiedades sólo utilizarla en caso de que sea necesario actualizar los datos de la propiedad desde un objeto externo, siempre que pueda evitarlo, hágalo. Trate de manejar el flujo de información dentro del mismo objeto, y en caso de ser necesario utilizar las propiedades para la comunicación con objetos externos.

En el caso de la propiedad Nivel es un ejemplo claro de la utilización de un cálculo dentro de una propiedad. Esta toma el valor de la variable privada experiencia y calcula el Nivel en base a la cantidad de experiencia que tiene el jugador. Este es uno de muchos ejemplos en donde se puede utilizar las propiedades de esta manera. Muchos ya estarán aplicando esto mediante métodos; no digo que esté mal utilizar métodos en algunos casos, pero va a depender estrictamente de la situación, no siempre se puede utilizar las propiedades para cálculos o métodos para los cálculos. Más adelante cuando tratemos temas de buenas práctica en el desarrollo explicaremos más en profundidad esto que acabo de mencionar.

Perfecto, todo esto que me esta enseñando es genial, pero en muchas ocasiones necesito editar una variable desde el inspector y si es privada no puedo acceder a ella, y si es pública no tiene sentido utilizar propiedades. Para eso se debe colocar un modificador llamado [SerializeField], esto permite que una variable privada sea mostrada y modificada desde el inspector de Unity. Más adelante explicaré más a fondo el tema de la serialización de campos, por ahora sólo le dejaré un ejemplo para que lo vaya implementando de a poco.

public class Personaje : MonoBehaviour
{
    [SerializeField] int experiencia;
}

Por último en el ejemplo de la propiedad Vida, tenemos una declaración vacía de la propiedad lo que significa que se maneja igual que una variable pública, aún no le encuentro mucha utilidad, sobretodo en que casos utilizar esta forma de propiedad, pero si está permitido debe tener un porqué. En lo personal si colocamos la propiedad de esta manera tenemos el mismo nivel de control que una variable pública ya que no existe un filtro entre los datos internos y cómo los datos internos deben comportarse ante los datos externos.

Nuestros servicios

¿Necesita que desarrollemos su proyecto?


Desarrollo

¿Necesita aprender cómo desarrollar su proyecto?


Tutoría

TEORÍA

OPERADOR TERNARIO

Bien ahora comenzamos con el operador ternario, como es de costumbre analizaremos el resumen dejado más arriba.
«Sirve mucho para reducir líneas de código, es un condicional simple en una sola línea de código.» No hay demasiado que explicar en este caso, es un muy buena práctica para la optimización de lineas de código, además tendrás un código mucho más limpio y fácil de mantener. Lógicamente es igual que un if de única línea, la ventaja está a la hora de mantener el código limpio, legible y reducido. 
Bueno sin más vamos a ver el ejemplo.

public class OperadorTernario : MonoBehaviour
{
    void Start()
    {
        int vida = 10;
        string mensaje;
        mensaje = vida > 0 ? "Estoy vivo" : "He muerto";
    }
}

Analicemos un poco de que trata esta simplificación. 
Tenemos 2 variables, una de tipo entero y otra de tipo cadena de texto. Cuando la vida (entero) es mayor a cero, la variable mensaje (cadena de texto) va a valer «Estoy vivo» en caso contrario valdrá «He muerto». El ejemplo es muy sencillo. Es lo mismo que el siguiente ejemplo.

public class OperadorTernario : MonoBehaviour
{
    void Start()
    {
        int vida = 10;
        string mensaje;
        if(vida>0)
            mensaje="Estoy vivo";
        else
            mensaje= "He muerto";
    }
}

Como puede llegar a notarlo es mucho más limpio, fácil de entender y reduce líneas de código, es por lo cual recomiendo utilizarlo siempre que tenga la oportunidad. Recuerde que funciona para una sola línea, no serviría si dentro del if necesita tener más de una línea de código.

TEORÍA

ESTÁTICOS

Bueno ahora comenzaremos con los estáticos, es un modificador que permite acceder los datos que hay en ella desde cualquier punto. Este modificador se puede usar para clases, métodos y variables. Para las clases, esto permite poder llamar a una clase sin la necesidad de crear una instancia de ella, si bien llamar a una clase en sí no tiene sentido alguno; pero si deseas acceder a una variable o método que también necesitan ser estáticos si es de mucha utilidad. 

Veamos algunos ejemplos para aclarar el cómo se usa.

public class Enemigo : MonoBehaviour
{
    public static int enemigoCantidad = 0;
    private void Start()
    {
    }
    public Enemigo()
    {
        enemigoCantidad++;
    }
}

Como podemos ver en este ejemplo, sólo la variable enemigoCantidad es estática, la clase y los métodos en ella no lo son. 

public class Juego2 : MonoBehaviour
{
    private void Start()
    {
        Enemigo enemigo1 = new Enemigo();
        Enemigo enemigo2 = new Enemigo();
        Enemigo enemigo3 = new Enemigo();
        Debug.Log(Enemigo.enemigoCantidad);
    }
}

Tenemos que tener en cuenta si la clase no es estática, aún así podemos acceder a la variable estática y no requiere que haya una instancia de esa clase en el escenario. Tal como se hace en el Debug.Log, en esa sentencia no se llama a una instancia de la clase, no se llama ni a enemigo1, ni 2, ni el 3; llamamos directamente a la clase y accedemos a su variable.
En este ejemplo creamos 3 instancias de la clase Enemigo, con el propósito de aumentar el valor de enemigoCantidad, ya que en el constructor de la clase Enemigo se suma 1 al valor existente de enemigoCantidad. Si no sabe lo que es un constructor de una clase, es un método definido por el lenguaje que es llamado cuando se crea una instancia de la clase, este método puede o no ser utilizado. 
Bueno ahora veremos un ejemplo de método estático.

public static class Utilidades 
{
    public static int Agregar(int valor1, int valor2)
    {
        return valor1 + valor2;
    }
}
public class UtilidadesEjemplo : MonoBehaviour
{
    private void Start()
    {
        int valor = Utilidades.Agregar(5, 6);
        Debug.Log(valor);
    }
}

Como podrá observar tenemos en el primer código una clase llamada Utilidades, la cual tiene un método estático Agregar. Este método puede ser llamado desde cualquier lado, este tipo de métodos son muy útiles a la hora de hacer cálculos que se van a necesitar varias veces en su programa. Si bien en el ejemplo la clase es estática pero no es necesario que lo sea para poder acceder al método estático. Vuelvo a repetir que es una buena práctica la utilización de métodos estáticos para la reutilización de código, aunque en lo personal no uso variables estáticas ya que se mantienen en memoria todo el tiempo, lo cual puede afectar al rendimiento de su programa.

DESPEDIDA

Si ha llegado hasta aquí quiero felicitarlo por su esfuerzo y dedicación con el aprendizaje de su carrera profesional. Espero que le haya sido de utilidad, que le haya gustado. Déjanos su comentario que le ha parecido nuestro primer post de la saga Aprendiendo sobre Unity. Nos vemos en el próximo post.

“Esfuércese, capacítese y haga la diferencia”

Comienzo de la capacitación

Aprendiendo sobre Unity

Comienzo de la capacitación

Hola bienvenido/a, te doy las gracias por estar aquí, seguirnos en nuestro trabajo. Hoy vamos a ver en qué consiste esta capacitación, asumo que has venido aquí mediante el video; en caso contrario aquí te lo dejo:

Bien, vamos a explicar un poco más de la información que presenta el video. Esta es una capacitación en línea gratis para personas que desean aprender más sobre Unity. Este material no sirve para personas que no saben absolutamente nada de Unity Engine. Ya que lo básico lo he explicado en muchas ocasiones y hay mucho material de este tipo en Internet.

La idea de este material es aportar algo nuevo y distinto a la red; no tiene sentido hacer lo mismo que todos hacen. Si no sabes nada o sabes muy poco sobre Unity. Aquí te dejo un material que puedes visitar y aprender lo esencial que debes saber para poder tomar esta capacitación:

CONOCIMIENTOS PREVIOS:

Si al menos tienes un año de experiencia trabajando o estudiando Unity, entonces puedes realizar el estudio de este material. La capacitación se estructura en 2 partes como mencioné en el video; la primera parte consiste en un video corto en donde enseñaré la práctica del tema explicado; la segunda parte es un post en este mismo blog en donde explicaré extensamente la teoría de esta práctica.

¿A qué me refiero cuando digo extensamente? Además de lo obvio, los post serán bastante largos, por lo cual van a exigir más esfuerzo para aprender esto que un simple video de 20 minutos que puedas encontrar en Youtube. En caso de que desees aprender la práctica sin más puedes ver solo el video práctico y listo; pero lo más recomendable es que estudies todo el material. Si bien te llevará más tiempo hacerlo pero te prometo que te servirá mucho más que si solo ves el video.
Hoy en la era digital estamos acostumbrados a lo rápido, a lo instantáneo, el problema que trasladamos esa ansiedad por consumir información a nuestra capacitación laboral. Lo cual es un error muy grave, ya que no se puede aprender a programar en un lenguaje en un día por más que algunos lo prometan, tal vez puedas aprender algunas cosas básicas pero nada competente laboralmente.

En esta capacitación insertaremos descansos dentro de los post para que sean más fáciles de estudiar.

“Has un pequeño descanso.”

Unity

Si realmente deseas ser competente en tu mercado laboral entonces tienes que comprometerte y hacer la diferencia. Si bien un video es más rápido tanto para aprenderlo como para aplicarlo, pero si no lo aplicas seguido eso que aprendiste no durará mucho tiempo en tu memoria. ¿A qué se debe esto? Se debe al poco esfuerzo de concentración que exige ver un video explicativo. En cambio leer un material sobre un determinado tema exige mucha más concentración y esfuerzo de tu parte para poder entender el material. Esto quiere decir que hay muchas más probabilidades que esta información permanezca en tu memoria.

Existe un detalle más, toda la información puesta en videos está comprimida , resumida, acotada. Por el simple hecho que un video de más de una hora no lo ve casi nadie. A menos que sea una conferencia o algo muy importante. Entonces ¿Por qué estudiar información incompleta o resumida? Por falta de tiempo o porque no quieres esforzarte para realmente capacitarte en el tema. Si tu caso es el primero, si dejas un video a la mitad es más difícil continuar el hilo. A diferencia de dejar un documento o post que estabas leyendo y no lo pudiste terminar de leer. No es necesario que leas toda la teoría en un solo día. Tienes casi una semana entera para ir leyéndolo de a poco y así aprovechar toda la información.

Un detalle muy importante, no omitas ninguna información, para poder aprender algo primero debes desaprender, esto es porque las personas omiten temas que creen dominar y tal vez hay información importante que puede aportar a un mejor manejo del tema que aparentemente manejaban muy bien. Debes estudiar todo el material sin excepción, en caso contrario de que no sepas un tema que no está explicado en la teoría, investígalo, pregunta, estúdialo, no importa cuánto tiempo te tome aprenderlo lo importante para continuar este material es que no tengas ni la más mínima duda sobre ningún concepto. No me molestan las preguntas, puedes comentar el blog o enviarme un mensaje privado a través del formulario de contacto y les responderé lo más pronto que pueda.

Bien como  ya mencioné anteriormente los post serán  un poco largos, esta es una pequeña introducción a la capacitación, en el siguiente post comenzaremos a ver programación basada en la nueva API de Unity (en lo personal uso la beta de Unity 2019, aunque no es obligatorio tener esta versión para estudiar el material, con la 2018 es suficiente). Antes de irme quisiera decirte que además de código también explicaremos sobre mantenimiento de código, administración de sistemas de gran tamaño, sistemas multidisciplinarios, ya que cuando trabajamos solos o entre pocos no hay problema pero cuando son muchos los que trabajan en un mismo recurso las cosas comienzan a complicarse. Éstas prácticas no son meras técnicas que saco de algún libro y ya, sino es lo que uso en donde trabajo.

using UnityEngine;
public class Prueba : MonoBehaviour
{
void Start()
{
Debug.Log("<b>Esta capacitación va a ser genial</b>");
}
}

No quiero que te vayas hoy sin que te lleves al menos unos consejos sobre programación. No hagas lo más rápido sino lo que es correcto.

Un ejemplo simple de esto que acabo de decir sería las personas que por trabajar más rápido o esforzarse menos, no comentan su código. Esto es un error gravísimo, uno de los más graves que puede tener un programador que aspira a ser profesional. Tienes que evitar esta mala práctica a toda costa, no significa que tengas que comentar cada linea de código pero una buena práctica es comentar cada método y si el método es muy complejo tener algunos comentarios dentro de él.

Ahora veremos un ejemplo:

using UnityEngine;
public class Prueba : MonoBehaviour
{
public Transform objetivo;
void Start()
{
MostrarDistancia();
}
/// <summary>
/// Este método muestra la distancia que hay entre el personaje y el objetivo.
///</summary>
void MostrarDistancia()
{
float distancia = Vector3.Distance(transform.position, objetivo.position);
Debug.Log("<color=#ECFF00> Distancia: </color>"+"<b>"+distancia.ToString()+</b>);
}
}

“Al llamar a un método comentado nos muestra su comentario.”

Unity
Comentar código para Unity

Otra buena práctica que podemos tener es no meter los inputs en un simple if dentro de un Update. Y más cuando un mismo input es comprobado varias veces en un mismo script.

Vamos a ver el ejemplo:

using UnityEngine;
public class Prueba2 : MonoBehaviour
{
void Update()
{

//Este ejemplo es lo que NO deben hacer.
if (Input.GetKeyUp(KeyCode.Z)|| Input.GetKeyUp(KeyCode.V))
Debug.Log("Vete a dormir");
if (transform.position.y < 0)
{
transform.position = Vector3.zero;
if (Input.GetKeyUp(KeyCode.Z)|| Input.GetKeyUp(KeyCode.V))
gameObject.SetActive(false);
}
}
}

La utilización de un método que compruebe las entradas, además de ahorrar líneas de código, hace más fácil identificar y cambiar los inputs del mismo.

Ejemplo correcto:

using UnityEngine;
public class Prueba2 : MonoBehaviour
{
void Update()
{
if (ComprobarEntrada())//Este es el ejemplo de lo que SI deben hacer.
Debug.Log("Vete a dormir");
if (transform.position.y < 0)
{
transform.position = Vector3.zero;
if (ComprobarEntrada())
gameObject.SetActive(false);
}
}

/// <summary>
/// Este método comprueba el ingreso por teclado.
/// </summary>
/// <returns>devuelve verdadero si fue soltada la tecla z o v</returns>
bool ComprobarEntrada()
{
if (Input.GetKeyUp(KeyCode.Z) || Input.GetKeyUp(KeyCode.V))
return true;
else
return false;
}
}

Y bueno llegamos al último tip de esta introducción, en lo personal lo uso mucho, sirve mucho para mantener el código, sobre todo cuando vuelves después de un tiempo de no haber trabajando en el proyecto esto ayuda mucho. Se trata de comentar los métodos que son llamados por un Invoke, InvokeRepeating o Start/StopCoroutine.

Veamos un ejemplo:

using UnityEngine;
public class Prueba3 : MonoBehaviour
{
void Start()
{
Invoke("MostrarTiempo", 2);
}
/// <summary>
/// Muestra el tiempo actual.
/// Es llamado por un Invoke en el método Start.
/// </summary>
void MostrarTiempo()
{
Debug.Log(Time.time);
}
}

La práctica de este comentario es muy importante, por ejemplo que debas realizar una mejora o nueva versión de un proyecto anterior al que trabajas actualmente, no vas a recordar todo el código y si no está comentado de esta manera no podrás encontrar quien está llamando a ese método, ya que visual studio no encontrara referencias cuando coloques la herramienta de buscar referencias al método. Es por eso que debes comentar en donde está siendo llamado, recuerda esto no es para todos los métodos sino sólo para los que son llamados a través de un Invoke, InvokeRepeating o Start/StopCoroutine.

Bueno espero que les haya gustado este precalentamiento, nos vemos en el siguiente post y prepárate para ponerte en acción.

“Esfuérzate, capacítate y has la diferencia”