Si nunca antes has creado un script, no te preocupes, no es exactamente ciencia de cohetes. Aprender a programar es como aprender un nuevo idioma, pero estás “hablando” con la maquina. Al igual que un lenguaje humano se puede dividir en oraciones que consisten en un sustantivo y un verbo, los lenguajes de programación se pueden dividir en variables (el sustantivo) y métodos (el verbo) que a menudo se combinan en enunciados (la oración). Aprender a programar simplemente requiere un poco de esfuerzo para aprender el vocabulario y luego juntarlo de una manera lógica.
El script que crearemos contendrá el código al que nos referimos como una “clase”. Una clase a menudo se relaciona conceptualmente con un plano desde el que puede crear objetos. En Unreal, usarás tu clase para crear “Actores” que se conectan a “Objectos” de forma muy similar a como puedes agregar un colisionador de física o un componente de audio. Al escribir sus propios scripts, puede tener una funcionalidad completamente nueva y personalizada de su propio diseño.
C++ es un lenguaje de programación orientado a objetos que toma la base del lenguaje C.
Es un lenguaje de programación diseñado a mediados de los años 80 por Bjarne Stroustrup. La intención de su creación fue el extender al exitoso lenguaje de programación C con mecanismos que permitieran la manipulación de objetos. En ese sentido, desde el punto de vista de los lenguajes orientados a objetos, el C++ es un lenguaje híbrido. Posteriormente se añadieron facilidades de programación genérica, que se sumó a los otros dos paradigmas que ya estaban admitidos (programación estructurada y la programación orientada a objetos). Por esto se suele decir que el C++ es un lenguaje de programación multiparadigma.
Aqui es donde se unen C++ y Unreal para videojuegos.
En el panel Content Browser de Unreal, seleccione el botón “Add New”, desde el cual tiene la opción “New C++ Class”. Alternativamente, también puede click derecho en Content Browser, “New C++ Class”, pero de todos modos tendrá que volver al panel del proyecto para nombrar y abrir el nuevo archivo. De forma predeterminada, tendrá que elegir un tipo de clase, en este caso elegiremos Actor. Por ahora solo escribe “Demo” para el nombre de nuestro script y después el botón verde “Create Class”.
El nombre de archivo que escriba para su script es importante por una variedad de razones:
- El nombre del archivo se usará automáticamente como el nombre de la clase en el código de plantilla que crea automáticamente.
- Hay algunas reglas sobre qué nombres son legales para usar en una clase:
- Debe comenzar con una letra y debe consistir solo en caracteres alfanuméricos. Si intentó ingresar “1Bunny”, obtendrá un error.
- No puede soportar espacios. Si trataste de ingresar un nombre con un espacio, como “Mi clase”, Unreal intenta arreglarlo por ti (pero solo a medias) y crea el código de plantilla con un nombre de clase de “Mi Clase” aunque abandone el espacio en el nombre del archivo. Luego, cada vez que intente agregar el script a un objeto, Unreal se quejará de usted: " No se puede agregar el script. No se puede agregar el componente ‘ScriptName’ porque no existe. Verifique si el nombre del archivo y el nombre de la clase coinciden.
- Los nombres de tus clases deben ser únicos: no puedes tener dos clases llamadas “Boogers” sin importar lo gracioso que pienses que sería. De nuevo, Unreal intentará solucionar este problema automáticamente y enumerará su nombre de archivo y clase (agregue un número al final) para que sea único.
- Si nombra una clase con el mismo nombre que algo que Unreal ya ha tomado, como “AActor”, recibirá una advertencia, “Script ‘AActor’ tiene el mismo nombre que el componente incorporado de Unreal.
- Los programadores pueden ser muy selectivos y tienen pautas para casi todo, incluso los nombres que usa e incluso el caso de las letras con las que escribe. Un buen nombre de clase será un sustantivo o frase nominal y utilizará “PascalCasing”, donde la primera letra de cada palabra es mayúscula y todas las demás letras son minúsculas. Tenga en cuenta que estas pautas no son obligatorias, pero son una buena práctica. Lea más sobre convenciones y pautas de nombres en este post que escribir sobre buenas prácticas.
Ahora que hemos creado un script, podemos hacer doble clic para abrirlo. Visual Studio debe abrirse como su editor predeterminado (si aún no ha instalado ningún otro editor de código), y es el que le recomiendo que use para seguir. Con Visual Studio abierto, debería haber cargado automáticamente su script, y debería ver algo como lo siguiente:
// Fill out your copyright notice in the Description page of Project Settings.
#include "Demo.h"
// Sets default values
ADemo::ADemo()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ADemo::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ADemo::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Demo.generated.h"
UCLASS()
class LEARNCPPUNREAL_API ADemo : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADemo();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
Las primeras dos líneas de nuestro script se refieren a algo llamado “include”. Volviendo a nuestra analogía de que un lenguaje de programación es como un lenguaje humano, puedo decir que las diferentes palabras significan cosas diferentes según el idioma, y algunas veces incluso las palabras dentro del mismo idioma pueden tener diferentes significados dependiendo del contexto. Estas son librerías que contienen funcionalidad para que nosotros podamos usarlas dentro de nuestro script.
Como vemos, tenemos dos archivos, Demo.cpp y Demo.h, esto viene de C++, ya que nuestro archivo .cpp sera el destinado para nuestra funcionalidad, mientras que nuestro archivo .h sera destinado para la declaración de nuestra funcionalidad.
El archivo .h, tiene los métodos virtuales que en el archivo .cpp podemos usar.
Como un principiante, ocasionalmente, puede seguir con un ejemplo que muestra el código sin mostrar que requería una biblioteca (lo hago en varias de mis entradas). Luego, cuando escribe el ejemplo, se encuentra con un error feo. Podemos simular uno ahora, eliminando los includes de nuestro script. Guarde el archivo e intente construir la solución. El editor de código debe mostrar una línea roja en nuestra definición de clase. Para resolverlo vuelve a Visual Studio a insertar la línea que necesitamos y ahora debería poder construir el script nuevamente sin problemas.
Después de las líneas del include, hay una línea vacía. Las líneas vacías y otros “espacios en blanco”, como las pestañas y los espacios adicionales, etc. no significan nada para el código en sí y solo sirven para la legibilidad humana.
La siguiente línea es la declaración de nuestra clase. Tiene varias palabras clave:
- Class : así es como sé que mi guion es una “clase”. Hay varios tipos de cosas que se pueden definir, algunas de las cuales incluyen: struct, enum e interface, pero nuevamente, esos son temas más avanzados y pueden omitirse por el momento.
- LEARNCPPUNREAL_API : El nombre del proyecto actual.
- ADemo : este es el nombre de la clase y también debe ser del mismo nombre que el archivo que creamos. Al igual que puede agregar componentes a Objetos como colisionadores o luces, ahora podrá agregar un componente llamado “Demo” que eventualmente hará algo … (pero aún no hemos implementado nada)
- Public AActor : tenga en cuenta que esta palabra está separada por dos puntos. Significa que nuestro script hereda de otra clase (con ese nombre). La herencia es otro tema avanzado, pero por ahora es suficiente saber que tiene acceso a un montón de funcionalidades debido a eso.
La línea de declaración de clase termina con un corchete abierto “{”. Habrá un corchete de cierre “}” en la última línea del script. Todo lo que está entre esos dos corchetes son los contenidos de nuestra clase, y en su mayor parte consistirá en las declaraciones e implementaciones de variables y métodos.
En las línea 1, verá una barra diagonal doble, “//”. Esto indica algo llamado “comentario”. Al igual que el espacio en blanco, un comentario es algo que existe para ayudar a la lectura, no el código en sí. Cualquier cosa que siga una doble barra, hasta llegar a la siguiente línea nueva, es parte del comentario. La gente usa comentarios para explicar qué se supone que debe hacer el código y para dar pistas sobre cómo se debe usar. Si necesita un comentario muy largo, puede usar “/” para comenzar y “/” para finalizar un comentario. Cualquier cosa intermedia se considerará parte del comentario, incluso si abarca múltiples líneas nuevas.
- Puede alternar las líneas de un script para que sea un comentario, hacer clic con el botón derecho y seleccionar “Alternar los comentarios de línea”. A veces hago esto cuando tengo un “error” complicado (un error en mi código o lógica) y quiero aislar partes de mi código para que entiendan qué está pasando. Puedo resaltar grandes secciones de código y desactivarlo, por lo que es un comentario. Cuando esté listo, puedo volver a encenderlo con el mismo comando.
El código de la plantilla que se generó para nosotros contiene dos métodos, uno llamado “BeginPlay” (línea 20) y el otro se llama “Tick” (línea 24). En general, puede nombrar un método como quiera, aunque hay algunas reglas y convenciones, al igual que hay para nombrar la clase. Sin embargo, estos dos métodos son especiales y Unreal los “llamará” automáticamente. Esta funcionalidad se obtiene porque “heredamos” de “AActor” en nuestra definición de clase. Consulte este enlace para obtener más información sobre lo que puede hacer un AActor.
Todos los métodos tienen algo llamado firma que incluye tres cosas:
- Un tipo de devolución
- El nombre del método
- Un conjunto de parámetros
Los dos métodos definidos en nuestro script tienen un tipo de retorno de “void” que significa que no devuelve un valor, y tienen un conjunto de parámetros vacíos, porque no hay nada entre los paréntesis de apertura y cierre que siguen al nombre del método. Voy a profundizar en la explicación de las variaciones de estas firmas en una lección futura. Cada método tiene sus propios corchetes abiertos y cerrados “{}” al igual que la clase. Cualquier “declaración” de código entre esos dos corchetes se realizará siempre que el método sea “llamado”. Actualmente nuestros métodos no tienen ninguna declaración dentro de ellos. Esto significa que a pesar de que nuestros métodos serán llamados, nada sucederá.
Una declaración es a menudo la combinación de un método y una variable, y siempre termina en un punto y coma, al igual que nuestras oraciones escritas a menudo terminan con una marca como un punto. Para nuestro primer ejemplo, simplemente hagamos que la computadora nos responda. Entre los paréntesis del método de Tick, agregue la siguiente línea:
void ADemo::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UE_LOG(LogTemp, Warning, TEXT("Mostrando por consola !!"));
}
- Debe tener mucho cuidado al escribir los ejemplos (o copiarlos y pegarlos) exactamente como se presentan o es probable que genere errores en su código. La ortografía errónea de una variable o método, el uso incorrecto de una letra para una llamada u olvidar el punto y coma al final de la línea son errores comunes entre los principiantes.
Guarde el script, luego regrese a Unreal y dale al botón Compile. Cree una nueva escena y arrastre el script “Demo” a la escena.
Reproduzca la escena y se imprimirá un mensaje en la ventana de la Output log. Tenga en cuenta que si la ventana de la Output log no está abierta, puede abrirla desde la barra de menú “Windows-> Developer Tools-> Output log”. También verá el último mensaje de la consola en la parte inferior de la ventana de Unreal. El mensaje que se muestra es “Mostrando por consola !!”.
¿Entonces qué pasó? Unreal llamó al método “Tick” de nuestro script cuando nuestro script se terminó de cargar. A su vez llamamos a un macro llamado “UE_LOG” en una clase llamada “ADemo” y pasamos un parámetro de log, uno de tipo de log y un mensaje string. En este ejemplo, el mensaje se crea dinámicamente.
Reproduzca la escena de nuevo y la ventana de la consola se llenará rápidamente con mensajes, y cada uno mostrará una hora diferente pero actual. Esto se debe a que Unreal llama automáticamente el método de “Tick” una vez por cada fotograma que se reproduce (esto puede ser de 30 a 60 veces por segundo o más).