A MOVER ESA NAVE!

Vamos a pasar a la acción directamente y vamos a mover a nuestra nave. Para esto, y como había nombrado, recuerden que el componente Transform es el que se encarga de posicionamiento, rotación y escala. Así que cualquier transformación de esas que queramos hacer, se la tenemos que pedir a ese componente. Para esto, hay dos variables que vamos a usar siempre, y si nos falta una, podemos acceder siempre a través de la otra:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log(transform);
        Debug.Log(gameObject);
    }
}

 

 

La variable transform nos da acceso al componente Transform y la variable gameObject nos permite acceder al GameObject entero donde están todos los componente. ¿Por qué son tan importantes? En primera, porque cada una guarda una referencia a la otra, o sea que podría escribir gameObject.transform o transform.gameObject para acceder desde una a la otra. Pero… ¿Por qué guardar cada una en la otra? Varios componentes de Unity nos brindan muchas veces una variable o la otra por diferentes razones. Entonces… Sin importar cual de las dos tengamos, sabemos que podemos acceder a la otra.

Pero de esas dos variables, la más importante es gameObject, puesto que si puedo acceder al GameObject contenedor de todo, también debería poder acceder a cualquier componente que dicho GameObject tenga. Más adelante, cuando sea necesario, les voy a mostrar cómo.

Ahora vamos con la parte “copada”… ¿Y cómo lo movemos? Bien… Teniendo acceso al componente Transform sólo tenemos que acceder a las propiedades que controlan la información de posición:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log(transform.position);
        Debug.Log(transform.localScale);
        Debug.Log(transform.rotation);
    }
}

 

 

Lo que estoy haciendo en esta porción de código es imprimiendo los valores de posición, escala y rotación del objeto. Como verán, cuando apreten el botón de “Play” el objeto mostrará siempre los mismos valores puesto que no cambian… A menos que los movamos… Pero hay algo que tenemos que tener en cuenta al momento de hacerlo, y es que el movimiento se hace a través de vectores. O sea, no podemos sumarle o asignarle un valor X como 4 a la posición del objeto, sino que tenemos que asignarle un tipo de dato llamado Vector3.

 

VECTOR3 PARA MOVER OBJETOS

Es un tipo de dato que representa un vector en 3 dimensiones (x, y, z). Unity lo usa para muchas cosas, entre ellas, trasladar, escalar y rotar objetos. Para asignar estos valores tenemos que hacer cuentas que den como resultado un Vector3. Matemáticamente tenemos cuentas con las cuales podemos generar este tipo de dato. Por ejemplo, un Vector3 multiplicado por un escalar, nos da como resultado otro Vector3.

Este tipo de dato también tiene propiedades estáticas que nos facilitan algunas cosas. Por ejemplo:

 

Vector3.zero
Vector3.down
Vector3.left
Vector3.right
Vector3.up
Vector3.one

 

Esto nos facilita algunas cuentas. Por ejemplo, si querémos obtener un Vector3 que apunte hacia la derecha con una longitud de 3 podríamos escribir algo como:

 

Vector3.right * 3;

 

Esto nos devuelve un Vector3 con el valor (x=3, y=0, z=0). O sea que… Si querémos que nuestra nave se mueva hacia la derecha, tendríamos que escribir en nuestro código algo como esto:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        transform.position += Vector3.right * 3;
    }
}

 

Guarden el script (algo que SIEMPRE deben hacer), y pruebenlo. Van a notar que la nave se va hacia la derecha MUY RÁPIDO. Esto es porque de esta manera la nave se está moviendo hacia la derecha 3 metros POR FRAME. O sea, cada vez que Unity ejecuta el bloque Update(). Esto es unas 60 veces por segundo, aunque a veces pueden ser 1000 o pueden ser 2. ¿Por qué es tan variable? Bueno… La realidad es que depende de la computadora que tengamos y de qué tan cargado esté el juego. O sea que cada vez que estos factores cambien, la nave se movería más o menos rápido. Por supuesto, esto no es lo que querémos. En cada juego querríamos que las velocidades sean las mismas, y no diferentes según la computadora del usuario.

