La parte de “acción” de la programación proviene de “llamar” (también conocido como “invocar”) algo llamado “método” (también conocido como “función”). En esta lección aprenderemos cómo definir y llamar a nuestros propios métodos, y luego revisaremos algunos más que son especiales para Unity. Finalmente, crearemos nuestra propia demo de “Magic 8 Ball” y explicaremos cómo vincular un método con el clic de un botón y generar el resultado de una etiqueta.
Declaraciones de métodos
Un método requiere al menos tres cosas, pero generalmente tiene cuatro:
- un tipo de datos de retorno
- un nombre de identificador
- un conjunto de parámetros
- un cuerpo (opcional si también marca el método como “abstracto”, “externo” o “parcial”, pero esas son características avanzadas para más adelante).
Aquí están algunas muestras:
private void MetodoQueRealizaAlgo()
{
Debug.Log("Hola Mundo!");
}
Este método se declara con un tipo de devolución de “vacío”, que es un caso especial y significa que no devuelve nada. El nombre del identificador es “MetodoQueRealizaAlgo” y el conjunto de parámetros está vacío (hay paréntesis sin nada dentro). El “cuerpo” del método es todo, desde el corchete abierto hasta el corchete de cierre “{” y “}”. Puede colocar “declaraciones” dentro de un cuerpo de método como he hecho aquí. Cuando se llame a nuestro método, veremos el mensaje “Hola Mundo!” impreso en la consola.
public bool IsRegistrado (string myID) {
return string.Equals(myID, "Moon");
}
Este método de ejemplo comienza con la palabra clave “public”, que puede recordar al usar las variables en la lección anterior. Al igual que las variables, los métodos predeterminados son “privados” a menos que especifique lo contrario. Al hacer público este método, otras clases pueden “invocarlo”. Luego vemos un tipo de retorno de “bool” (verdadero o falso). Tenga en cuenta que a menos que el tipo de devolución de su método sea “vacío” debe tener una declaración dentro del método que realmente “devuelva” un valor del tipo que indicó, o el compilador se quejará , “no todas las rutas de códigos devuelven un valor” . Por lo general, esta será la última línea del método, ya que las instrucciones posteriores al “retorno” no se podrán ejecutar. El identificador es “IsRegistrado” y tomamos un único parámetro llamado “myID” que debe ser un tipo de “string”.
private int Multiplicar (int a, int b) {
return a * b;
}
Marqué el último método de ejemplo “privado”, que es innecesario ya que es privado de forma predeterminada, pero a veces es posible que desee volver a repetir sus intenciones a otros programadores. Este método devolverá un “int” (un valor numérico que usa números enteros). El identificador es “Multiplicar” y toma dos parámetros. Tenga en cuenta que cada parámetro debe especificar su propio tipo de datos, nombre de identificador y múltiples parámetros están separados por comas.
Invocaciones de método
Para “invocar” su método, utiliza una declaración que hace referencia al identificador del método seguido de los parámetros necesarios, y luego a un punto y coma. Tenga en cuenta que no necesita volver a especificar el tipo o el nombre del parámetro, y puede pasar cualquier valor o variable existente, siempre que el tipo de datos coincida.
En un minuto mostraré el código que llama a cada uno de nuestros métodos de demostración, pero antes de eso, agreguemos algunas variables a nuestra clase para hacerlo más interesante.
public string test;
public int value1;
public int value2;
Las declaraciones que escribimos que llaman a nuestros métodos deben ser “ejecutadas” ellas mismas, y la manera más fácil de hacerlo es conectarnos a un método que Unity que llamará por nosotros. Agregue el siguiente código en el método de Start:
void Start ()
{
MetodoQueRealizaAlgo();
if (IsRegistrado(test)) {
Debug.Log("Registrado.");
} else {
Debug.Log("No Registrado.");
}
int value = Multiplicar(value1, value2);
Debug.Log("Resultado: " + value);
}
La primera afirmación que hemos hecho “llama” a nuestro primer método de ejemplo “MetodoQueRealizaAlgo”. Es muy simple porque no acepta ni devuelve ningún valor.
Luego tenemos algo llamado “instrucción if” que nos permite ramificar y ejecutar código selectivamente. Lo que aparece dentro del paréntesis de apertura y cierre se evalúa como verdadero o falso y esa evaluación determina qué camino seguir. Debido a que nuestro método arroja un valor verdadero o falso, podemos simplemente invocarlo en su lugar. Si el valor que devuelve nuestro método “IsRegistrado” es “verdadero”, entonces veremos el mensaje “Registrado” impreso en la consola. De lo contrario, la condición “else” se hace cargo y veremos el mensaje “No registrado” impreso en su lugar. Al igual que un método, las instrucciones de código que se ejecutan selectivamente están envueltas por un corchete de abrir y cerrar.
Debemos pasar una cadena como parámetro cuando invocamos “IsRegistrado”, pero no nos confundamos por el nombre del parámetro en nuestra declaración de método y el nombre de lo que pasamos en nuestra declaración: los nombres no tienen que coincidir. De hecho, el valor ni siquiera tiene que ser nombrado. Podría haber pasado un valor literal como “Moon” (tenga en cuenta que habría incluido las comillas en el código). El nombre en la declaración del parámetro se usa en la implementación del método (las declaraciones que aparecen dentro del método), pero de lo contrario no importa. Lo que sí importa es que pasemos “algo” del tipo de datos correcto. Si accidentalmente pasa el tipo de datos incorrecto, el compilador generará un error, “La mejor coincidencia de método sobrecargado para ‘CLASS.METHOD (ARG)’ tiene algunos argumentos inválidos”. En este ejemplo, usamos la variable de cadena llamada “test” que definimos anteriormente en nuestra clase.
El método “IsRegistrado” se marcó como público, lo que no hace diferencia en el ejemplo presentado aquí. Una clase puede llamar a cualquiera de sus métodos independientemente de si el método está marcado como público, privado o protegido. Sin embargo, si otra clase tuviera una referencia a una instancia de esta clase, podríamos “llamar” cualquier método público que contenga a través de la notación de puntos con una declaración como la siguiente:
bool resultado = instance.IsRegistrado("Moon");
Finalmente llamamos al método “Multiplicar” pasando dos variables separadas por comas del tipo correcto, en este caso nuestras variables “value1” y “value2”. El valor devuelto de un método se puede asignar a una variable y volver a utilizarlo más tarde, cuando imprimimos un mensaje que nos dice el resultado de la multiplicación.
Crea una nueva escena y adjunta tu guion a algo en la escena (la cámara o un objeto de juego vacío está bien). Use el inspector para asignar valores a las variables y luego ejecutar la escena. Para ver el resultado del ejemplo, asegúrese de mirar en la ventana de la consola (desde la barra de menú, seleccione “Windows -> Console”).
Métodos MonoBehaviour
Los dos métodos más comunes para familiarizarse son los dos incluidos en la plantilla (“Start” y “Update”). Sin embargo, hay muchos más métodos de plantilla en los que puede conectarse. Los siguientes son algunos de los que uso con más frecuencia.
“Awake” se llama inmediatamente después de la instanciación de un objeto. Es la primera llamada a método con la que puede conectarse, y puede ser una buena ubicación para “inicialización” (esto puede incluir obtener referencias a otros componentes o crear instancias de prefabricados, etc.) aunque en otras ocasiones podría necesitar esperar hasta " Start “para asegurarse de que todo esté activo y configurado correctamente. Tenga en cuenta que tanto Awake como Start solo se llamarán una vez en la vida de un objeto.
“OnEnable” se llama despues. A menudo uso OnEnable para registrar oyentes de eventos y OnDisable para eliminarlos. Una diferencia clave entre este método y Awake o Start es que se puede invocar varias veces, cada vez que cambia el estado “habilitado” del objeto, por lo que solo tiene sentido ir a ciertos tipos de código de inicialización.
Se llamará a “Start” antes del primer frame del método de “Update”(después de que todos los objetos hayan ejecutado sus métodos Awake y OnEnable) siempre que el objeto en el que está activado esté habilitado. Al igual que el método “Awake”, puede ser un buen lugar para inicializar tus objetos.
“Update” se llama una vez por frame, en un intervalo de tiempo variable, y proporciona un manejo conveniente para el “bucle del juego”. “FixedUpdate” es similar pero se ejecuta en un intervalo de tiempo fijo y se usa para interactuar con Física. Se llama a “LateUpdate” después de que la Actualización haya finalizado y proporciona una opción para que tenga lógica en respuesta a otros cambios.
Se llama a “OnDestroy” cuando eliminas un GameObject de la escena. Solo se llama una vez en la vida de un objeto y puede ser un buen lugar para limpiar todo lo que se creó durante la inicialización. Por ejemplo, si creaste una textura o malla, querrás asegurarte de que también se destruyan aquí.
Magic 8 Ball
Crea una nueva escena y agregue un Panel (desde la barra de menú elija GameObject -> UI -> Panel). Luego agregue un objeto de Botón y Texto y agrégalos a ambos al panel. El botón se usará para activar una respuesta de nuestra Bola mágica 8, y el texto es la etiqueta donde se mostrará la respuesta. Crea un nuevo script llamado “Magic” y pega el siguiente código:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class Magic : MonoBehaviour
{
public string[] respuestas;
[SerializeField] Text _label;
public void Pregunta()
{
int index = UnityEngine.Random.Range(0, respuestas.Length);
_label.text = respuestas[index];
}
}
En la línea 7 de este script, hemos declarado un tipo especial de variable que aún no te he mostrado: una matriz o array. Una matriz es una colección de valores del tipo especificado. La declaración de nuestra variable “respuestas” tiene el mismo aspecto que declarar una variable de string normal, excepto que agregamos un corchete de abrir y cerrar después del tipo de datos. Puede hacer que cualquier declaración de variable sea una matriz utilizando este ejemplo. Como nuestra variable es pública, aparecerá en el inspector y llenaremos sus valores allí.
También creamos una variable para mantener una referencia a un componente de texto. Usamos la marca “[SerializeField]” en lugar de “public” porque necesitamos asignar la referencia en el inspector, pero ningún otro script “necesita saber” sobre esta etiqueta o su uso, es algo “interno” para la implementación de nuestro script y podría cambiar fácilmente en cualquier momento.
En la línea 10, definimos un método que usaremos como un “detector de eventos”, un método que se invoca automáticamente en función de los eventos activados. En este caso, nuestro “evento” es presionar un botón de UI. Tenga en cuenta que nuestro método debe ser público para poder conectarlo al botón a través del inspector.
Nuestro método tiene dos declaraciones. La primera (línea 12) crea una variable temporal llamada índice, a la que asignamos un número aleatorio. Generamos nuestro número aleatorio utilizando el método “Range”, que nos permite especificar un valor mínimo (incluido) y máximo (exclusivo) para producir el resultado. Si nuestra matriz de respuestas tuviera 3 strings, entonces generaríamos 0, 1 o 2 de este método, porque el valor que especificamos para “min” es 0 y el valor que especificamos para “max” es dinámico basado en la cantidad de respuestas en la matriz.
La siguiente declaración (línea 13) asigna a la variable de texto de nuestra etiqueta una de las respuestas de nuestra matriz. Se accede a los valores individuales dentro de la matriz mediante “índice” (un valor numérico dentro de corchetes). Tenga en cuenta que las matrices están basadas en cero, lo que significa que el primer elemento de la matriz se encuentra en el índice 0.
Regresa a Unity y adjunta el script a algo de la escena. Tenga en cuenta que realmente no importa dónde lo conecte, pero un objeto de nivel raíz como el “Canvas” o un objeto de juego “Controlador” especialmente creado (solo un GameObject vacío) son candidatos bastante buenos que alguien podría esperar usar.
Asigne la referencia de la etiqueta del script (tenga en cuenta que aparecerá como “Texto” en el inspector aunque usemos “texto label” en el código) arrastrando y soltando el objeto Texto de la escena en el campo en el inspector de nuestro guion.
Expanda el campo “Respuestas” haciendo clic en la flecha y establezca el tamaño para contener tantas respuestas como desee (debe ser al menos una o la demostración generará un error, porque mi código de muestra no muestra errores). Agregue algunas respuestas como: “Sí Definitivamente”, “No es una oportunidad” y “Quizás” a la matriz.
Seleccione el botón en el panel Jerarquía. Ahora mira la parte inferior del componente “Button” en el inspector y verás un grupo “OnClick” que está actualmente vacío. Haga clic en “+” en la parte inferior de ese grupo para agregar un “detector de eventos”. Arrastra cualquier objeto que tenga tu script Mágico en el nuevo campo de objeto que apareció. A la derecha del campo de objeto hay un selector de función, actualmente dice “Sin función”. Úselo para seleccionar “Magic -> Pregunta()”.
Ahora todo está configurado. Ejecuta la escena. Haga su pregunta y haga clic para obtener una respuesta, que se elegirá al azar y se mostrará en nuestro Texto.