Unity: programación de videojuego básica en C#.

Yone Moreno Jiménez
15 min readDec 8, 2017

--

Contenidos de esta parte del curso:

Requisitos para seguir el curso:

Crear y aplicar scripts:

Estructura de los scripts

Variables

Operadores de asignación y aritmética

Operadores de comparación y lógica

Métodos / funciones

Curso basado en los tutoriales oficiales de Joshua Kinney. Traducido por Yone Moreno Jiménez.

Requisitos para seguir el curso:

Tener alguna versión de Unity instalada.

Crear y aplicar scripts:

Si queremos programar en Unity necesitamos crear scripts que son unidades de código que realizan una misión, para ello damos clic derecho sobre la carpeta por defecto abajo a la izquierda Assets, Create, Folder, y la llamamos Scripts:

Debería quedar como:

Ahora que tenemos una carpeta en donde organizar todos nuestros scripts creemos algunos de estos, botón derecho dentro de la carpeta de Scripts, create, C# script:

Le podemos dar un nombre, como es un ejemplo pongámosle ExampleScript:

Si pulsamos doblemente sobre el script se nos abrirá en un editor de texto. Lo primero que es bueno saber es qué significa NombreScript : MonoBehaviour. Bien MonBehaviour es una clase de la cual hereda nuestro script y esto nos permite comunicarle a Unity: quiero que mi script sea usado dentro de los objetos del juego ¿vale?.

Aprendamos cómo crear un objeto de juego o GameObject en inglés. Para ello volvemos al Unity, arriba a la izquierda en la Hierarchy clicamos en create, 3d object, capsule:

Hagamos clic izquierdo en nuestro ExampleScript y arrastrémoslo al objeto cápsula que acabamos de crear, con ello logramos asociar el trozo de código al objeto de juego:

Si quisiéramos eliminarlo podríamos hacerlo haciendo clic derecho sobre el título del objeto y en el menú clicar Remove Component:

También se puede añadir un script a un objeto clicando en Add Component, abajo a la derecha, Scripts, elegimos el que queramos:

Además se puede hacer de forma directa en un sólo paso el crear el script y aplicárselo al objeto mediante Add Component, New Script, le damos el nombre que queramos:

Nos daremos cuenta de dos cosas, primero de que el componente, el script, ya nos lo añade debajo de todos los demás, a la derecha, en este caso lo hemos llamado Test:

Otra cuestión es que al hacer así el script no te lo añade en la carpeta actual, en Scripts, sino que lo pone en la raíz del proyecto, en Assets, es decir, no está en la actual:

Sino en la raíz:

Una cosa a tener en cuenta. A mí me gusta depurar usando prints, es decir imprimiendo por pantalla lo que está ocurriendo, pero si tuviéramos un objeto hiper complejo con muchos scripts nos convendría tener una manera de habilitar/deshabilitar cada script para ir comprobando que funciona bien uno a uno. Para ello tenemos la casilla de arriba a la izquierda en cada componente, que nos permite habilitar/deshabilitar cada uno:

Como hemos visto podemos hacer clic en el nombre del componente y darle a remove component para borrarlo, o clic derecho y remove component; pero ojo porque el script seguirá en nuestro proyecto:

Para quitarlo del proyecto vamos al panel de abajo a la izquierda, clic derecho, delete, o pulsando el botón suprimir del teclado:

Estructura de los scripts

A continuación vamos a entender qué significan las partes que componen un script porque así estaremos preparados para crear los comportamientos que queramos que nuestros objetos tengan. Primero, arriba tenemos esas frases que comienzan por using. Esta palabra nos permite acceder a lo que se llama namespaces.

Un namespaces es simplemente una colección de clases a las que se hace referencia utilizando un prefijo seleccionado en el nombre de la clase.

A nosotros nos importa esto para comprender lo siguiente: nuestro script ExampleScript está heredando de MonoBehaviour (ello se observa mediante ExampleScript : MonoBehaviour, los : significan que lo primero hereda, es hijo de, lo segundo).

