Scripting en unity #2

Retomaremos lo dado en el anterior post sobre aprendizaje:

Scripting en unity #1

Nuevamente agradecemos a Carlos Marton Pavon por darnos la posibilidad de compartir su material.


Posición rotación y escala

Las operaciones más comunes en un juego son las de Posicionar, Rotar y Escalar. En la unidad anterior vimos como editar la posición de un objeto mediante el transform.position

this.transform.position += Vector3.left*Time.deltaTime;

Ahora vamos ver otra forma, utilizaremos el Translate para trasladarnos entre posiciones.

Translación

Translate tiene varias opciones, nosotros vamos a utilizar la que toma una X,Y,Z y un espacio relativo.

¿Qué es un espacio relativo? Supongamos que tenemos un objeto, digamos… una manzana, en la posición (1,0) y luego tenemos otro… digamos una banana, en la posición (2,0) Estas posiciones son en coordenadas de mundo, la manzana está a 1 metro de el centro de nuestra escena y la banana a 2 metros Ahora si hablamos de coordenadas locales, por ejemplo podemos decir que la banana está a un metro de la manzana, o sea en la posición (1,0) en las coordenadas de manzana. así mismo, la manzana estaría en la posición (-1,0) si tomamos como referencia las coordenadas de la banana.

Si utilizamos como espacio de movimiento el Self, queremos decir que nosotros somos el centro del mapa, por lo que si nos trasladamos a la posición (1,0) nos moveremos una unidad en X, si estamos ubicados en (8,0) pasaremos a (9,0) el código sería así:

void Update () {
float speed = 2;
this.transform.Translate (0.0f, speed * Time.deltaTime, 0.0f, Space.Self);
}

Rotación

Las rotaciones en Unity se manejan en Quaterniones, no me voy a poner a explicar en detalle los Quaterniones porque no hace falta, Unity nos abstrae de la mayor parte de esta necesidad. Las rotaciones podemos verlas desde el inspector en grados, cuando el objeto es rotado, es rotado z grados en el eje z. Desde código, tenemos varias formas de realizar una rotación, las mas comunes son: yo diría que, si mantienen la esfera de la unidad anterior, la cambien por otra figura, ya que no se nota mucho si esta rota. desde el centro hacia una dirección:

void Update () {
float angulo = 90;
this.transform.Rotate (Vector3.left*Time.deltaTime*angulo,Space.Self);
}

O tomando un vector de referencia:

void Update () {
float speed = 90;
this.transform.Rotate (new Vector3(1,1,1), Time.deltaTime*speed,Space.Self);
}

Por ultimo queda la escala.

Unity no tiene una función específica pero podemos utilizar las operaciones matemáticas con vectores para modificar la escala.

float scale = 5
this.transform.localScale = Vector3.one * scale;

Al ejecutar este código nuestro objeto pasará a tener escala 5, muy simple, no? Vamos a darle vida a nuestro objeto y que haga “pulsasiones”

void Update () {
float rate = 4f;
float max = 0.6f;
float min = 0.3f;

float scale = (Mathf.Cos (Time.time * rate ) + 1) / 2;
scale = Mathf.Lerp (min, max, scale);
transform.localScale = Vector3.one * scale;
}


Imput

La principal diferencia entre una película y un juego es la interacción, no podemos hacer un juego si no interactuamos de alguna forma con el usuario! Hay multitud periféricos para cumplir esta tarea, pero hoy veremos los dos mas utilizados, el Mouse y Teclado. Unity nos facilita bastante la vida para leerlos, veamos como:

Teclado

Tenemos varias opciones para manejar el input del teclado, tanto un manager para definir los inputs y así como mediante scripts, y si te interesa, incluso puedes crear tu propio sistema de Input!. El manager es mitad script y mitad editor, se puede acceder a el mediante el menu Edit->Project Settings->Input.

Ahora en el inspector podemos ver el manager y la definición de cada input por nombre.

Desde script, podemos acceder a estas variables mediante el uso del nombre del input que queremos leer, por ejemplo:

if (Input.GetAxis (“Fire1”) != 0) {
transform.Translate (Vector3.one * Time.deltaTime);
}

