Páginas

jueves, 27 de marzo de 2014

Una historia de producción

Tenemos dos trabajadores, el trabajador A y el trabajador B, que tienen que entregar un producto en una fecha concreta.



Para hacer ese producto se han de hacer dos tareas,  una de las tareas depende de la otra.


Asignamos una tarea al trabajador A y otra al trabajador B.

Ahora el mapa ideal de la producción sería que el trabajador A teminara su tarea unos días antes del deadline, para dar tiempo al trabajador B de completar su tarea.


Pero el productor no consigue transmitir lo a sus trabajadores este mapa ¿Qué sucede entonces?

Que en ausencia de planificación todos los trabajadores interiorizan que sus tareas deben estar completadas para el día de la entrega.

Y el trabajador A tiene este mapa en su cabeza.


Y el trabajador B lo mismo.


Al combinarlos, obtenemos este escenario.


Lo cual es imposible, ya que las tareas dependen una de la otra.

Con lo que el trabajador B empezará a quejarse unos días antes de la entrega.



Y el escenario final será éste.


Y sí, lo habéis adivinado.





sábado, 22 de marzo de 2014

De Scorsese a Leónidas o cómo recuperar la ilusión por crear



Ésto es un fragmento de una entrevista a Martin Scorsese que refleja un punto de vista que comparto, especialmente la última frase, porque frente a la ilusión que uno siente por crear siempre se alzan otras fuerzas que se oponen a este interés. Estoy hablando de intereses económicos, prejuicios o simple ignorancia, y para sacar una idea adelante hay que tener muy claro que te vas a enfrentar a todo ésto.

Como diseñador yo elijo tener una actitud apasionada y desafiante, pero también he tenido que ceder algunas veces a estas fuerzas, y han sido momentos muy dolorosos en que he tenido que tirar semanas de trabajo por culpa de fuerzas a las que, desde mi posición, no tenía capacidad de oponerme. Y hay que saber recuperar la ilusión después de éstos golpes, darse un tiempo para descansar y lamerse las heridas para después levantarse y volver a la batalla, aunque sea para que te partan la cara otra vez, porque por eso somos creativos, porque nos gusta innovar y estamos dispuestos a pagar el precio que supone luchar contra las convenciones.

Solo entonces escucharemos de nuevo el rugido del pequeño Leónidas que todos tenemos dentro, gritándonos.



Diseñadoreeeeeeees ¿Cuál es vuestro oficio?

Y contestaremos





¡AU! ¡AU! ¡AU!

domingo, 16 de febrero de 2014

Creando billboards en Unity

Crear un billboard en Unity es sencillo pero como todo, cuando te pones a hacerlo tiene su arte.



Para quien no lo sepa, un billboard es un plano 2D que se orienta automáticamente hacia la cámara, como estos árboles de Mario Kart.

Script

Este es mi script para billboards. He implementado tres métodos distintos.

using UnityEngine;
using System.Collections;

public class Billboard : MonoBehaviour {

public enum Metodo
{
metodo1,
metodo2,
metodo3

}

public Metodo metodo;

// Use this for initialization
void Start ()
{
if(metodo == Metodo.metodo1)
{
DoLookAt1();
}
else if(metodo == Metodo.metodo2)
{
DoLookAt2();
}
else if(metodo == Metodo.metodo3)
{
DoLookAt3();

}

}

// Update is called once per frame
void Update ()
{
if(metodo == Metodo.metodo1)
{
DoLookAt1();
}
else if(metodo == Metodo.metodo2)
{
DoLookAt2();
}
else if(metodo == Metodo.metodo3)
{
DoLookAt3();
}

}

void DoLookAt1()
{
// Tomo mi posicion y la de la camara
Vector3 cp = Camera.main.transform.position;
Vector3 op = transform.position;

// Proyecto las posiciones en el plano XZ
Vector3 cp2 = new Vector3(cp.x, 0, cp.z);
Vector3 op2 = new Vector3(op.x, 0, op.z);

// Muevo el objeto y la camara a las posiciones en XZ
transform.position = op2;
Camera.main.transform.position = cp2;

// Hago un lookAt
transform.LookAt(Camera.main.transform);

// Restauro las posiciones
transform.position = op;
Camera.main.transform.position = cp;

}

void DoLookAt2()
{
// Copio la rotacion de la camara
transform.rotation = Camera.main.transform.rotation;

// Pongo el objeto mirando al lado contrario
transform.Rotate(0, 180, 0);

}

void DoLookAt3()
{
// Tomo los angulos de euler de la camara y oriento el objeto
Vector3 ce = Camera.main.transform.eulerAngles;
transform.eulerAngles = new Vector3(0, ce.y, 0);

// Lo pongo a mirar en sentido contrario
transform.Rotate(0, 180, 0);

}
}


Método 1


// Tomo mi posicion y la de la camara
Vector3 cp = Camera.main.transform.position;
Vector3 op = transform.position;

// Proyecto las posiciones en el plano XZ
Vector3 cp2 = new Vector3(cp.x, 0, cp.z);
Vector3 op2 = new Vector3(op.x, 0, op.z);

// Muevo el objeto y la camara a las posiciones en XZ
transform.position = op2;
Camera.main.transform.position = cp2;

// Hago un lookAt
transform.LookAt(Camera.main.transform);

// Restauro las posiciones
transform.position = op;
Camera.main.transform.position = cp;


Lo que hace el método es transferir la cámara y el billboard al plano XZ, hacer un lookAt a la cámara y restaurar las posiciones de los objetos.




Con este método los billboards se orientan a la posición de la cámara.



En la vista, da sensación de perspectiva porque los billboards no tienen todos la misma orientación. Si eso es lo que se busca, pues ya está.


Método 2