Es decir, nosotros somos ExampleScript y estamos haciendo uso de cosas que pertenecen a MonoBehaviour, que sería el equivalente a nuestro padre o madre. En la vida real haríamos uso de la casa, y en el script hacemos uso de unas funciones ya presentes como son Start() y Update().

Para probar lo anterior comentemos la línea que pone UnityEngine, los comentarios se realizan con // y señalan que esa línea no va a ser ejecutada, es decir, el programa la va a ignorar. Sería lo mismo que emanciparnos de nuestros padres:

Lo que ocurre es que si nos emancipamos de nuestros padres no podremos usar su casa, por tanto aquí no podríamos heredar de MonoBehaviour y por ello se señala subrayado en rojo como un error.

En concreto si dejamos el cursor sobre el error nos lo explicará comentando que no podemos acceder a MonoBehaviour, lógico porque hemos comentando using UnityEngine y por tanto hemos abandonado la casa de nuestros padres:

A continuación borraremos la // del principio del using que acabábamos de poner y entendamos qué son las clases. Las clases son contenedores de métodos (comportamiento), cosas que se hacen, y datos (variables), cosas que se tienen:

Por ejemplo si quisiéramos crearíamos una clase Player, jugador, y sus métodos serían PlayerMovement, moverlo, PlayerAttack, atacar etc.

Además hay que saber que el nombre de la clase y el fichero deben coincidir, en nuestro caso, arriba, el fichero se llama ExampleScript.cs y la class ExampleScript, esto es así para que Unity pueda saber que archivo de nuestro ordenador contiene la definición del comportamiento del objeto de juego:

Luego hay que tener en cuenta que ya de forma predefinida se nos dan dos métodos (también llamados funciones). Start(), se ejecuta cuando se crea el objeto:

Además hay que tener en cuenta que los métodos son trozos de código que devuelven o no, algo. Es decir, por ejemplo, nuestra madre nos puede llamar lo cual significa que nosotros somos su método, para recoger nuestra habitación. Después de que nosotros recogamos nuestra habitación ‘no le devolveremos nada a nuestra madre’. En el caso de los programas esto se explica mediante la palabra void, vacío en español:

También se nos da la función Update() la cual se ejecuta cada vez que se imprime la pantalla, es decir entre 30 y 60 veces por segundo:

Variables

Para empezar a declarar una variable hay que indicar un accesor. Es decir una palabra que limite qué clases pueden usar está variable. Hay dos palabras public

o private

. Public quiere decir que toda clase puede acceder a está variable. Private significa que sólo la clase actual ExampleScript puede usar esa variable.

Luego seguiremos con el tipo de dato. Este puede ser un float

el cual es un número decimal como 0.2 u 9.7 o 3.14. Un int

es un número entero como 7, o 9 o 1000. Un bool

es un dato que puede contener false o true. Seguro que muchos estaréis pensando ¿por qué hay que usar tipos de datos? Bueno imaginémonos que tenemos un bote que pone ‘pepinillos’. Uno esperaría encontrar pepinillos dentro. Qué ocurre si al destaparlo encuentras pescado crudo. Pues que tendríamos un problema. Pues lo mismo es en código.

Sigamos construyendo la variable. Ahora hace falta darle un nombre. Hay que tener en cuenta que su nombre puede ser cualquiera pero debemos cumplir una regla: su nombre no puede ser alguna de las palabras que se usan en el lenguaje con un significado especial; por ejemplo, no podemos ponerle UnityEngine, porque habría conflicto:

y nos daría un error. Por ejemplo si quisiéramos una variable para guardar la distancia del jugador al suelo la podríamos llamar isGrounded

. Hay que tener en cuenta que los nombres de variables tienen que ser una única palabra, así que si queremos incluir varias, hay que hacerlo como: primeraSegundaTerceraPalabra, es decir la primera inicial en minúsculas y para separar palabras indicar la inicial de cada en mayúsculas.

Luego vamos a inicializar el valor de la variable. Para ello después del nombre, ponemos un = y el valor. En este caso como el valor es decimal, separamos la parte exacta de la decimal con punto y acabamos con f. Además la frase se termina con ; así:

