Diferencia entre revisiones de «Unity Scripts»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 288: Línea 288:
  
 
<br />
 
<br />
 +
=Obtener una referencia a cualquier GameObject=
 +
 +
https://gamedev.stackexchange.com/questions/135209/how-to-store-references-to-scene-objects-in-prefabs/135221
  
 
=Métodos de la clase MonoBehaviour=
 
=Métodos de la clase MonoBehaviour=

Revisión del 11:00 26 ene 2019

Introducción

  • 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

Nombre de los scripts

  • Cambiar el nombre => cambiar clase



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.
Unity3d scripts 16.jpg
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.
Unity3d scripts 17.jpg
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.
Unity3d scripts 18.jpg


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.
Unity3d scripts 19.jpg



  • 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.



  • 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:



  • 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':
Unity3d scripts 25.jpg



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:


  • Durante la programación de un vídeojuego os daréis cuenta de la necesidad de contar con un mecanismo que nos permite acceder a los componentes de un GameObject.
Por ejemplo, podrías tener unos soldados que al pasar a una zona abierta, fueran capaces de detectar al protagonista a una distancia mayor (por lo tanto su collider sería más grande, como hicimos en el ejemplo).



Obtener una referencia a cualquier GameObject

https://gamedev.stackexchange.com/questions/135209/how-to-store-references-to-scene-objects-in-prefabs/135221

Métodos de la clase MonoBehaviour

  • Awake/Start
  • Reset



Orden de ejecución de los scripts / Componentes




-- Ángel D. Fernández González -- (2018).