Acá vienen, de nuevo, al rescate las matemáticas. Podemos hacer una cuenta que haga que el personaje se mueva por segundo, sin importar cuál sea el framerate. Para ayudarnos con esto, Unity nos da una variable llamada Time.deltaTime. ¿Qué hace exactamente esta variable? Básicamente almacena el tiempo que tardó Unity en pintar el último frame. Esto significa que a mejor PC, este valor es más chico, y mientras peor sea, más grande es. O sea, inversamente proporcional. Vamos a ver algunas cuentas.

FPS Time.deltaTime

1

1

2

0.5

4

0.25

5

0.2

10

0.1

20

0.05

60

0.016

144

0.00694

 

Podríamos decir entonces que el valor de Time.deltaTime es 1 / FPS.

Entonces… Podemos usar este valor como multiplicador, ya que: Mientras PEOR sea nuestra PC entonces MÁS GRANDE va a ser este valor, por ende el héroe se movería TRAMOS MÁS GRANDES. Por el contrario, mientras MEJOR sea nuestra PC entonces MÁS CHICO va a ser este valor, por ende el héroe se moverá TRAMOS MÁS CORTOS. De esta forma, en todas las PCs debería moverse a la misma velocidad, y con esto me refiero a llegar al mismo tiempo a un punto determinado, sin importar si se ve más intercalado o cortado en una PC que en otra.

Es importante aplicar este concepto para todo lo que requiera un tiempo, lo cual no necesariamente significa que todo lo que deba ser por tiempo tenga que ser multiplicado por Time.deltaTime. Pero quizás todo lo que queramos que dependa de un tiempo y está dependiendo actualmente de un FrameRate sí debamos multiplicarlo por esto… Quizás… Siempre depende del caso.

Entonces, para que nuestro código quede “mejorado”, la sentencia debería quedar de esta manera:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        transform.position += Vector3.right * 3 * Time.deltaTime;
    }
}

 

 

Prueben ahora el proyecto, y van a ver que la nave se mueve más lenta. Aunque no es exactamente “más lenta” la definición, sino que ahora se mueve POR SEGUNDO. Antes se movía al ritmo del FrameRate, ahora se mueve por segundo. Por supuesto alguien podría decir: “Che… Pero se sigue moviendo por frame”… Y tendría razón, porque se mueve en el bloque Update(), pero para arreglar la oración podríamos decir que ahora nuestra nave, en el estado actual, se mueve a “3 metros por segundo“, mientras que antes se movía a “3 metros por frame“.

 

VARIABLES EN EL INSPECTOR

Una de las cosas que Unity nos permite hacer es modificar nuestras variables desde el editor. O sea, si mi nave tiene ciertas variables que yo podría llegar a querer cambiar en algún momento determinado, podría exponerlas en el editor para que se puedan cambiar mediante un campo de texto y no tener que volver al código, recompilar y tener otro valor. Para hacerlo, lo único que necesitamos es que nuestra variable sea pública. Para esto solo basta crearla con el modificador de acceso public de la siguiente manera:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    public float speed;
    
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        transform.position += Vector3.right * 3 * Time.deltaTime;
    }
}

 

 

De esta manera podremos ver que aparece en el inspector de Unity para que la podamos modificar, cuando seleccionamos a nuestra nave, o a cualquier GameObject que contenga nuestro script.

 

 

Por supuesto, el cambio que restaría hacer sería reemplazar el valor “3” que tenemos en el código por la variable que acabamos de crear:

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Hero : MonoBehaviour
{
    public float speed;
    
    // Use this for initialization
    void Start ()
    {
        
    }
    
    // Update is called once per frame
    void Update ()
    {
        transform.position += Vector3.right * speed * Time.deltaTime;
    }
}

 

 

Ahora ya podemos modificar la velocidad de nuestra nave desde el editor de Unity. Esto nos permite realizar cambios de una manera mas “accesible” a nosotros y a la persona que esté encargada de armar los niveles, como un Game Designer o Level Designer.