Jorge Vallejo Blog

Blog del creativo, ilustrador y profesor de videojuegos Jorge Vallejo

Category: unity

Nace Unity Do , el camino del videojuego

Llevaba un tiempo pensando en crear un canal de youtube donde volcar mi conocimiento sobre programación y Unity, como docente de videojuegos, hay muchas cosas que me dejo en el tintero en las clases, por falta de tiempo.

Unity a sufrido constantes mejoras en los últimos años, algunas de las cuales se han vuelto muy interesantes pero demasiado especificas , por ejemplo el nuevo sistema para animación 2D, por eso en el canal Unity Do, puedo explorar los nuevos paquetes, las actualizaciones, assets y tambien hacer hincapie en la programación y el diseño de videojuegos.

¿Por qué es necesario crear un canal como Unity Do?

Como su nombre indica UnityDo es un guiño a las artes marciales, como Judo, Taekwondo , Karate Do.. en ese caso el do significa camino, una filosofia de entrenamiento y mejora continua, que es precisamente la quiero inculcar en el canal.

Por lo tanto Unity Do, es el camino de Unity, el camino del videojuego, y mi intención es conseguir fomentar la programación y el desarrollo de videojuegos en castellano, ya que hay muy buenos canales en ingles, pero creo que en español , que tambien les hay muy buenos, nos falta ser un poco mas desprendidos con el conocimiento e ir más alla de lo basico.

Como en cualquier otro proyecto que uno se embarca debe aspirar a lo máximo, mi reto es conseguir tener un dojo virtual, una comunidad de seguidores, que hayan pasado del blanco al negro, de apenas tener un concomiendo a ser capaces de crear grandes videojuegos.

Escenas de paisajes en Unity

Crear escenas de paisajes es una buena practica para entender como posicionar elementos, como crear una composición y como funcionan las luces en Unity, trabajando con un directional light y unas pocas luces mas para matizar es suficiente.

Un protocolo de trabajo, sin utilizar terrains, que serán explicados en otro articulo

Gran Capitán creado en Unity3d
Escena creada con Unity

1) Cambiamos el modo de Color Space a linnear en File-> Build Settings ->Player Settings ->Other Settings -> Linnear

2) Metemos un skybox de un cielo

3) El skybox nos dará una definción aproximada de la hora del día, amanecer, atardecer etc

4) Colocaremos la rotación del directional light basándonos en la hora aproximada del día, si es de noche podemos dar una luz azulada tenue

5) Importar las texturas y crear los materiales colocando sus mapas

6) Importar diferentes modelos para crear una composición general (Montañas, rocas, arboles

7) Colocar los objetos creando la composición, se puede importar una referencia y meterla en un plano, o usar Cinemachine >Storyboard

8) Creada la composición los gameobjects serán marcados como static

9) Los objetos complejos se aumenta su escala en el lightmap en el Mesh Renderer ->Lightmap Settings -> Scale Lightmap (Para que aparezca el objeto tiene q ser static)

10) Si queremos meter reflejos , creamos un Reflexion Probe , y lo colocamos en los objetos que tengan propiedades metalic , specular o roughness

11) Colocamos la cámara creando el cuadro de la composición

12) Bakeamos ->Lighting->Settings->Generate Lighting

13) Podemos meter como máximo un par de point light para crear ambientaciones

14) Corregimos iluminaciones y posiciones

15) Volvemos a Bakear

Unity crear arrays o matrices

¿Qué es una matriz o array de elementos?

Podemos definir un array como una lista de elementos ordenados, de tal forma que iremos guardando datos en diferentes “cajas” las cuales están ordenadas y numeradas con un indice único que empieza en 0 en csharp y Unity la crearemos definiendo:

Primer el ámbito de aplicación, si es publica o privada

Después el tipo de variable o clase por ejemplo int

Después los corchetes que van a servir para identificar el array o matriz, de tal forma que mientras int numero solo puede contener un número int[] Numeros va a poder contener una cantidad de elementos que debemos dar al crear la matriz, reservando en memoria espacio para esos elementos.

Podemos darle el nombre que queramos, aun que yo aconsejo poner la primera letra en mayúsculas y en plural para que de una forma sencilla distingamos una matriz de otro tipo de variables.

En general determinaremos cuantos elementos va a contener el array ya que necesariamente necesita saberlos para funcionar, si no sabemos el numero de elementos que va a contener hay otras estructuras como los List que lo permiten.