public float speed = 10.0f;

Hasta ahora hemos declarado una variable e inicializado la misma todo en una línea. También se puede hacer en dos pasos, primero declararla vacía y luego en el Start() darle contenido:

Con variables tan sencillas se prefiere hacerlas en línea:

Así que si pulsamos ctrl + s o file save guardamos el código.

De vuelta en Unity veremos que se recarga el script y nos aparece en el objeto una variable llamada speed puesta a 10. Eso es porque la hemos declarado public y es accesible:

Si quisiéramos podríamos cambiar su valor:

Si quisiéramos devolverle el valor original podemos clicar en la ruedita arriba a la derecha, Reset:

Operadores de asignación y aritmética

Primero aprendamos cómo hacer comentarios en bloque o multilínea. Se hacen mediante la escritura de /* */ Todo lo que esté dentro será ignorado por el programa. Los comentarios nos sirven para explicar qué hace el código, son buenos cuando se trabaja en equipo.

Por ejemplo el operador = se usa para asignar lo que está a su derecha a lo que se encuentra a su izquierda, en concreto, en el ejemplo de la variable que acabamos de crear asignamos un valor de 10.0 a la variable llamada speed.

Otro operador es el += Significa coge el contenido de la variable de la izquierda y súmale lo que haya a la derecha, es decir, si tenemos: speed = speed + y; podemos acortar la escritura como speed += y;

Además también existe el -= que resta al contenido de la izquierda lo que pongamos a la derecha, el *= que multiplica al contenido de la izquierda lo que tengamos en la derecha y el /= que divide lo puesto a la izquierda por lo escrito en la derecha.

Ahora bien hay un operador curioso y raro que se suele usar llamado módulo. El módulo es el resto de dividir un número por otro, se denota mediante %

Por ejemplo si tenemos 7 % 3 que se lee ‘siete módulo tres’, el resultado será el resto de la división de 7 entre 3. En contreto 7 dividido por 3 da 2, de resto 1.

El resumen:

Los anteriores realizan una operación con el valor que ya se encuentra a la izquierda, pero también se pueden hacer operaciones más sencillas tipo a = b + c; es decir donde en una variable se guarde el resultado de operar con otras dos:

Bueno, ahora hagamos un ejemplo sencillo de uso de lo aprendido. Primero declararemos algunas variables dentro de nuestro ExampleScript por encima del Start()

Como vemos tenemos la speed, velocidad, distance, distancia y time, tiempo.

Luego nos gustaría hacer algo como calcular la velocidad a la que va el personaje, esto es speed = distance / time;

Además para que sea interesante vamos a imprimir por pantalla el valor que se nos calcula, para ello usamos la función print() y dentro de los paréntesis ponemos un texto que queramos entre comillas dobles

“You are travelling at: “ y como queremos incluir el contenido de una variable usamos el + que significa cógeme y úneme en la frase a imprimir por pantalla con lo siguiente, que es el nombre de la variable speed, y luego otro + y las comillas dobles para indicar la unidad de medida “MPH” (miles per hour, millas por hora, porque el ejemplo está cogido de un autor inglés, podríamos poner “Km/h kilómetros por hora”)

Le damos a ctrl s o file save para guardar el código y volvemos a unity, donde nos aparece lo nuevo:

Nos puede sorprender que el valor de speed en Unity sea de 10, porque en el código lo hemos cambiado para que sea 0.0 y hemos guardado. Pero el guardar el código no significa que se sobreescribe lo de Unity, para ello hay que pulsar en la ruedita arriba a la derecha y darle a Reset:

Ahora que está todo a 0, démosle a Play arriba en el botón de la flecha:

Y abajo a la izquierda veremos un mensaje como el siguiente:

You are travelling at NaN MPH.

Esto se debe a que estamos intentando dividir 0 entre 0 por ello sale que la speed es NaN, not a number:

Como queremos calcular cosas cambiemos la Distance a 100 y el Time a 1 y veamos que pasa:

