Si yo fuera un modelo de datos de una maquina, habría variables que me describirían incluyendo una para hacer referencia a mi nombre (un valor que no ha cambiado) y mi edad (un valor que cambia cada año). Algunas variables solo pueden ser determinadas por mí, como el nombre de mi película favorita, y otras pueden ser controladas total o parcialmente por fuentes externas, como mi estado civil. Todos estos tipos de relaciones se pueden modelar en código cuando conoces el vocabulario correcto. En esta lección, crearemos una clase que implemente el ejemplo que acabo de proporcionar.
Modelando un humano
Para comenzar, crea una nueva escena. Vamos a agregar una nueva clase c++ dándole al botón de “Add New” -> New C++ Class -> Actor -> Nombre: Humano. Cuando se cree la clase, le daremos doble click para que se nos inicie en visual studio.
Ahora nuestro archivo Humano.h lo dejaremos asi:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Humano.generated.h"
UCLASS()
class LEARNCPPUNREAL_API AHumano : public AActor
{
GENERATED_BODY()
};
y nuestro archivo Humano.cpp:
#include "Humano.h"
Esto es lo mas limpio que podemos dejar las clases. Ahora como en la anterior sección, vamos a implementar el método BeginPlay() junto con un Debug.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Humano.generated.h"
UCLASS()
class LEARNCPPUNREAL_API AHumano : public AActor
{
GENERATED_BODY()
public:
FString name = "Moon";
protected:
virtual void BeginPlay() override;
};
#include "Humano.h"
void AHumano::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("Hola, mi nombre es %s"), *name);
}
Antes de explicarlo, me gustaría que volvieras al editor y clicaras el botón compile. Esto realizara un procesamiento para ver que archivos han cambiado y actualizarlos en el editor, para que los cambios se vean reflejados cuando reproduzcamos la solución. Cada vez que cambies algo en Visual Studio, tienes que compilar.
Después solo tenéis que arrastras la clase Humano al escenario y veréis como os sale el mensaje por consola.
Explicare esta parte, empezando por el .h, como se ve, en el bloque public he creado una variables FString con nombre name y valor Moon.
Lo que hemos hecho es “leer” o “obtener” el valor almacenado por una variable llamada “name”, anexarlo a la cadena de texto y pasar todo el mensaje como un parámetro al método que imprimió el mensaje a la consola.
Para “escribir” o “establecer” una variable, usamos algo llamado operador de asignación. Para confundirte, los programadores de hace mucho tiempo decidieron que este operador se vería como el signo igual (y para comprobar realmente la igualdad, decidieron usar DOS signos iguales - suspiro). Entonces, para “escribir” o “establecer” una variable, puede usar una línea de código como la siguiente:
name = "Moon";
Si tuviera que poner esa línea de código en el método de BeginPlay sobre la línea que imprime el mensaje “Hola”, cuando ejecute la escena, tendrá dos personas que lo recibirán con el mensaje “Hola, mi nombre es Moon”. Mientras que la escena continúe, Moon será su nombre, como puede verificar en la consola. Sin embargo, cuando detenga la escena, los nombres volverán a los valores que tenían antes de presionar play (en mi caso, Moon).
Campos
Nuestro humano no tiene una variable por edad, así que a continuación le mostraré cómo “declarar” su propia variable llamada “campo”. Como mínimo, todas las variables deben declararse con dos cosas, un “Tipo de datos” y un “Nombre” mediante el cual usted “identifica” la variable. Agregue la siguiente línea a su script, dentro de la clase (entre los corchetes), pero fuera de los métodos. Por convención, la mayoría de las variables de nivel de clase aparecen en la parte superior de la clase.
public:
FString name = "Moon";
int32 edad = 30;
Hay muchos tipos de datos que puede elegir al declarar sus variables (consulte la lista completa aquí: https://docs.unrealengine.com/en-us/Programming/Development/CodingStandard) . Los más comunes que querrás incluir son:
- bool - este es un tipo de valor que por defecto es falso, y solo puede contener “falso” o “verdadero”
- int32 - este es un tipo de valor que por defecto es 0, y puede contener números enteros, por ejemplo: 42
- float: este es un tipo de valor que por defecto es 0 y puede contener números con decimales, por ejemplo: 3.14159f
- FString - un tipo especial que tiene como valor predeterminado null (nothing), y puede contener matrices de caracteres,como: “Hola”
Como es usuario de Unreal, también usará con frecuencia otros tipos de datos, como:
- Objetos: este es un tipo de referencia cuyo valor predeterminado es nulo y puede contener una referencia a un objeto activo.
- FColor: este es un tipo de valor que por defecto es nulo y puede contener un RGB.
- FVector - este es un tipo de valor (una estructura) que por defecto es cero en cada uno de sus subcampos (x, y , z).
Hay varias otras palabras que pueden aparecer en una declaración de variable antes del tipo de datos. “Solo lectura” indica una variable que solo se puede asignar en el momento en que se crea un objeto (por una clase “Constructor” o mientras se inicia la variable). “Const” es similar, pero debe inicializarse solo en la declaración. “Estático” indica una variable que pertenece a la clase misma en lugar de instancias de la clase (por ejemplo, muchas de las variables en la clase “Time” son estáticas).
Al declarar la variable en el nivel raíz de nuestra clase, le estamos dando un “alcance” de nivel de clase. Esto significa que la variable será visible en todas partes dentro de la clase(.cpp y .h), incluso dentro de los métodos dentro de la clase. Tenga en cuenta que también puede declarar variables dentro de un método, pero su alcance será más limitado, y otros métodos o clases no tendrán acceso a esas variables.
Guarde su script y regrese a Unreal. Mira a uno de tus Humanos e intenta establecer la variable de nombre/edad que acabamos de declarar … oye espera, ¿por qué no lo vemos? Las variables tienen algo llamado “visibilidad”. Cuando no se especifica la visibilidad de una variable, se predetermina a “private”, lo que significa que solo su clase sabe que existe. Unreal solo muestra variables que están marcadas como “public” o por “Blueprint”, que es una forma especial de exponer una propiedad al inspector de Unreal sin permitir que otros scripts conozcan la variable. Cualquiera de las siguientes líneas permitirá que su variable aparezca en el inspector:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Humano.generated.h"
UCLASS()
class LEARNCPPUNREAL_API AHumano : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
FString name = "Moon";
UPROPERTY(VisibleAnywhere)
int32 edad = 30;
protected:
virtual void BeginPlay() override;
};
Antes de continuar, vamos a dirigirnos a nuestra clase, le daremos click derecho y crearemos un blueprint basado en ella.
Esto nos creara un nuevo blueprint que tenga de herencia nuestra clase humano. Ahora arrastramos a la escena nuestro BP MyHumano. Dentro del BP veremos en las variables que salen las dos que creamos.
Ahora cualquier cambio que realicemos en el nombre, cambiara el resultado. Por ejemplo colocando dos BP con el nombre de Moon y Andrea, este es el resultado.
Como vemos, podemos editar el valor de nuestra variables desde el inspector por medio de nuestro BP que hereda de la clase Humano, pero cual es la explicación a que no podamos editar nuestra edad. La respuesta es por el tipo de macro que definimos.
- UPROPERTY(EditAnywhere): Es posible editarse.
- UPROPERTY(VisibleAnywhere): Solo es posible verse
Ademas de ese parametro de la macro, podemos definir otro más por si queremos tener acceso a esos valores desde nuestros blueprints. Estos parámetros son:
- UPROPERTY(EditAnywhere, BlueprintReadOnly): Es posible editarse, pero no se tiene acceso desde los BP.
- UPROPERTY(VisibleAnywhere, BlueprintReadWrite): Solo es posible verse, no editarse desde el inspector pero accesible desde BP.