Con new llamamos al constructor del array ya que en csharp los arrays o matrices funcionan como objetos, con sus propias propiedades y métodos , para dar un numero de elementos debemos usarlo, finalmente una matriz de tipo int solo podrá contener int, por eso escribimos int[20], reservando memoria para 20 enteros.

Para acceder a un elemento usaríamos Numeros[indice] , por ejemplo Numeros[0] nos devuelve el elemento que este guardado en la “caja” 0

Si definimos la matriz utilizando el constructor, en este caso al ser números enteros todos los elementos tendrían un valor inicial de 0.

Podemos también definir una matriz de esta otra forma:

En vez de usar el constructor utilizamos una colección de elementos, la cual se define con llave { elementos separados por comas y fin de llave }

Automáticamente la matriz se define con seis elementos como si se hubiese utilizado new int[6]

Numeros[0] , nos devolvería en este caso 1

Unity eliminar duplicados en un cadena

Existen diferentes formas de conseguir eliminar duplicados en una cadena, las formas más sencillas sería utilizar otros métodos como puede ser importar System.Linq la cual nos permite “limpiar” de duplicados con su método Distinct.

Sin embargo como ejercicio para comprender el funcionamiento de los arrays creo que puede ser muy útil hacerlo nosotros mismos, ya que tendremos que ver previamente como saber si un elemento está en un array y como añadir un elemento a un array.

Primer vamos con ¿Cómo saber si un elemento está en un array?

bool LetraEstaEnMatriz(char letra, char[] Letras){
		for (int i = 0; i < Letras.Length; i++) {
			if (letra == Letras [i]) {
				return true;
			}
		}
		return false;
	}

Creamos una función que devuelve un bool y recorremos el array comparando letra a letra, al hacer return si encuentra una letra se sale de la función por lo que no continua el for

La siguiente función a implementar es la que nos añade un elemento a un array , lo normal es añadirlo al final del array, la ventaja de crear nuestra propia función es que podriamos cambiar este orden si quisieramos.

char[] AñadeLetraAMatriz(char letra,char[] Letras){

		//se aumenta la matriz
		char[] Copia_letras=new char[Letras.Length+1];

		for (int i = 0; i < Letras.Length; i++) {
			Copia_letras [i] = Letras [i];

		}
		//queda la ultima
		Copia_letras[Letras.Length]=letra;
		Letras = Copia_letras;
		return Letras;
	}

Un array no permite añadir directamente, lo que hay que hacer es crear una copia previa, dejando un “espacio” para la nueva letra, despues se vuelca todo el array y finalmente se añade la última, volvemos a meter los elementos en el array original con Letras=Copia_letras y finalmente devolvemos el array con las letras

Ahora nos queda la parte final, para eliminar los duplicados, crearemos otra función

char[] SacaLetrasSinRepetir(string _palabra){
		char[] Letras=new char[0];

		for (int i = 0; i < _palabra.Length; i++) {
			for (int j = 0; j < _palabra.Length; j++) {

				if (i != j) {
					if (_palabra [i] == _palabra [j]) {
						if (!LetraEstaEnMatriz (_palabra [i], Letras)) {

							Letras = AñadeLetraAMatriz (_palabra [i], Letras);
						
							break;
						}
					} else {
						if (!LetraEstaEnMatriz (_palabra [i], Letras)) {
							Letras = AñadeLetraAMatriz (_palabra [i], Letras);

						}
					}
				}			
			}

		}
		return Letras;
	}

Primero creamos un array de dimension 0 que esta preparado para ir añadiendo letras, con char[] Letras=new char[0];

Despues recorremos _palabra , aqui hay que tener en cuenta que necesitamos dos bucles anidados para que haga la comparación de una letra con todas las demás.

Si tenemos por ejemplo una cadena “AABB”, lo que debemos hacer es comparar el elemento 0 , es decir A con ABB, despues la segunda A con BB ..

Por eso usamos los dos for, ahora bien una letra siempre será igual a si misma por eso despreciamos el caso i==j quedándonos solo con i!=j

Si la letra coincide es igual a otra, es decir esta repetida, comprobamos que no la tenemos ya en la matriz, con la función LetraEstaEnMatriz (_palabra [i], Letras) como es no , usamos la exclamación para negar el caso quedando

!LetraEstaEnMatriz (_palabra [i], Letras) si entramos en este if significa que no tenemos la letra en Letras por lo que la podemos añadir con la función

Letras = AñadeLetraAMatriz (_palabra [i], Letras); Después tenemos un break; este hace que se salga del primer for, por que ya no necesitamos comprobar más si tenemos una A que es igual a otra la guardamos solo una vez