Si le damos a Play y miramos abajo a la izquierda dice:

You are travelling at 100 MPH.

Si pusiéramos Time a 2:

Nos saldría:

You are travelling at 50 MPH.

Operadores de comparación y lógica

Para dar lógica a nuestro programa necesitamos comparar valores de variables mediante condiciones. Por ejemplo el operador == devuelve true si lo que hay a ambos lados es igual, y false si no:

También tenemos el complementario != que significa no es igual que. Da true si lo que hay a ambos lados es diferente y false si no:

Luego tenemos mayor que, da true si lo de la izquierda tiene mayor valor que lo de la derecha, menor que, mayor o igual que, menor igual que:

Luego tenemos los operadores lógicos que se usan para crear comparaciones / condiciones complejas:

&& significa y, || es o, ! es no; se entiende mejor con un ejemplo:

Por ejemplo, normalmente las condiciones y comparaciones se usan dentro de una estructura llamada if. Se escribe:

if( seCumpleCondición ) {

hacerAlgo;

}

Si quisiéramos indicar al jugador cuándo está sobrepasando el límite de velocidad podemos usar lo siguiente:

if( speed > 70 || speed < 40){

print(“You are breaking the law!”);

}

Expresa: si la velocidad es superior a 70 o inferior a 40, pon por pantalla You are breaking the law!, tú estás infringiendo la ley!.

Guardamos y volvemos a Unity.

Si a la derecha ponemos que viajamos Distance 100 en Time 1

Abramos la Console, donde se imprimen los mensajes:

Si no la ves disponible clica en el menú superior en Window -> Console.

En concreto, vemos que vamos a 100 MPH por tanto nuestra velocidad es > 70 y estamos infringiendo la ley:

Si cambiáramos el time a 2, iríamos a 50 de speed y ya no infringiríamos la ley:

El motivo de este comportamiento recordemos que es la condición de dentro del if que acabamos de escribir:

Que expresa si nuestra velocidad speed es mayor que 70 o menor que 40 infringimos la ley, si no, como en este caso, vamos a 50 simplemente imprimimos lo que está fuera del if: You are travelling at 50 MPH.

Métodos / funciones

Ahora vamos a aprender qué son y cómo se usan los métodos. Los métodos son un conjunto de instrucciones. Los métodos son instrucciones que realizan tareas.

Si quisiéramos que la velocidad del jugador se calcule cada vez que pulsemos un botón podríamos empezar creando un método para ello:

void SpeedCheck(){

}

Recordemos que void significa el tipo de dato que nos devuelve el método, en este caso como devuelve nada le ponemos void. SpeedCheck es el título del método, normalmente los nombres de métodos se distinguen de los de variables poniendo la primera inicial también en mayúsculas. Los () paréntesis significan que es un método. Las {} llaves encierran el conjunto de instrucciones que componen nuestro método.

Así que ahora podemos coger el código que habíamos escrito antes seleccionarlo cortarlo y ponerlo dentro del método:

Guardamos y volvemos a Unity:

Le damos a Play y nos damos cuenta de que no se imprimen mensajes en la consola:

Esto se debe a que antes estábamos poniendo todo el código en el método predefinido Start() que se ejecuta al empezar la vida del objeto de forma automática.

Si quisiéramos llamar a nuestra función cuando pulsamos el espacio haríamos lo siguiente:

Es decir dentro del Update() el método que Unity ejecuta cada vez que se imprime la pantalla entre 30 y 60 veces por segundo, escribimos:

if( Input.GetKeyDown(KeyCode.Space)){

SpeedCheck();

}

Esto expresa: si presionamos del teclado el espacio, entonces llama a la función SpeedCheck(). Una llamada a una función es el nombre de la función con los paréntesis ().

Guardamos y volvemos a Unity.

Si volvemos a Unity y le damos a Play veremos que no se imprime ningún mensaje, bien:

Pero si le damos al espacio, sí:

You are travelling at 50MPH.

Ya con esto hemos aprendido a usar los métodos y las condiciones con ifs ;=).

--

--