Esto haría que nuestro objeto se mueva si apretamos el boton 0 del mouse o la tecla Left Control Además disponemos de otro método para obtener el input, podemos hacerlo utilizando los métodos GetKey, GetKeyDown y GetKeyUp, que como su nombre lo indica, nos dicen el estado de determinada tecla en ese momento. Un ejemplo de su uso:

if (Input.GetKeyDown (KeyCode.A)) {
transform.Translate (Vector3.up * Time.deltaTime*10);
}
if (Input.GetKey (KeyCode.S)) {
transform.Translate (Vector3.left* Time.deltaTime);
}
if (Input.GetKeyUp (KeyCode.D)) {
transform.Translate (Vector3.right * Time.deltaTime*10);
}

Con el KeyCode podemos acceder al codigo ASCII de cada tecla de forma sencilla. Un ejemplo típico de movimiento utilizando lo que vimos arriba sería:

void Update () {
float h = Input.GetAxis (“Horizontal”);
float v = Input.GetAxis (“Vertical”);
float speed = 3;
transform.Translate (new Vector3(h,v)* speed * Time.deltaTime);
}

Horizontal y Vertical leen las teclas WASD y las flechas del teclado.

Mouse/Ratón

Leer el mouse en 2D es bastante simple, pero en 3D es un poco más complicado, el Input manager nos permite un poco mas de customización sobre este, sugiero que revisen y exploren que hace cada una. Vamos al código, primero debemos saber cual es la posición del puntero en la pantalla, para esto basta con hacer:

Vector3 mousePosition = Input.mousePosition;

Esto nos dará un vector con la posición del mouse, partiendo de abajo a la izquierda de la pantalla (0,0) y la esquina superior derecha es el (ancho, alto) de la pantalla Estas coordenadas sirven para interactuar con objetos 2D o determinar si el puntero se mueve y hacia donde. Ahora si queremos interactuar en 3D es un poquito más complicado ya que el puntero solo se mueve en 2 direcciones y esto hace que sea difícil saber que tan profundo en el mundo 3D se debe posicionar. La solución simple es trazar una linea desde la posición de pantalla hacia el mapa, si esa linea colisiona con algún objeto del mapa, asignamos esta posición, sino proporcionamos una profundidad arbitraria, esta distancia es la distancia desde la cámara y la podemos obtener así:

   void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //esto tira un rayo desde la posición de la cámara en la dirección del móuse
float profundidad=0;
RaycastHit hitinfo;
if (Physics.Raycast(ray, out hitinfo)) //aqui vemos si colisiona con algo ese rayo
{
this.transform.position = hitinfo.point; //si colisiono con algo, nos posicionamos en ese lugar
}
else
{
depth = 10;
MoverMouseAProfundidad(profundidad); //sino, nos posicionamos en una profundidad elegida de forma arbitraria
}
}
void MoverMouseAProfundidad(float profundidad)
{
Vector3 screenPos = Input.mousePosition; //obtenemos la posición del mouse
screenPos.z = profundidad; //
Vector3 posicionEnElMapa = Camera.main.ScreenToWorldPoint(screenPos);                        this.transform.position = posicionEnElMapa;
}

Has pruebas

Crea una escena, agrega unos objetos, une este script a uno de ellos y observa que ocurre! ScreenToWorldPoint Nos da una posición relativa a la cámara, pero solo funciona si le pasamos una profundidad, sino siempre nos va a devolver la posición de la cámara. Bueno,ahora sabemos mover objetos con el mouse y utilizar rayos para medir distancias pero como sabemos si un objeto con un script ha sido clickeado o seleccionado? Unity tiene funciones para esto! Si el objeto tiene un collider recibirá una notificación cuando el mouse interactue con el. Estas funciones son OnMouseDown, OnMouseUp, OnMouseEnter, OnMouseOver, OnMouseExit y OnMouseDrag. OnMouseDown se activa cuando el objeto es clickeado. OnMouseDrag se activa cuando el objeto esta siendo arrastrado. OnMouseEnter se activa cuando el mouse pasa por encima OnMouseExit se activa cuando el mouse deja al objeto.


 

Hasta otra developeros! ayúdanos a compartir el blog y ayudarnos a seguir creciendo!

 

Comments

One Comment

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *