Entender los scripts de Unity y la Unity scripting API - glantucan/puzzle_game GitHub Wiki
API son las siglas de Application Public Interface, o Interfaz Pública de Programación. Una interfaz en programación (no confundir con la interfaz gráfica de un programa) son las funciones y variables que podemos utilizar de una librería o entorno de programación. En este caso la API de Unity son las variables y funciones que se pueden utilizar de este motor de juego desde nuestros programas.
Todas estas funciones y variables están organizadas en lo que se denominan clases. Un clase es una especie de molde a partir del que se pueden crear instancias (copias) de un objeto. Las instancias de una clase serán objetos (de programación, no físicos) que tendrán las variables y funciones que están definidas en su clase.
Cuando creamos un script en Unity, por defecto vemos en el editor lo siguiente:
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Las dos primeras líneas:
using UnityEngine;
using System.Collections;
Indican que espacios de nombres va a utilizar nuestro script. Las clases de Unity están organizadas en espacios de nombres o paquetes, porque son un montón, y no tiene sentido incluir todo ese código en nuestro juego si no lo estamos usando. Por eso, cada vez que creamos un script de Unity, debemos usar sólo los paquetes que contienen las clases que necesitamos. Si usamos una clase que no hemos incluido el compilador dará un error, diciendo que no encuentra esa clase.
La siguiente línea de código dice:
public class Player : MonoBehaviour {
Esto es la declaración de la clase de nuestro script. Un script define una clase de objeto. Cuando arrastramos el script a un gameobject y se crea un componente con él, ese componente es una instancia de la clase que contiene el script. Podemos crear muchas "copias" o instancias de un script. Cada una de ellas contendrá todas las propiedades y métodos que definamos en la clase. Cada una de ellas puede tener valores diferentes almacenados en esas propiedades.
Así, la clase que estamos creando se llama Player
. Y esta clase hereda
de MonoBehaviour
, o lo que es lo mismo: Player
extiende la clase MonoBehaviour
. Esto es lo que significa : MonoBehaviour
.
Cuando una clase hereda
de otra, contendrá todas las propiedades y métodos definidos en la original. Por tanto, nuestra clase Player
contendrá todas las propiedades y métodos definidos en MonoBehaviour
, aunque no se vean en nuestro código, más las propiedades y métodos que definamos nosotros, por eso se dice que extiende a MonoBehaviour
.
Esto significa que podemos leer y modificar los valores de las propiedades y llamar a las funciones que están definidas en MonoBehaviour
. Nuestra clase contiene una copia de ellas.
Todas estas propiedades y métodos de MonoBehaviour
están descritas en la página correspondiente de la Scripting API de Unity.
En la parte derecha de la página tienes un menú expansible con todos los espacios de nombres. Puedes expandir y colapsar secciones clickando en los espacios de nombres:
Si sabes en que espacio de nombres o paquete está la clase que necesitas consultar puedes utilizar este menú para buscar primero el espacio de nombres y luego hacer click en la entrada Classes que contiene todas las clases de ese espacio y que está debajo de todos los sub-espacios de nombres que contiene. Por ejemplo la clase MonoBehaviour
está en el espacio UnityEngine
así que expando ese espacio de nombres y hago scroll hacia abajo hasta encontrar la entrada Classes. La expando y busco MonoBehaviour
(las clases están ordenadas alfabéticamente).
Haciendo click sobre ella, aparecerá en la parte de la derecha la referencia de todas las propiedades y métodos de dicha clase.
Como ves esta no es una forma muy cómoda de usar la ayuda, pero está muy bien que lo hagas de vez en cuando para que veas la enorme cantidad de clases que hay en el motor de Unity y por qué es necesario que estén organizadas en varios paquetes o espacios de nombres.
En cuallquier caso, no está de más ojear las clases que nos llamen la atención. Conocer bien la API de Unity te ayudará a resolver los problemas que tengas entre manos.
También puedes utilizar el panel de búsqueda en la parte superior derecha de la página.
Las dos formas anteriores son las únicas cuando estás consultando la ayuda off-line . Puedes consultar esta página aunque no tengas conexión a internet desde el panel de ayuda de Unity: Help -> Scripting Reference.
Pero cuando tengas conexión a internet la forma más rápida de encontrar cualquier clase o propiedad es usando google. Escribe el nombre de la clase, propiedad o método que quieres consultar, seguido de Unity, y google te mostrará la página de referencia correspondiente entre los primeros resultados de la búsqueda (normalmente el primero).
Es desafortunado, pero los ingenieros de Unity decidieron llamar a propiedades y métodos de otra forma al escribir la documentación.
A continuación os explico a que equivalen los nombres que ellos les ponen a los miembros de una clase, en la jerga estándar que se utiliza para todos los lenguajes de programación.
Cuando consultes la referencia de Unity, verás que las propiedades y métodos de cada clase están divididas en varias categorías.
-
Variables: Son propiedades públicas de la clase.
-
Public Functions: Son los métodos públicos de la clase
-
Static Variables: Son propiedades estáticas públicas de la clase.
-
Static Functions: Son métodos estáticos públicos de la clase.
-
Messages: Son lo que nosotros llamamos funciones evento. Cada una está asociada con un evento concreto que detecta el motor de Unity. Cuando el evento ocurra, se ejecutará la función del mismo nombre si esta existe en una clase que herede de la que se describe. En realidad son métodos privados de la clase, que el motor busca y ejecuta si existen y cuando se produce el evento. Ejemplos:
Start()
,Update()
,OnCollisionEnter()
, etc. en la claseMonoBehaviour
. -
Inherited Members: Son miembros de la clase (variables o funciones) que han sido heredados de otra clase. Dentro de esta sección se vuelven utilizar las categorías anteriores (Variables, Public Functions, Static Variables y Static Functions). A efectos prácticos se pueden usar exactamente igual que los anteriores y de hecho en esta sección suelen estar algunos de los que más se utilizan, así que no te la saltes cuando estés buscando la propiedad o método apropiado para la tarea que estés intentando realizar.
-
Operators Aquí se encuentran descritos los operadores para los que se pueden utilizar instancias de esta clase como operandos, y como usan.
Importante: Fíjate en que dentro de cada una de estas categorías se encuentran los miembros de la clase correspondiente, y una descripción breve de los mismos. Pero el nombre es un enlace a una página con una descripción más detallada y normalmente algún ejemplo de uso. No dejes de hacer click en ellos.
Dicho mal y pronto, los miembros normales estarán presentes en todos los objetos creados a partir de una clase. Es decir, la propiedad this.gameObject
, por ejemplo, existirá en todos los componentes creados a partir de un mismo script, y en cada uno de ellos podrá tener un valor diferente.
Si hablamos de métodos, los normales también están presentes en cada una de las instancias de la clase. Por ejemplo, si queremos obtener el componente Collider del gameObject al que tenemos pegado nuestro script, usamos this.GetComponent<Collider>()
. Cada instancia de nuestra clase, buscará su gameObject padre, y dentro de el, el componente collider que halla, y en cada caso esta función devolverá un collider diferente.
Por eso escribimos siempre delante de estos miembros la variable que contiene la instancia a la que nos referimos. this
es la variable que contiene la instancia dentro de la que estamos. Más adelante veremos que podemos usar otras instancias también para obtener sus propiedades y llamar a sus métodos.
Los miembros estáticos son muy distintos. No están asociados a ninguna de las instancias de la clase. Son globales. Por ejemplo Instantiate()
es un método estático que sirve para crear un clon de un gameObject. Si intentas escribir this.Instantiate()
verás que el compilador te da un error. Esto ocurre porque éste método no está en ninguna instancia de la clase, es global.
Si queremos seguir el criterio de poner delante que cualquier miembro quien es su dueño, en este caso deberíamos escribir MonoBehaviour.Instantiate(...)
(*).
Así, siempre que escribamos una propiedad o una llamada a un método normal pondremos delante quién es su propietario:
GameObject myGO = this.gameObject; // this es una instancia de nuestra clase
Collider myCol = this.GetComponent<Collider>();
myCol.isTrigger = true; // myCol es una instancia de Collider.
Mientras que cuando usemos propiedades estáticas, escribiremos el nombre de la clase en la que están definidas(*).
Vector3 origin = Vector3.zero; // zero es una propiedad estática de Vector3
//...
GameObject newEnemy = MonoBehaviour.Instantiate(enemyPrefab);
(*) Instantiate()
está originalmente definido en la clase Object
de Unity, y en rigor habría que escribir Object.Instantiate()
. Pero como MonoBehaviour
la hereda (como muestra su página en la referencia de Unityy), podemos escribir también MonoBevaiour.Instantiate()