Unity Scripts
Revisión del 17:25 25 ene 2019 de Wiki (discusión | contribuciones) (→Obtener una referencia de cualquier componente)
Sumario
Introducción
- Ya vimos anteriormente en esta Wiki como crear un script y sus dos métodos principales.
- Ahora explicaré unos conceptos básicos de programación para los que no sepan programar y quieran aprender operaciones básicas para mover-interaccionar con las figuras 3D.
- Es resto de alumnos, puede ir a las secciones siguientes.
Programación básica
Referencias dentro de los Scripts
- Los scripts son la base del desarrollo de videojuegos.
- A pesar de las herramientas que nos ofrece Unity para 'crear' una escena, el movimiento-detección de colisiones-acciones deben ser programadas para dar sentido a nuestro videojuego.
- Los scripts son asociados a un GameObject de la escena.
- Para 'asociar' un script a un GameObject debemos añadir un componente de tipo script y escoger el script creado.
- También se puede 'arrastrar' el script a la ventana Inspector, estado el GameObject seleccionado.
- Nota para programadores:
- Los que sepan de programación orientada a objectos, todos los GameObjects vienen a ser Instancias de una clase en el momento el que se ejecuta el juego.
- Los scripts también son clases que se instancian cuando se inicia la ejecución.
- Dentro del script, podemos acceder a la instancia de la clase Transform y que guarda toda la información de rotación-escalado-posición del GameObject asociado.
- La forma de acceder es mediante la orden: transform (con minúscula) o gameObject.tranform.
- Fijarse que 'gameObject' lleva la primera letra con minúscula, indicando que hace referencia a la instancia 'actual' del gameobject asociado al script.
- Por lo tanto, todas las propiedades que aparecen cuando estamos en un script hacen referencia al 'gameObject' asociado y es lo mismo poner gameObject.propiedad que propiedad.
- Dentro de un script podemos definir propiedades que hagan referencia a otros gamebjects o componentes.
- La forma de hacerlo es la siguiente:
1 using UnityEngine;
2
3 public class ScriptCubo : MonoBehaviour {
4
5 [SerializeField]
6 public Transform esfera;
7
8 // Use this for initialization
9 void Start () {
10 Debug.Log(gameObject.transform.position);
11 }
12
13 // Update is called once per frame
14 void Update () {
15
16 }
17 }
- Como vemos estamos definiendo una propiedad con visibilidad public.
- Al hacerlo, dicha variable aparece reflejada en la ventana Inspector cuando asociemos el script a un GameObject.
- En la imagen hemos 'arrastrado' el script al gameobject Cubo (o lo podemos añadir pulsando el botón add component y buscando el script).
- Como vemos, gráficamente aparece la propiedad Transform que hemos definido en el script.
- Ahora solo tenemos que arrastrar un GameObject de la escena a dicha propiedad.
- Lo que hemos hecho es hacer que la propiedad esfera definida en el script (public Transform esfera) pase a ser el transform de la esfera.
- Por lo tanto, ahora desde el script 'ScriptCubo' el cual está asociado al gameobject Cubo vamos a poder realizar cualquier operación sobre el transform del objeto esfera.
- Por ejemplo, vamos a hacer que el cubo se sitúe en la posición de la esfera.
- Para ello modificamos el script y añadimos las siguientes líneas al método update:
1 void Update () {
2
3 esfera.position = transform.position + Vector3.up*2;
4 }
- Lo que estamos indicando con esta línea es situar a la esfera 2 unidades por encima (en el eje Y) de donde se encuentre el cubo.
- Se ejecutamos el juego y movemos el cubo en ejecución podemos comprobar como se mueve la esfera.
- Las posibilidades que nos brinda esto son muchas.
- Imaginar un juego en el que quieres que al protagonista (el cubo) siempre lo siga sin fiel robot (la esfera) a una cierta distancia...
- Podríamos modificar el script para que al pulsar la tecla espaciador, la esfera se dirigiera a la posición del cubo a una velocidad determinada...
1 public class ScriptCubo : MonoBehaviour {
2
3 [SerializeField]
4 public Transform esfera;
5 [SerializeField]
6 public float velocidad;
7
8 .....
9 void Update () {
10
11 esfera.position = Vector3.Lerp(esfera.position, transform.position, velocidad * Time.deltaTime);
12 }
- Recordar darle una velocidad en la ventana Inspector y al ejecutar el juego, podéis comprobar como si movemos el cubo (en la ventana Scene) la esfera lo sigue.
- Al igual que hemos hecho una 'referencia' a la propiedad 'Transform' de un GameObject, podemos pasar referencias de cualquier componente de un gameobject e incluso de un GameObject completo.
- Vamos a modificar el script para que al pulsar la tecla espaciador, la esfera se destruya.
- Para destruir un GameObject necesitamos hacer uso del método Destroy(Object obj, float t = 0.0F).
- A dicho método se le debe pasar como parámetro el objeto que queremos destruir y opcionalmente podemos indicar el tiempo que debe pasar desde que indicamos que queremos destruir el objeto hasta que se destruye realmente.
- Nota: Destruir quiere decir que el GameObject se elimina de la escena (y también se libera la memoria asociada al mismo).
- El script modificado es el siguiente:
1 using UnityEngine;
2
3 public class ScriptCubo : MonoBehaviour {
4
5 [SerializeField]
6 public GameObject esfera;
7
8 // Use this for initialization
9 void Start () {
10
11 }
12
13 // Update is called once per frame
14 void Update () {
15
16 if (Input.GetKeyDown(KeyCode.Space))
17 {
18 Destroy(esfera, 2);
19 }
20
21 }
22 }
- Línea 6: Ahora la referencia va a ser un GameObject (con todos sus componentes)
- Línea 16: Comprobamos si pulsamos la tecla barra espaciador.
- Línea 17: Eliminamos de la escena a la esfera después de 2 segundos.
- Cambiando la escala
- Con el anterior ejemplo debéis de tener claro que en Unity todo son clases (todos los componentes de un GameObject, el GameObject en si mismo,...) por lo que vais a poder obtener las referencias a dichas clases y cambiar por programación cualquier propiedad de las mismas o llamar a métodos que estén definidos en las mismas.
- Podéis crear referencias a luces, a cámaras, a animaciones,...a cualquier GameObject o componente que podáis añadir a un GameObject.
Obtener una referencia de cualquier componente
- Vimos en el punto anterior como obtener una referencia 'de forma gráfica' de un componente o GameObject.
- Pero en el desarrollo del juego vamos a necesitar tener referencias a esos mismos componentes directamente en el código.
- Para obtener una referencia a un componente de un GameObject necesitamos utilizar el método getComponent.
- Un ejemplo concreto para obtener el componente Transform de un objeto sería:
1 Transform transform = MiGameObject.getComponent<Transform>();
- Entre los < Tipo > indicamos el tipo de componente que queremos recuperar.
- Aún no vimos como gestionar las colisiones entre GameObjects, pero uno de los componentes que se utilizan son los Collider.
- En el ejemplo anterior, podemos ver como el cubo tiene un 'Box Collider' como uno de sus componentes.
- Si quisiéramos obtener una referencia a este componente dentro del código de un script podríamos hacerlo de la siguiente forma:
1 BoxCollider boxCollider = gameObject.GetComponent<BoxCollider>();
- Nota:Recordar que dentro de un script podemos poner 'gameObject.' de forma optativa.
- La línea anterior sería igual a poner: BoxCollider boxCollider = GetComponent<BoxCollider>();
- Veamos un pequeño ejemplo en el que vamos a modificar el tamaño del BoxCollider dinámicamente al pulsar la tecla C.
- El código del script (siguiendo el ejemplo de la sección anterior) sería el siguiente:
1 using UnityEngine;
2
3 public class ScriptCubo : MonoBehaviour {
4
5 [SerializeField]
6 public GameObject esfera;
7
8 private BoxCollider boxCollider;
9
10 // Use this for initialization
11 void Start () {
12 boxCollider = gameObject.GetComponent<BoxCollider>();
13 }
14
15 // Update is called once per frame
16 void Update () {
17
18 if (Input.GetKeyDown(KeyCode.C)) {
19 boxCollider.size = new Vector3(3, 3, 3);
20 }
21
22 if (Input.GetKeyDown(KeyCode.Space))
23 {
24 Destroy(esfera, 2);
25 }
26
27 }
28 }
- Línea 8: Declaramos la propiedad boxCollider de tipo BoxCollider que es privada por lo que no aparece en la ventana Inspector.
- Línea 12: Cuando se inicie el script, obtenemos la referencia al boxCollider del GameObject al que está asociado el script (en el ejemplo es la esfera).
- Línea 19: La propiedad boxCollider ahora tiene todos los métodos y propiedades del componente BoxCollider que aparece en la ventana Inspector.
- Entre ellos está la propiedad 'size' que espera recibir un Vector3.
- Si ejecutamos el código:
- Ejemplo de referencias utilizando GetComponent
- Este mismo proceso lo podemos realizar sobre los componentes de cualquier GameObject al que podamos acceder.
- Por ejemplo, en el caso anterior, vamos a hacer que también se modifique el Collider de la esfera.
- Si pulsamos sobre la esfera podemos comprobar que el tipo de collider de la esfera es una SphereCollider y que la propiedad para cambiar su tamaño es 'radius':
- Como dentro del script tenemos una referencia al GameObject Sphere podemos obtener su componente de la forma:
1 // Update is called once per frame
2 void Update () {
3
4 if (Input.GetKeyDown(KeyCode.C)) {
5 boxCollider.size = new Vector3(3, 3, 3);
6 SphereCollider sphereCollider = esfera.GetComponent<SphereCollider>();
7 sphereCollider.radius = 3.5f;
8 }
9
10 if (Input.GetKeyDown(KeyCode.Space))
11 {
12 Destroy(esfera, 2);
13 }
14
15 }
- Nota: Se pone 3.5f para indicar que el valor es de tipo 'float', es decir, un número con decimales. Si es entero no hace falta poner el punto y Unity realiza la conversión internamente (de forma implícita).
- Si ejecutamos el código:
- Ejemplo de referencias utilizando GetComponent
Métodos de la clase MonoBehaviour
- Awake/Start
- Reset
Orden de ejecución de los scripts / Componentes
-- Ángel D. Fernández González -- (2018).