// Copio la rotacion de la camara
transform.rotation = Camera.main.transform.rotation;

// Pongo el objeto mirando al lado contrario
transform.Rotate(0, 180, 0);


El método 2 lo que hace es poner a los billboards mirando en dirección contraria a la cámara.


Todos los billboards tienen la misma orientación.


Y la vista no da efecto de perspectiva. Probablemente esto sea lo que se busque en la mayor parte de los casos.


Ahora bien ¿Qué pasa si la cámara rota en X, o sea hace un picado? Que los árboles también miran hacia arriba. Nuevamente ésto puede ser bueno o puede ser malo, dependiendo de lo que se busque.


En la vista todos los árboles se ven de frente  pesar del picado.


Método 3

// Tomo los angulos de euler de la camara y oriento el objeto
Vector3 ce = Camera.main.transform.eulerAngles;
transform.eulerAngles = new Vector3(0, ce.y, 0);

// Lo pongo a mirar en sentido contrario
transform.Rotate(0, 180, 0);


Soluciona los problemas del método 2 porque tomamos solo el ángulo de euler Y de la cámara, lo transferimos al objeto y rotamos 180 grados en Y.


Con ésto los árboles no rotan en X y mantienen la perspectiva en el picado, lo que en este caso tendría sentido en mi opinión.

Descarga

Dejo aquí el proyecto, se abre con Unity 4.3






sábado, 15 de febrero de 2014

La buena, la fea y la mala o cómo implementar una pausa en Unity




Podríamos decir que, como en la mítica película del oeste, hay tres formas de implementar una pausa en Unity, la buena, la fea y la mala.

Empezaré por la mala.

La mala

La mala es poner el timeScale a 0, lo que provoca que se pause todo Unity, es decir el sistema de animación, el de físicas, etc. Solo podremos activar y desactivar objetos o recibir eventos.


void OnPause()
{
    Time.timeScale = 0;
    menuPause.active = true;
}

void OnResume()
{
    Time.timeScale = 1;
    menuPause.active = false;

}


Es un sistema sencillo y rápido de implementar, pero como he dicho tiene la desventaja de que no se pueden usar animaciones, por lo que el menú de pausa aparece y desaparece de golpe.

La buena

La buena es que tengamos un GameManager que sepa qué objetos forman parte del juego y que sea capaz de mandarles una señal a todos los objetos del juego para que se pausen y se despausen. Cada objeto implementará la pausa a su manera y el resto del engine seguirá funcionando como siempre.

Un objeto típico haría algo así

bool paused;

void Update( float delta )
{
    // Si estamos en pausa cortamos aquí
    if (paused) { return; }


    ...

}


void OnPause()
{
    animation.Stop();
    paused = true;

}

void OnResume()
{
    animation.Play();
    paused = false;

}


Y en el GameManager


List<GameObject> gameObjectList;

void OnPause()
{

    foreach(GameObject o in gameObjectList)
    {
        o.SendMessage("OnPause");
    }

    menuPause.animation.Play("Appear");
}

void OnResume()
{
    foreach(GameObject o in gameObjectList)
    {
        o.SendMessage("OnResume");
    }

    menuPause.animation.Play("Dissapear");

}


Este sistema requiere de una buena planificación a la hora de implementar el juego, porque hay que controlar qué se pausa y qué no, pero a cambio podremos tener unos menús de pausa animados.

La fea

La solución fea es... Poner el timeScale a un número muuuuuy pequeño, con lo que todos los sistemas siguen actualizándose pero muuuuy poco, con lo que podremos usar animaciones en el menú de pausa siempre y cuando las reproduzcamos a una velocidad muuuuuuy alta.

void OnPause()
{
    Time.timeScale = 0.00000001;

    menuPause.animation.speed = 10000000; 
    menuPause.animation.Play("Appear");

}

void OnResume()
{

    Time.timeScale = 1;
    menuPause.animation.speed = 1;
    menuPause.animation.Play("Dissapear");

}


Si un jugador paciente se queda mirando a la pantalla durante tres horas igual te pillan.

Conclusión

Estos son los tres métodos que conozco. La buena es adecuada si se tiene tiempo y se pone cuidado al implementarla, la mala es adecuada si no se tiene tiempo y se busca algo seguro, y la fea... Pues... Es fea. Si es el día de entrega y se tiene que implementar una pausa deprisa y corriendo... Puede ser una solución, pero yo no me iría a dormir tranquilo.

Aunque le haya llamado así, en el mundo real la fea es la adecuada para la mayor parte de los casos :)

Más info en Unity Answers.

sábado, 8 de febrero de 2014

Haciento tests

Esta tarde he hecho un test para una conocida compañía de videojuegos que empieza por g. El test no puedo difundirlo pero nadie dijo nada de mi solución, así que allá va.

Tres items para un juego de carreras



Dos tipos de superficie que no sea asfalto:


Diseña un circuito fácil:



Diseña un circuito difícil:


En total le he dedicado dos horas. He ido un poco deprisa y corriendo, como si estuviera haciendo un examen.

lunes, 3 de febrero de 2014

Recomendaciones para un juego de lucha


Una empresa me ha pedido que les haga una recomendación como diseñador para su juego de lucha, y ahí que he ido. Si me hubieran pagado ya la cosa hubiera sido genial pero ya se sabe cómo es España y también cómo salen las cosas luego, claro.  Aquí dejo el documento.


Nuevo blog profesional

Ha llegado el momento de dar un paso adelante y profesionalizarse, por lo que he creado un nuevo portafolio profesional con un look más serio. Espero que algún día me sirva para conseguir un trabajo mejor.



Este blog voy a continuar actualizándolo porque aquí puedo expresarme con más libertad y mantener en forma el espíritu juvenil. Según el proyecto en que me meta lo iré colocando en un blog u otro.