Nos queda la otra posibilidad que la letra no sea igual, la guardamos en la misma matriz Letras, así tendremos tanto las que se repiten como las que no.

Sólo queda devolver el array que contendrá las letras sin los duplicados con un return

Como siempre digo en mis clases , este es el camino que he elegido yo, no es el único , quizá tu lógica te lleve por otro hasta es posible que el código se pueda optimizar más, para eso debes buscar tu propio camino.

Recreando iVisual , Escuela de nuevas tecnologías de Valladolid en Unity

Primero se tomaron fotos de referencia.

Después, se recrea la geometría base utilizando Probuilder, el cual nos permite modelar dentro de Unity, colocamos un FPS Controller para movernos por el escenario, en esta fase es fundamental corregir escalas, probar q el personaje se mueve con soltura sin estar demasiado “apretado”, también se colocan cubos simples con los objetos base, que seran convertidos en Prefabs para ser sustituidos después.

Colocamos materiales con texturas, Probuilder va creando las UVs por lo que simplemente seleccionado caras podemos asignar los materiales. También colocamos los primeros modelos.

En este proyecto las luces se apagan y encienden en tiempo de juego, por lo que las pusimos mixed, hay q tener en cuenta que al añadir el postprocesing todo se volverá algo más oscuro.

Las bombillas llevan un material de emisión que se puede desactivar por código, Material.DisableKeyword(“_EMISSION”);

Finalmente añadimos los efectos de postproducción con Postprocesing v2, en esta versión podemos controlar diferentes postprocesing mediante volumen de forma que podemos tener un postprocesing en el pasillo y otro distinto en una habitación.

El efecto Bloom pertime que los materiales emisión se vean más suavizados y con un halo.

La corrección de color, colocamos todo el color en ACES el modo más fílmico y ajustamos la exposición, contraste etc.

Con Screenspace añadimos reflejos en el suelo en aquellos materiales que tienen algo de reflexión.

También metimos reflexion probes para controlar los reflejos del Ironman , los cuadros y las manillas de las puertas.

Unity luces: Recreando Cesta de pan, de Salvador Dalí

Inspirado en el cuadro de Dalí, Cesta de pan, recreo la composición y las luces en Unity, utilizo un spot light para iluminación base y area lights para marcar zonas de brillo, finalmente subo el contraste con postprocesing.
Modelos usados :
Mesa:
https://sketchfab.com/models/e9ef3eadee9d4491b7c59fdbb19c30cd

Cesta de pan:
https://sketchfab.com/models/bb7e9cf4496f420c8d825d2e507f124b

Pan:
https://sketchfab.com/models/35c647c3231b4d7ba3dfdc1d0ba4d036

Unity script saber si un número es par o impar

Un script muy sencillo de c# que pongo de ejemplo para usar el operador % modulo , y comprobar su utilidad, el cual devuelve el resto de una división.
Ya que el resto de la división de un numero par entre dos es siempre 0
public int numero;
if(numero%2=0){
print(numero+" es par");
}else{
print(numero+" es impar");
}

Demo de ¿Donde está Lupo?


Se trata de un videojuego sencillo, basado en la realidad de tener un gato y no saber por dónde anda, así q la pregunta ¿Donde está Lupo? Surge cada día.
De este hecho cotidiano decidí darle una vuelta para crear un videojuego pensado para el aprendizaje de idiomas, ya que recuerdo que el tema de las localizaciones me daba quebraderos de cabeza en inglés.
Como últimamente he estado diseñando en pixel art, deci hacerlo con un estilo parecido a las aventuras gráficas tipo Lucas Arts.
El proyecto está en desarrollo, pero ya es funcional.
Si os interesa saber más sobre ¿Donde está Lupo? Dejarme un comentario.

Realidad Virtual Unity abriendo y cerrando un cajón

YouTube player

En Realidad Virtual la interacción lo es todo, es curioso como Oculus provee de un SDK para empezar a desarrollar y que sin embargo traiga sólo ejemplos de agarrar y lanzar objetos y nada sobre elementos que desplazan , giran, mueven etc.
Así que hay que buscarse la vida, en este caso por ejemplo, con un trigger compruebo si la mano entra en la zona del cajón, después paso su velocidad al cajón, el cual tiene un rigybody con y,z frezeadas así como todas las rotaciones, finalmente con un Mathf.Clamp controlo las posiciones maximas y mínimas. El resultado es funcional, aunq me quedaría controlar si está en modo agarrar, es decir con el puño cerrado.