Introducción al desarrollo de video juegos con Unreal Engine 4

Unreal Engine 4, en mi opinión, es uno de los motores de juegos más potente que existe en la actualidad, y el equipo de Epic Games lo ha puesto por completo a disposición de todos bajo una licencia 19 USD mensuales.

Este primer tutorial pretende dar una introducción al UE4. Crearemos la base de nuestro juego, donde tendrás al personaje protagónico caminando por el nivel usando una cámara fija, con controles básicos. Este simple inicio nos permitirá aprender a importar los modelos 3D al proyecto. Crear la clase necesaria para controlar al personaje. Entender la filosofía que sigue el framework de Unreal en su modelo de clases. Una introducción a la programación en Unreal Engine usando C++. La comunicación entre C++ y el Editor. Los mecanismos de animación del personaje y una introducción al Visual Scripting usando el Blueprint Editor.

Obteniendo el Unreal Engine 4

El proceso para obtener el motor es súper simple. Entra en https://www.unrealengine.com/register regístrate y paga los primeros 19 USD, créeme, probablemente estos sean los 19 USD que más alegría te darán en la vida :). Ahora tendrás acceso a lo mismo con lo que trabaja el equipo de Epic Games.

El próximo paso es obtener el motor. Este lo podemos tener de dos formas, directo el ejecutable desde el Launcher que al abrirlo nos dará para bajar la última versión o compilando todo el código fuente … sip, así mismo, por si fuera poco, tenemos acceso ha todo el código fuente del motor.

En el sitio se describen bien los pasos para bajar los fuentes desde https://github.com/EpicGames/UnrealEngine/releases y los pasos para compilarlo así que nos detendremos aquí. De todas formas si tienes algún problema con el proceso puedes dejarme tus comentarios.

Requisitos antes de comenzar

Es válido aclarar en este momento que este y los próximos tutoriales asumen que tienes un dominio AVANZADO de C++ y del desarrollo de juegos.

Modelo 3D del personaje protagónico y sus animaciones

Lo primero que necesitamos para comenzar nuestro juego es el modelo 3D del personaje principal con sus animaciones. Todos los modelo 3D que conforman un juego, tanto los personajes como los objetos y las animaciones son creados por los diseñadores y animadores de nuestro equipo, con herramientas de modelado y animación 3D como Maya, 3DsMax o Blender. Al terminar el proceso de modelación y animación en estas herramientas, se exporta el modelo, el esqueleto y las animaciones en formato FBX.

Como en lo personal, el modelado y la animación 3D se me da muy mal :) vamos a partir de los recursos en FBX de uno de los proyectos de ejemplo que viene con el UE4. Esto es exactamente lo que nos daría nuestro equipo de diseño. Puedes bajar los recursos aquí: https://d26ilriwvtzlb.cloudfront.net/a/a7/ThirdPerson_FBX.zip

Descomprime el .zip, de momento solo trabajaremos con HeroTPP.FBX, Walk.FBX y Idle.FBX. Si tienes algún software de modelado 3D, como Maya por ejemplo, puedes importar estos ficheros para que les des un vistazo de cerca.

Archivo Hero.FBX cargado en Maya 2015. Vista del esqueleto.

Archivo Hero.FBX cargado en Maya 2015. Vista del esqueleto.

Archivo Hero.FBX cargado en Maya 2015. Vista del modelo.

Archivo Hero.FBX cargado en Maya 2015. Vista del modelo.

 

Hero.FBX es el modelo 3D de nuestro personaje con su esqueleto para poderlo animar. Idle.FBX y Walk.FBX son las animaciones de reposo y caminar del personaje. En estos dos últimos archivos no se encuentra el modelo ya que no es necesario, para las animaciones solamente necesitamos la información del movimiento de los huesos del esqueleto, por lo que al exportar las animaciones no hay que incluir el modelo.

Creando un nuevo proyecto en Unreal Engine 4

Ya con nuestro modelo 3D y sus animaciones en formato FBX estamos listo para comenzar. Lo primero es crear el proyecto. Crear un nuevo proyecto en Unreal Engine es súper simple. Abrimos el editor y nos muestra una ventana con dos pestañas: Project, que contiene los proyectos existentes previamente creados y New Project, que como es lógico, nos permite crear un nuevo proyecto.

Una de las primeras cosas geniales que encontramos al intentar crear un proyecto nuevo, es que ya el UE4 viene con un grupo de Proyectos “Plantilla” que podemos usar como base de nuestro juego, según el estilo que queramos crear. 3ra Persona, 1ra Persona, Top-Down o Side-Scroller.

Como el objetivo que tiene este primer tutorial, es una introducción al UE4, no vamos a usar ninguna de estas plantillas relativamente avanzadas, vamos a crear nuestro proyecto prácticamente desde cero, usaremos el Template Basic. Selecciona New Project/Basic Code y abajo en el campo nombre escribimos el nombre de nuestro proyecto, en este caso yo usaré UE4Demo. Por último da clic en Create Project.

Ventana para Crear o Abrir un proyecto en Unreal Engine 4

Ventana para Crear o Abrir un proyecto en Unreal Engine 4

Hecho esto se crea automáticamente el proyecto y se abre en el IDE correspondiente según el sistema que usemos. Para Windows es Visual Studio 2013 y para MAC OS es XCode 5.1. Este tutorial es desarrollado en MAC OS, por lo que estoy usando como IDE de programación el XCode. Una vez abierto el XCode con el proyecto, tenemos que compilarlo para poderlo abrir en el Editor. Da clic en la esquina superior izquierda para seleccionar el Scheme UE4DemoEditor – Mac y después Menú Product/Build For/Running.

El proceso de compilación demorará unos segundos. Una vez que termina podemos seleccionar desde el menú del XCode, Product/Run. Esto nos abrirá automáticamente el Editor con nuestro proyecto.

Unreal Engine 4 Editor con nuestro nuevo proyecto acabado de abrir

Unreal Engine 4 Editor con nuestro nuevo proyecto acabado de abrir

UE4 nos crea una escena con algunos objetos agregados a la misma. De momento vamos a dejarlo. Puedes dar clic en el botón Play de la barra Superior (Toolbar) para ver lo que tenemos. Por defecto tendremos el control de la cámara con el mouse y el teclado y podremos desplazarnos por la escena, pero por supuesto, este no es el objetivo, nosotros queremos que entre en este mundo nuestro personaje :)

Importando modelo 3D de nuestro personaje

Ya nuestro equipo de diseño nos entregó el modelo exportado en FBX con su esqueleto y su dos animaciones básicas :), ahora vamos a importarlo en el proyecto. En el Panel de la esquina inferior izquierda del Editor tendemos el Content Browser. En este panel es donde tendremos organizados todos los recursos de nuestro juego. Da clic en el Botón New y selecciona New Folder y dale un nombre a la carpeta, por ejemplo “Character”. Hecho esto tendremos una nueva carpeta en el Content Browser, entra en ella, selecciona Import y busca el FBX del personaje: Hero.FBX (los FBX de las animaciones los vamos a importar más tarde). Recuerda que en este FBX lo que tenemos es el modelo 3D del personaje con su esqueleto. Al dar en OK nos sale la ventana FBX Import de UE4 y ya automáticamente seleccionado Skeletal Mesh.

Ventana FBX Import del Unreal Engine 4

Ventana FBX Import del Unreal Engine 4

Vamos a tomarnos unos minutos para un poco de teoría. Como puedes ver en esta ventana de import se muestran tres tipos de recursos que se pueden importar desde FBX. Static Mesh, Skeletal Mesh y Animation.

Static Mesh: Un Static Mesh es un objeto estático de nuestro juego, por ejemplo una silla, un edificio. O sea, solamente el modelo 3D sin animación, sin esqueleto.

Skeletal Mesh: Un Skeletal Mesh, es exactamente lo que estamos importando ahora, un modelo 3D con un esqueleto asociado para ser animado. O sea, todos los personajes de nuestro juego serían Skeletal Mesh.

Animation: Un Animation, es la información de transformaciones de los huesos de un esqueleto para darle vida a las acciones como caminar, saltar, etc. Lo que tenemos en Idle.FBX y Walk.FBX que importaremos más adelante.

Automáticamente UE4 detecta que lo que estamos importando es un Skeletal Mesh no es necesario cambiar más nada, los parámetros por defecto son suficiente, da clic en el botón Import. En caso de algún warning en el proceso de importación, ignóralo. En próximos tutoriales veremos todo el proceso de Exportar/Importar y el Animation Rigging Toolset que nos da Epic para preparar los modelos y las animaciones y abordaremos en detalles este tema.

Una vez importado el modelo en el Content Browser tendremos 3 nuevos elementos: Hero (SkeletalMesh), Hero_PhysicsAsset (PhysicsAsset) y Hero_Skeleton (Skeleton).

Si haces doble clic en el SkeletalMesh puedes abrir el modelo importado en el Editor Persona de UE4. Persona es el editor de Skeleton, Skeletal Meshes, Animations Blueprints y otros elementos de animación en UE4.

El Skeletal Mesh de nuestro héroe en el Persona Editor

El Skeletal Mesh de nuestro héroe en el Persona Editor

Al abrir el SkeletalMesh en Persona a la izquierda tendremos el Skeleton Tree que es el árbol con todos los huesos que conforman el esqueleto del modelo. En el panel de abajo tenemos el Mesh Details. Este panel está compuesto por varias secciones, con los Materiales aplicados al modelo (De momento no tenemos ningún material, o mejor dicho, solamente tenemos un material por default que le da esa vista gris opaca a nuestro personaje)

El Hero_PhysicsAsset es el PhysicsAsset que se genera automáticamente al importar el Skeletal Mesh, este asset de momento no lo usaremos, en próximos tutoriales veremos para que es, pero si eres muy curioso dale doble clic, te abrirá el editor que trae UE4 para manipular este tipo de assets. En la esquina superior izquierda tiene un botón que dice Simulate, da clic en él y mira lo que pasa. Eso te dará una noción del objetivo de este recurso generado automáticamente al importar el Skeletal Mesh.

Por último el Hero_Skeleton es solamente el esqueleto del modelo que importamos, pero el esqueleto por separado. Una característica genial de UE4 es que podemos compartir el mismo esqueleto entre distintos modelos 3D que sean relativamente parecidos en su modelo. En vez de tener que importar siempre para cada uno de estos el modelo 3D y el esqueleto, solamente importamos el esqueleto una vez, y podemos asociar distintos modelos a este esqueleto.

Bien, ya tenemos en nuestro proyecto los recursos del personaje principal, vamos ahora a lo que nos gusta, el código :)

Introducción a la programación en Unreal Engine 4

Un proyecto en Unreal Engine 4 está compuesto básicamente de dos grandes piezas que trabajan en conjunto. Los niveles, que es lo que se trabaja en el Editor y el proyecto de programación, que trabajamos en el IDE de programación. Vimos como al crear un nuevo proyecto en UE4 se crean ambas partes. Ahora vamos a trabajar en la segunda parte, la parte del código.

En Unreal Engine 4 se programa en C++, al crear un nuevo proyecto, automáticamente se crea un proyecto en el XCode (o Visual Studio si usas Windows) con las clases básicas para nuestro juego. Abre tu IDE de programación con el proyecto creado. Dentro de la carpeta Source es que se encuentran los fuentes nuestros. Dentro de la carpeta Engine están todos el framework. Tener acceso a esto es genial, porque sirve de mucha ayuda para revisar como están implementadas las clases, o para que es una determinada propiedad, viendo los comentarios puestos por el propio equipo de Epic. Antes de crear nuestra primera clase vamos a comentar rápidamente la filosofía que sigue Unreal Engine en su framework.

En UE4 todos los elementos que aparecen en nuestro juego son Actors (heredan de la clase AActor). Una silla, una mesa, un enemigo o el personaje principal. Los elementos del juego que son controlados, o sea que no son estáticos, que tienen un comportamiento, son Pawns. Hay un tipo especial de Pawn que es el Character. El Character es el Pawn que representa al personaje principal y tiene implementaciones particulares que solo tendrá el Pawn que será controlado por el jugador. Por ejemplo, si en nuestro juego tenemos al personaje principal y a un enemigo. El personaje principal será un Character y el enemigo será un Pawn solamente. Ahora… todos los Pawns son controlados por una clase Controller, para el caso del Character, este es controlado por un PlayerController. El PlayerController es la clase que recibe las entradas del jugador, del ser humano, y mediante ellas controla al personaje en el juego, al Character. Básicamente el PlayerController representa al ser humano, el Character (Tipo especial de Pawn) representa al personaje dentro del juego y es controlado por el PlayerController. Mientras que los otros Pawns pueden ser controlados, por ejemplo, por AIController.

. . . sip :S, bastante enredado, pero poco a poco a medida que te familiarices con Unreal Engine dominarás esta filosofía, la jerarquía de clases y la relación entre ellas.

Volviendo al código, dentro de la carpeta Source tenemos una carpeta con el nombre que le dimos al proyecto, en mi caso UE4Demo y dentro unas pocas clases con las que comenzar nuestro juego.

La primera clase a tener en cuenta es UE4DemoGameMode esta es la clase que define el GameMode de nuestro juego. En Unreal la clase GameMode define las reglas del juego, por ejemplo, las condiciones en las que se gana, las condiciones en las que se pierde etc, además es la encargada de definir el PlayerController, el Pawn por defecto, entre otras muchas cosas. Es el núcleo del juego. Si abrimos el .h veremos que es una clase que hereda de AGameMode y de momento no tiene más nada.

//AUE4DemoGameMode.h
#pragma once

#include "GameFramework/GameMode.h"
#include "UE4DemoGameMode.generated.h"

UCLASS()
class AUE4DemoGameMode : public AGameMode
{
	GENERATED_UCLASS_BODY()
};

Como notarás de seguro, la clase tiene en su declaración dos macros que te llamarán la atención, UCLASS() y GENERATED_UCLASS_BODY

Unreal Engine posee un robusto sistema para el manejo de objetos. La clase base para los objetos en Unreal es UObject. el macro CLASS puede ser usado en clases que derivan de UObject, de esta forma el sistema manejador de UObjects es avisado de la existencia de esta clase.

Al incluir estos macros logramos que la clase a bajo nivel sea tratada por los mecanismos de Unreal como el “Recolector de basura, Serialización, Inicialización automática de las propiedades, Integración automática con el Editor etc”.

Ahora vamos a ver la implementación de nuestro GameMode. Como verás en el UE4DemoGameMode.cpp tendrás solamente la implementación del constructor.

//AUE4DemoGameMode.cpp
#include "UE4Demo.h"
#include "UE4DemoGameMode.h"
#include "UE4DemoPlayerController.h"

AUE4DemoGameMode::AUE4DemoGameMode(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	PlayerControllerClass = AUE4DemoPlayerController::StaticClass();
}

El constructor del GameMode de nuestro juego de momento solamente tiene la inicialización del atributo PlayerControllerClass. PlayerControllerClass es el PlayerController para nuestro juego, o sea, la clase que será la interfaz entre el ser humano y el Character que este controlará. Aquí simplemente es inicializada con una instancia estática de nuestro UE4DemoPlayerController. Por eso es que podemos movernos como un fantasma por todo el nivel cuando corremos el proyecto ahora mismo. Tenemos un PlayerController, pero como no tenemos un Character no tenemos cuerpo dentro del juego.

La otra clase que tenemos ya previamente creada es UE4DemoPlayerController. Esta es la implementación del PlayerController de nuestro juego y como verás está vacía, de momento no necesitamos nada personalizado en ella, todo lo necesario para nuestro PlayerController de momento está en la clase base APlayerController, pero dejamos esta clase por aquí para cuando necesitemos implementar algún comportamiento personalizado.

Bien, basta de teoría, vamos a la practica.

Ya tenemos importado en el Editor los recursos que conforman a nuestro personaje, pues vamos a acabar de hacerlo entrar en escena :)

Creando nuestra primera clase en Unreal Engine

Como lo primero que vamos a hacer es darle vida a nuestro personaje, la clase que vamos a crear es la clase del personaje. Como comentamos anteriormente, el personaje controlado por el jugador es un Pawn, pero es un Pawn especial, es un Character. Por lo que la clase que controle al personaje protagónico de nuestro juego tiene que heredar de Character.

Para agregar una nueva clase al proyecto la forma más cómoda de hacerlo es desde el Editor. Vuelve al Editor y mediante el menú principal selecciona File/Add Code to Project. Tendremos una ventana para seleccionar la clase base de la nueva clase que como dijimos será Character. En esa ventana puedes ver las otras clases bases comunes en Unreal Engine y una pequeña descripción de las mismas. Selecciona Character, da en el botón Next, escribe el nombre para tu clase, por ejemplo, HeroCharacter y finaliza el proceso. Al finalizar el Editor te pregunta si quieres abrir la clase en el IDE, le damos OK y ya veremos ahí nuestra clase HeroCharacter creada. La estructura de momento ya es conocida, una clase C++ normal que hereda de ACharacter y con los macros ya explicados UCLASS() y GENERATED_UCLASS_BODY().

Configurando el Character desde el Blueprint Editor.

Ya tenemos nuestra clase para representar el personaje protagónico de nuestro juego, este es un buen punto para comentar una de las cosas que en lo personal más trabajo me costó adaptarme al entrar en el mundo de Unreal Engine, sobre todo porque llegué a Unreal Engine después de trabajar mucho en el desarrollo de juegos 2D con motores como el Cocos2D. En este caso todo se hace desde código (aunque ya a estas alturas han varios Editores geniales para Cocos2D). En UE4 la filosofía de trabajo es muy distinta, aquí por supuesto que podemos hacerlo todo desde programación pero esto implica que el ritmo de producción generalmente será más lento y propenso a bug. Por este motivo al desarrollar juegos sobre Unreal Engine trabajaremos indistintamente con el Editor o directamente desde el código. Básicamente es decisión de los desarrolladores cuando usar uno u otro.

Para demostrar el engranaje entre el código en C++ y el Editor en Unreal Engine vamos a configurar nuestro Character en los dos lados, esto también nos permitirá demostrar lo genial que quedan comunicados el código C++ y el Editor.

Bien, ya tenemos desde código nuestra clase para representar al Character, vamos ahora a configurar los componentes del Character pero desde el Editor. Abre el Editor y en el Toolbar tenemos el botón Blueprints. Selecciona Blueprints/New Class Blueprint en la parte de abajo de la ventana hay una sección que dice Custom Classes, selecciona ahí y busca la clase que acabamos de crear para nuestro Character, HeroCharacter, y le ponemos un nombre, por ejemplo, HeroCharacterBlueprint y selecciona para que se cree dentro de la carpeta Game/Character. Una vez terminado el proceso se abrirá el Blueprint Editor en el modo Components. Desde aquí podemos configurar todo nuestro Character.

imagen_06

A la izquierda del editor tenemos el panel Components este panel contiene todos los componentes que conforman el Character al seleccionar uno, en el panel de abajo se muestran las propiedades de ese componente. El CharacterMovements como el nombre lo indica es el componente que contiene las propiedades que afectan el movimiento del Character, por ejemplo, aquí tenemos Max Walk Speed que es el máximo de velocidad que toma el personaje al desplazarse, hay muchísimas más propiedades, dale un vistazo a todas por arriba para que tengas una idea de todo lo que se puede configurar en el Character con respecto al movimiento.

El otro componente que tiene un Character es el CapsuleComponent. El CapsuleComponent es usado para la detección de colisiones con el personaje. Es esa capsula transparente que se ve en el Viewport del Editor y es la zona de colisión del personaje.

Por último dentro del CapsuleComponent tenemos un Mesh, que como ya te imaginarás es el Mesh que representa a nuestro personaje. Además hay un ArrowComponent que nos ayuda para saber la dirección del Character.

Bien, el primer paso será acabar de configurar el Mesh de nuestro Character. Selecciona en el panel de Componentes el componente Mesh y en el panel detalles en la sección Mesh tienes la propiedad Skeletal Mesh despliega el combobox que hay aquí y selecciona el único Skeletal Mesh que tenemos en nuestro proyecto que creamos al importar el fbx de nuestro héroe. Al hacer esto en el Viewport se verá el modelo de nuestro héroe. Usa las herramientas de traslación y rotación para colocar el Mesh dentro del CapsuleComponent y mirando en la misma dirección que el Arrow Component. Por último da clic en el botón Save en la esquina superior derecha del Editor.

Mesh del personaje en la posición correcta en el HeroCharacterBlueprint

Mesh del personaje en la posición correcta en el HeroCharacterBlueprint

Hecho esto acabamos de darle un cuerpo a nuestro Character. Vamos a probar. Cierra el Editor del Character y corre el juego a ver que tenemos.

:( … como notarás no hay ningún cambio, seguimos teniendo control gracias al PlayerController por defecto pero no tenemos nuestro personaje ni nada. Bien, el problema es que nos faltaron algunas cosillas.

Primero, asegúrate que tienes configurado bien el GameMode. Da clic en el botón World Settings del Toolbar y asegúrate tener seleccionado en la sección GameMode nuestra clase U4DemoGameMode, debajo de GameMode tendrás los elementos configurados en este GameMode en PlayerControllerClass está nuestro PlayerController (UE4DemoPlayerController) ya que en el constructor de la clase UE4DemoGameMode inicializa esa propiedad, pero como notarás Default Pawn Class dice Default Pawn. Ese es exactamente el problema que tenemos. Creamos nuestro Character y le dimos un cuerpo pero no hemos definido en el GameMode que HeroCharacter es el Character (el Default Pawn Class ) de nuestro juego.

Vamos ha hacer esto desde el código para demostrar nuevamente la comunicación entre los componentes del Editor y el código en C++. Cierra el Editor abre el proyecto C++ y busca la clase UE4DemoGameMode modifica la implementación del constructor para que quede de la siguiente forma.

AUE4DemoGameMode::AUE4DemoGameMode(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	PlayerControllerClass = AUE4DemoPlayerController::StaticClass();
    
    //Obtiene en PlayerPawnBPClass.Object la referencia al HeroCharacterBlueprint creado y configurado desde el Editor
	static ConstructorHelpers::FObjectFinder<UClass> PlayerPawnBPClass(TEXT("Class'/Game/Character/HeroCharacterBlueprint.HeroCharacterBlueprint_C'"));
    
    //Inicializa el atributo DefaultPawnClass con el HeroCharacterBlueprint creado y configurado desde el editor
	if (PlayerPawnBPClass.Object != NULL)
	{
		DefaultPawnClass = PlayerPawnBPClass.Object;
	}
}

Vamos a dar un stop aquí para explicar que acabamos de hacer con estas pocas líneas porque aunque tengas experiencia en C++ de seguro que esta sintaxis te parecerá algo rara. En la primera línea lo que hacemos es buscar y obtener la instancia de la clase HeroCharacter creada en el editor mediante el Blueprint Editor. Creamos una variable del tipo FObjectFinder, FObjectFinder es una estructura parametrizada publica que se encuentra dentro de otra estructura de nombre ConstructorHelpers. FObjectFinder recibe en su constructor la dirección del objeto que vamos a instanciar, si el objeto es encontrado satisfactoriamente su instancia se almacena en la propiedad Object.

Un buen consejo, como tenemos los fuentes del Framework, puedes ver la implementación de todas estas estructuras ConstructorHelpers, FObjectFinder. En XCode basta con dar clic sobre su nombre con la tecla cmd presionada. Esto te llevará a la declaración de la estructura. Tomate unos minutos y dale un vistazo por arriba para que entiendas mejor su funcionamiento. Por último notar que para definirle la ruta a FObjectFinder usamos el Macro TEXT, básicamente todos los strings que escribamos directo en el código lo tendemos que hacer con esto, para que el compilador pueda convertir el string al tipo de dato correcto, en este caso un TCHAR *.

Bien, pues en teoría tenemos en PlayerPawnBPClass.Object la instancia de nuestro Character (PlayerPawnBPClass es el nombre que le dimos a la variable que acabamos de crear de tipo FObjectFinder), lo que queda es inicializar la propiedad DefaultPawnClass con este objeto. La clase GameMode tiene la propiedad DefaultPawnClass que define el Pawn que usará el personaje.

Listo, compila y ejecuta el juego. Al arrancar el juego automáticamente se agrega al Level nuestro personaje. Esto es porque en el Level que nos crea el Unreal Editor por defecto con la plantilla que seleccionamos al crear el proyecto, tiene un Actor de tipo Player Start. Y el GameMode automáticamente busca en el Level si hay una instancia de un Player Start y agrega en esa posición el Character.

Pero que problema tenemos ahora, perdimos el control, ya no podemos desplazarnos por la escena y la cámara está como en los ojos del personaje :(. Bien, vamos a solucionar este asunto configurando temporalmente una cámara estática en nuestro juego.

Configurando una cámara estática desde C++

En el Editor da clic derecho dentro del ViewPort y selecciona del menú desplegable Place Actor/Camera. Usa las herramientas de traslación y transformación para apuntar la cámara en la dirección del Play Start, para que se vea el personaje. Así me quedó a mi:

imagen_08

Ahora vamos a decirle al Unreal que la vista del juego será desde esta cámara. Para esto tenemos que comentar algo de teoría.

Como hablamos anteriormente según la filosofía de Unreal es el PlayerController la interfaz entre el personaje protagónico del juego (el Character) y el ser humano. Por lo que es lógico que lo referente a la vista del juego sea implementado aquí. PlayerController tiene el método SetViewTargetWithBlend este método permite definir en cualquier momento a donde es que está “mirando” la cámara del juego. Lo que vamos a hacer es llamar a este método y decirle que use la cámara que pusimos en el Level como la cámara del juego.

Podemos cambiar la dirección a la que apunta la cámara de nuestro juego en cualquier momento, pero en este caso queremos que desde el inicio sea la dirección a la que apunta la cámara que agregamos al level. Para esto vamos a usar un evento muy usado en Unreal que es el evento BeginPlay. todas las clases que hereden de AActor tienen este método que se llama, como dice su nombre, cuando inicia el juego. Vamos a sobrescribir este método en nuestro PlayerController (que deriva de AActor) para en ese momento cambiar la cámara del juego.

Abre UE4DemoPlayerController.h y abajo del macro GENERATED_UCLASS_BODY() agrega la siguiente línea: virtual void BeginPlay() override; con esto hacemos visible el método BeginPlay en nuestra clase UE4DemoPlayerController para poderlo sobrescribir en el .cpp.

Abre ahora UE4DemoPlayerController.cpp y agrega el siguiente método debajo del contructor. Revisa con detenimiento los comentarios para que entiendas lo que se hace dentro del método.

/** Metodo heredado de la clase AActor se llama automaticamente por el motor cuando comienza el juego. */
void AUE4DemoPlayerController::BeginPlay()
{
    //Llamamos el Begin Play de la clase padre
    Super::BeginPlay();
    
    //Recorremos todos los Actores en el Level mediante el TActorIterator
    //TActorIterator es un iterator parametrizado que nos permite recorrer todos los actores en el level
    for (TActorIterator<ACameraActor> It(GetWorld()); It; ++It)
    {
        //Obtenemos el actor actualmente en el loop. Como solo tenemos un solo ACameraActor en el Level, el iterator solo iterará una vez
        ACameraActor* _mainCamera = *It;
        
        //Configuramos el nuevo punto de vista del juego con la camara.
        //SetViewTargetWithBlend puede recibir más parametros, pero tienen valores por defecto, y de momento no necesitamos modificarlos.
        this->SetViewTargetWithBlend(_mainCamera);
    }
}

Listo !! compila y corre. Ahora verás el juego usando la cámara que agregamos al Level y ya podrás ver nuestro Character agregado a la escena.

Configurando una cámara estática mediante el Blueprint Editor

Bien, quisiera hacer un paréntesis aquí para volver a tocar el tema del Blueprint Editor. Al comenzar en Unreal Engine muchos chocamos con la incógnita: Cómo hago esto? Mediante C+ o mediante el Blueprint. Al final la decisión es de cada cual y a medida que vayas cogiendo soltura en Unreal Engine sabrás al directo si lo que vas a hacer en C++ o en el Blueprint Editor. Quiero aprovechar este momento para demostrar esto. Vamos a hacer lo mismo que acabamos de implementar en C++, o sea, cambiar la cámara del juego, pero ahora sin escribir una línea de código, todo lo haremos mediante el Blueprint Editor.

En el Editor da clic en el botón Blueprint del Toolbar y selecciona Open Level Blueprint esto te abrirá el Blueprint Editor con el archivo Blueprint para el Level completo. Digamos que es en este Blueprint donde implementaremos las cosas generales del nivel.

Siguiendo la lógica que usamos para implementar esto desde C++. Lo primero que hicimos fue implementar el Evento BeginPlay. Pues eso mismo haremos aquí, el Blueprint Editor es un Editor de scripting visual, por lo que en este Editor lo que haremos básicamente es programar pero con gráficos (si si . . . bien complejo de asimilar y entender la primera vez :) ) … aquí podemos agregar variables, eventos del sistema, funciones de clases especificas etc. En fin, todo, o casi todo lo que haces en C++ lo podrás hacer en el Blueprint Editor.

Comenzaremos agregando el Evento Begin Play. Clic derecho en el centro de la pantalla desmarca la opción Context Sensitive y busca Event Begin Play. Acabamos de agregar a nuestro script visual un Nodo que representa al método Begin Play de nuestro juego. Ahora, según nuestra implementación en C++ lo que hicimos dentro del BeginPlay fue obtener la referencia de la cámara que tenemos en el Level y llamar al método de la clase PlayerController SetViewTargetWithBlend pasándole como parámetro la cámara. Pues eso mismo haremos aquí.

Primero, necesitamos una referencia al PlayerController, recuerda que este script es “global” a nivel del Level y la implementación de C++ la hicimos dentro del PlayerController.

Agrega un nuevo Nodo como ya sabes pero ahora será Get Player Controller. Este nodo nos retorna la referencia del Player Controller del juego. Ahora necesitamos llamar al método SetViewTargetWithBlend como mismo hicimos en C++. De nuevo agrega un nuevo Nodo de nombre SetViewTargetWithBlend. Listo, ya tenemos todos los elementos que necesitamos para nuestro algoritmo visual. Pero falta una cosa, conectarlos.

El Nodo Event Begin Play tiene como un puerto que representa la salida. O sea, lo que se va a ejecutar cuando se lance este evento en el juego y si te fijas en el nodo Set View target with Blend tiene un puerto de entrada y de salida. El de entrada es el que nos interesa. Da clic en el puerto del evento Event Begin Play y arrastras la flecha hasta el puerto de entrada de Set View Target with Blend, cuando te muestre una marquita verde suéltalo. Con esto hemos hecho la conexión entre la salida de Event Begin Play y Set View target with Blend. Que quiere decir esto, que cuando se ejecute nuestro juego, se va a disparar el evento BeginPlay y se llamará al método Set View target with Blend. Pero que pasa, SetViewtargetWithBlend vimos que es un método que pertenece al PlayerController, por lo que hay que definirle al nodo Set View Target With Blend quien es el Player Controller. El Nodo Get Player Controller tiene un puerto de salida que dice Return Value y el Nodo Set View Target with Blend tiene un puerto de entrada que dice Target. Conecta estos dos puertos y de esta forma estarás diciendo que el método SetViewTargetWithBlend que se llamará es el del PlayerController retornado por el Nodo Get Player Controller. Por último recuerda que hay que pasarle como parámetro al SetViewTargetWithBlend el Actor que usará para configurar el nuevo punto de mira. Para esto nos falta agregar un último Nodo, el nodo que representa a la cámara. Salva estos cambios, cierra el Editor y selecciona en el Level la cámara que agregamos anteriormente. Ahora abre de nuevo el Editor da clic derecho y verás que tienes un acceso directo para agregar un Nodo Camera Actor. Una vez agregado conecta el puerto de salida del camera actor al puerto New View Target del Set View Target with Blend. Listo, ya tenemos nuestro script visual completo. En la esquina superior izquierda tienes un botón que dice Compile. Da clic ahí. Por último vamos a eliminar la sobre-escritura del método Begin Play en la clase C++ ya no es necesario (si quieres coméntalo para que no pierdas el código).

Cierra el Editor, abre el proyecto C++ y comenta en el UE4DemoPlayerController.h la declaración del método BeginPlay. Ve ahora al UE4DemoPlayerController.cpp y comenta o elimina completamente la implementación del método BeginPlay.

Listo !!. Compila y ejecuta el juego. Como notarás, es idéntico el resultado :). Ya te digo, es decisión tuya implementar lo que quieras en el Blueprint Editor o en C++ tu mismo le iras encontrando las ventajas y desventajas a cada método según lo que quieras hacer.

Tomate unos minutos si quieres, que aún nos quedan varias cosas :)

Configurando las animaciones del personaje

De momento lo que tenemos es bastante poco funcional. Simplemente al abrir el juego vemos al personaje protagónico, ya visto desde una cámara fija pero está ahí quieto sin hacer nada y estático totalmente. Vamos a darle un poco de vida.

Recuerda que nuestro equipo de diseño :) nos entregó además del modelo con su esqueleto en FBX las animaciones de caminar y reposo, también en formato FBX listas para importarlas. Pues vamos a ello. Abre el Editor en el Content Browser crea una nueva carpeta, yo le pondré Animations. Aquí tendremos todas las animaciones que importemos. Entra a la carpeta e importa los dos FBX Walk.FBX e Idle.FBX. Al seleccionarlas verás que por defecto en la ventana de FBX Import sale seleccionado Animations. Más abajo tiene la opción que permite ya en el momento de la importación seleccionar el esqueleto al que están asociadas estas animaciones. Da clic ahí y selecciona Hero_Skeleton por último da clic en Import.

Ya tenemos las animaciones de nuestro personaje, si quieres puedes darle doble clic desde el Content Browser para abrirlas en el Persona Editor y ver un preview de las mismas. Desde este Editor puedes ver todos los detalles de la animación, reproducirla y muchas más cosas que veremos en próximos tutoriales.

Ya tenemos las animaciones ahora falta asociarlas con nuestro personaje.

Creando la maquina de estado y actualizando el Character con la animación de reposo y caminar mediante Animation Blueprints.

El Animation Blueprints es la herramienta que nos da Unreal Engine para implementar toda la lógica de las animaciones del personaje de una forma súper simple. A partir de máquinas de estado y visual scripting.

Vamos a crear entonces el Animation Blueprints para el personaje. Entra en el Content Browser a la carpeta Animations da clic derecho en un espacio vacío y selecciona Animation/Animation Blueprint. Esto te abrirá la ventana de creación de Animation Blueprint. En la sección Parent Class selecciona AnimInstance y abajo en la sección Target Skeleton escribe el nombre del esqueleto que usa nuestro héroe, Hero_Skeleton por último da clic en el botón OK.

Automáticamente se agrega al Content Browser un AnimBlueprint con el nombre seleccionado para que lo cambies. Ponle el nombre que prefieras, por ejemplo HeroAnimBlueprint. Ahora, antes de hacer algo en el HeroAnimBlueprint vamos a definirle en nuestro Character que será este el Blueprint que usará para sus animaciones. Para esto ve en el Content Browser a donde tienes el Blueprint del character. En mi caso Game/Character/HeroCharacterBlueprint y dale doble clic. En la esquina superior derecha, selecciona el Modo Defaults y verás que hay una sección de nombre Animation para la propiedad Animation Mode selecciona Use Animation Blueprint y para la propiedad Anim Blueprint Generated Class selecciona la clase que acabamos de crear HeroAnimBlueprint_C. Listo, guarda y cierra el Editor.

imagen_09

Ve ahora al HeroAnimBlueprint, dale doble clic y se te abrirá el Persona Editor. De inicio tienes un nodo Final Animation Pose. A este Node conectaremos la salida de lo que vamos a crear ahora, pero primero, de nuevo un poco de teoría.

En Unreal Engine hay un mecanismo súper genial e intuitivo para definir las animaciones que tienen los personajes según su estado y las condiciones que definen cada estado. O sea, si el personaje está en reposo se animará la animación de reposo, si el personaje está caminando se ejecutará la animación de caminando. Se pueden hacer ligamentos entre animaciones, para que estos cambios sean mas fluidos, además definir las condiciones de cada estado. Por ejemplo, para que el personaje esté en reposo su atributo “velocidad” tiene que estar en cero, para que esté caminando su atributo “velocidad” será distinto de cero, y así. Todo esto se puede hacer mediante una maquina de estado y un script visual en el Animation Blueprint.

Vamos a crear la maquina de estado, de momento será muy simple. Dentro del AnimBlueprint Editor da clic derecho y selecciona StateMachine/Add State Machine esto agrega un Nodo de tipo StateMachine a la escena. Cámbiale el nombre a algo lógico, como HeroStateMachine o como prefieras. Ahora, dentro de ese State Machine vamos a definir los distintos estados que tendrá el personaje. Da doble clic en el nodo State Machine para entrar a editarlo. Dentro tienes un nodo de nombre Entry, da clic derecho Add State … y ponle al nuevo nodo Idle de nombre. Ahora conecta, como mismo hicimos en el level blueprint, el puerto de salida del nodo Entry al puerto de entrada del nodo Idle que acabamos de crear.

Seguidamente vamos a definir la lógica del estado Idle. Dale doble clic al nodo Idle, da clic derecho y selecciona Animation/Play Idle. Esto agrega el Nodo que representa la animación Idle que importamos anteriormente al Editor. ahora conecta este nodo al nodo Final Animation Pose.

Listo vamos a repasar como quedan todas las conexiones en cada uno de los niveles. De adentro hacia afuera tenemos nodo Play Idle conectado al nodo Final Animation Pose. En el nivel superior (HeroStateMachine) nodo Entry conectado al nodo Idle y por último en el nivel superior (AnimGraph) el nodo HeroStateMachine conectado al nodo Final Animation Pose. Hecho esto da clic en Compile en la esquina superior derecha del Editor. En el panel de la izquierda podremos ver un preview ya del personaje con la animación del Idle

imagen_10.1

imagen_10.2

imagen_10.3

Ejecuta el juego. Ya tenemos a nuestro personaje en su estado de reposo y animándose perfectamente.

Personaje principal ya en el juego en estado de reposo animándose correctamente.

Personaje principal ya en el juego en estado de reposo animándose correctamente.

Configurando los controles del juego

Muy bien, hasta ahora hemos creado y configurado el Character, hemos configurado una cámara fija temporal para el juego y hemos configurado la primera animación del personaje, el próximo paso de seguro que sabes cual es . . . hacer caminar al chico :)

Primero vamos a definir los controles del juego. Para esto desde el Unreal Engine Editor menú Edit/Project Settings, Sección Engine/Input, Bloque Bindings. Da clic en el botón del + en Axis Mapping y despliega la flechita. En el campo para escribir, escribe MoveForward. Da clic en la flechita al lado del EditText y despliega el campo y selecciona W y en Scale deja 1.0. Da clic de nuevo en el + al lado del EditText de MoveForward selecciona del nuevo combobox la S y en Scale pon -1.0.

Ahora da clic en el + de Axis Mappings para crear otra sección al nivel de MoveForward. En el nuevo EditText escribe MoveRight. Agrega dos hijos a MoveRight: A con Scale igual a -1 y D con Scale igual a 1.

imagen_12

Lo que acabamos de hacer es definir los controles que tendrá nuestro juego. El nombre que le ponemos, por ejemplo, MoveForward es para conocer esta entrada desde programación y lo que seleccionamos en el combobox es el control que disparará esta acción. El valor de Scale es un valor numérico que llega al método desde programación, generalmente con -1 y 1 es suficiente para la mayoría de los casos. Otra cosa a notar es que gracias a este valor de Scale las acciones que son en una dirección y en su contraria las registramos con el mismo identificador (MoveForward por ejemplo) y simplemente le cambiamos el valor de Scale a 1 si es hacia delante y a -1 si es hacia atrás.

Bien, hecho esto vamos a programar en el Character la lógica para lograr el desplazamiento por la escena con estos controles, de momento será muy simple el desplazamiento del personaje en la escena, pero suficiente para entender como funciona todo. Básicamente necesitamos dos cosas. Sobrescribir el método virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) de APawn para registrar los métodos que se van a llamar cada vez que se detecte las entradas que definimos, o sea un MoveForward o un MoveRight, y por supuesto, implementar el desplazamiento del Character en dependencia de la entrada.

Abre la clase HeroCharacter.h y modifícala para que quede de la siguiente forma:


UCLASS()
class AHeroCharacter : public ACharacter
{
	GENERATED_UCLASS_BODY()
    
protected:
    
    /** 
     * Se llama cuando el motor detecta la entrada configurada para 'MoveForward'.
     * En este caso cuando el usuario toca la tecla W o S del teclado 
     */
	void MoveForward(float Value);
    
    /**
     * Se llama cuando el motor detecta la entrada configurada para 'MoveRight'.
     * En este caso cuando el usuario toca la tecla A o D del teclado
     */
    void MoveRight(float Value);
    
    /**
     * Metodo de la clase APawn que permite configurar los 'binding' de los controles
     * Es llamado automaticamente por el Engine
     */
    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE;
    
};

Nada raro aquí, simplemente definimos dos métodos en donde vamos a implementar la lógica para cuando se detecte cada entrada y agregamos aquí también la declaración del método SetupPlayerInputComponent de APawn para poderlo sobrescribirlo

Ahora pasa al HeroCharacter.cpp y modifícalo para que quede de la siguiente forma:


#include "UE4Demo.h"
#include "HeroCharacter.h"


AHeroCharacter::AHeroCharacter(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{

}

void AHeroCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
    //Le dice al motor que cuando detecte las entrada de tipo MoveForward que llame al metodo AHeroCharacter::MoveForward
	InputComponent->BindAxis("MoveForward", this, &AHeroCharacter::MoveForward);
    
    //Le dice al motor que cuando detecte las entrada de tipo MoveRight que llame al metodo AHeroCharacter::MoveRight
	InputComponent->BindAxis("MoveRight", this, &AHeroCharacter::MoveRight);
}


/**
 *  Se llama cuando se detecta la entrada de tipo MoveForward (Cuando el usuario toca las teclas W o S).
 *  Determina la dirección en la que está el personaje y le aplica un movimiento (positivo o negativo) en esa dirección
 *
 *  @param Value Value es igual a 1 cuando se detecta W y -1 cuando se detecta S
 */
void AHeroCharacter::MoveForward(float Value)
{
	if ((Controller != NULL) && (Value != 0.0f))
	{
		//Obtiene la rotacion actual
		const FRotator Rotation = Controller->GetControlRotation();
        
		// Crea el vector de direccion a partir de hacia donde está rotado y aplica el movimiento
		const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
		AddMovementInput(Direction, Value);
	}
}

/**
 *  Se llama cuando se detecta la entrada de tipo MoveForward (Cuando el usuario toca las teclas A o D).
 *  @param Value Value es igual a 1 cuando se detecta D y -1 cuando se detecta A
 */
void AHeroCharacter::MoveRight(float Value)
{
	if ( (Controller != NULL) && (Value != 0.0f) )
	{
		//Determina la dirección del movimiento hacia los lados. Notar que solo nos intereza la rotacion en el eje Y
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);
        
		// Crea el vector de la dirección y aplica el movimiento
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
		AddMovementInput(Direction, Value);
	}
}

Ya aquí si tenemos algunas cosas que comentar, pero de seguro a estas alturas tienes una idea de todo. Primero, en SetupPlayerInputComponent usamos el parámetro que recibe para configurar los métodos que se van a llamar cuando se detecte cada una de las entradas. O sea, con InputComponent->BindAxis(“MoveForward”, this, &AHeroCharacter::MoveForward); estamos diciendo que cuando el Engine detecte la entrada MoveForward, que como definimos será cuando el jugador presione las teclas W o S del teclado, se llamará el método MoveForward. Y el mismo principio para la otra entrada.

Ahora vamos a ver la implementación del método MoveForward. Este método recibe un parámetro float, que es el valor Scale que registramos en el Editor. O sea, cuando se toque la W se llamará este método con 1.0 como parámetro y cuando se toque la S se llamará este método con -1.0 como Value.

El método lo que hace es determinar la rotación que tiene el modelo y el vector en la dirección a la que está orientado y mediante el método AddMovementInput hacemos que el personaje se mueva en esa dirección. Fíjate que se calcula la dirección y como se pasa Value que será 1 o -1 entonces el personaje se moverá hacia delante o hacia atrás según Value. AddMovementInput es un método de APawn que permite aplicar un movimiento al Pawn para el caso del personaje que no sea un cuerpo físico, como el nuestro. Para el caso del MoveRight fíjate que es prácticamente lo mismo, pero al calcular la dirección lo hacemos en base al eje Y y no con el eje X.

Listo, esto es todo lo que necesitamos. Compila y ejecuta el juego, cuando abra presiona las teclas W,S,A,D del teclado para controlar al personaje. Cuidado no te caigas por los bordes de la plataforma 😉

Umm pero aún tenemos dos problemas con este movimiento. Primero, el personaje no rota en la dirección del movimiento como sería lo lógico, y el otro problema es que a pesar que se está moviendo sigue con su animación de reposo. Vamos entonces a solucionar estos dos problemas.

Primero, para solucionar el problema de la rotación es muy fácil. Abre el HeroCharacter.cpp y modifica el constructor para que te quede de la siguiente forma:

AHeroCharacter::AHeroCharacter(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
    //Por defecto esta propiedad viene en true para el Character.
    //Pero en nuestro modelo de desplazamiento, no queremos que el personaje rote en base a la rotación del Controller.
    bUseControllerRotationYaw = false;
    
    //Configuración del componente CharacterMovement
    
    //Al estar en true habilita para que el character se rote en la dirección del movimiento al comenzar el movimiento.
	CharacterMovement->bOrientRotationToMovement = true;
    
    //Factor de rotación para la propiedad anterior.
	CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
    
    //Bajamos un poco el valor por defecto de MaxWalkSpeed para que el personaje camine un poco más lento.
    CharacterMovement->MaxWalkSpeed = 400.0f;
}

Recuerdas que el Character tiene un CharacterMovement verdad ?. Pues aquí lo que hicimos fue modificar algunos valores para cambiar el comportamiento por defecto del Character. Puedes revisar en el Editor desde el HeroCharacterBlueprint que creamos, todas las propiedades que tiene el CharacterMovement, juega un poco con ellas para que veas todo lo que se le puede definir al movimiento del Character.

Agregando animación de caminando al personaje.

Vamos a trabajar ahora en el último problema que tenemos, hacer que el personaje cuando esté en reposo tenga su animación de reposo (como ahora) pero cuando esté caminando reproduzca la animación de caminando, con esto veremos uno de los mecanismos que nos da Unreal Engine para ligar dos animaciones de forma suavizada, los Blend Space.

Blend Space es el Nodo del Animation Blueprint que nos permite hacer blending entre dos animaciones en base a la entrada de valores. En Unreal tenemos dos tipos: el Blend Space que es para varias entradas y el Blend Space 1D que es para una sola entrada. Para este simple ejemplo usaremos el Blend Space 1D ya que necesitamos solamente una entrada para lo que queremos lograr, la velocidad del desplazamiento.

Abre el Editor y dentro de la carpeta Animations en el Content Browser da clic derecho para agregar un Animations/BlendSpace1D ponle de nombre IdleWalkBlendSpace1D y dale doble clic para abrir el Editor de este elemento. Aquí la idea es la siguiente, decirle las dos animaciones que harán blending según el valor de una variable. En el panel de las propiedades de IdleWalkBlendSpace1D en el X Axis Label escribe Speed (esto es solo para una referencia, puede ser cualquier otra palabra que te represente el valor que se tiene en cuenta para cambiar entre una animación y otra). En el rango pon 0 y 100. Ahora fíjate que más abajo tienes un espacio como de una gráfica, arrastra hacia ahí desde el panel Asset Browser la animación Idle y colócala al inicio del eje X, has lo mismo para la animación Walk y colócala al final del eje. Listo, ahora mueve el cursor sobre el eje y fíjate en el panel Preview como a medida que el valor se va modificando, el modelo va cambiando de su estado Idle a Walk. Guarda y cierra este editor.

Configuración del IdleWalkBlendSpace1D

Configuración del IdleWalkBlendSpace1D

Ahora vamos a modificar el HeroAnimBlueprint para en el State Machine al nodo Idle cambiar su comportamiento. Abre el HeroAnimBlueprint ve desde el AnimGraph hasta el nodo Idle (si quieres puedes cambiarle el nombre ahora a Idle/Walk) ya que dentro de este nodo se manejarán estos dos estados. Entra para editarlo. Elimina el nodo de Idle que estamos usando ahora y agrega el IdleWalkBlendSpace1D que acabamos de crear. Como ves este Nodo a diferencia del anterior tiene un puerto de entrada con el nombre Speed (que se lo definimos cuando lo creamos) por lo que para que funcione alguien le tiene que suministrar este valor. En el panel MyBlueprint hay un icono con un +V que dice Variable. Esto es para agregar una nueva variable al gráfico. Da clic aquí y dale el nombre de Speed a la variable, arrástrala para el espacio de trabajo y cuando te pregunte Set/Get selecciona GET. Por último conecta Speed a IdleWalkBlendSpace1D y este al Final Animation Pose.

imagen_14

Ya tenemos el Nodo Idle/Walk listo, pero te estarás preguntando … a la variable Speed, quien le da su valor ?… Esto lo tenemos que definir en el EventGraph. Vamos a implementar un algoritmo que en cada loop de la animación obtenga el Pawn (que sería nuestro personaje) después que se llame al método GetVelocity que retorna el vector de desplazamiento que lleva el personaje en ese momento. Este vector por supuesto se modifica gracias a la implementación del MoveForward y MoveRight que hicimos anteriormente en C++. Cuando tengamos la velocidad, obtenemos la distancia de ese vector y vamos a usar ese valor para darle valor a la variable Speed. Todo esto lo vamos a hacer en el HeroAnimBlueprint/EventGraph.

Ya vimos anteriormente como es el Visual Scripting en el Blueprint Editor así que no tendrás problema y será otro momento para repasar su funcionamiento. Vale la pena aclarar en este punto, que como dijimos anteriormente, todo esto se puede hacer desde programación directo. Pero por ejemplo, la lógica del comportamiento de las animaciones es uno de los casos donde es mucho mejor hacerlo en el Blueprint para que quede todo el mecanismo de animación del personaje en un solo lugar y poderlo repasar y pre visualizar fácilmente.

Abre el HeroAnimBlueprint/EventGraph, agrega y conecta los Nodos para que te quede igual que la imagen siguiente. No voy a repetir paso a paso todo el proceso, porque con la explicación que hicimos anteriormente del Blueprint Editor debes poder hacerlo por tu cuenta y entender todo lo que hace el algoritmo.

Algoritmo del HeroAnimBlueprint/EventGraph con la lógica para setear el valor de la variable Speed usada dentro del State Machine del personaje para cambiar entre las animaciones de caminando y reposo.

Algoritmo del HeroAnimBlueprint/EventGraph con la lógica para setear el valor de la variable Speed usada dentro del State Machine del personaje para cambiar entre las animaciones de caminando y reposo.

Listo, compila y guarda el Blueprint y dale Play al juego… Super verdad !! ya tenemos nuestro personaje moviéndose por el terreno correctamente según queramos y cuando está detenido se anima con su animación de reposo y cuando está caminando se anima con su animación de Walk. :)

Conclusión

Hasta aquí este tutorial de introducción al Unreal Engine 4. En el próximo tutorial modificaremos la cámara, los controles y el movimiento del personaje para hacer nuestro juego un side-scroller style. Además agregaremos algo de lógica al juego, nuestro personaje tendrá que lograr alcanzar todas las monedas que existan en el escenario antes de un tiempo determinado, para poder ganar, de lo contrario perderá y tendrá que comenzar de nuevo. Mientras… déjame saber tus comentarios :).

Fernando Castillo Coello
Follow me

Fernando Castillo Coello

Gameplay Programmer at GameOlic
I've been into games development with Unreal Engine since 2014 and want to share with you some of the tips and tricks that I learned during my journey.
Fernando Castillo Coello
Follow me

33 pensamientos en “Introducción al desarrollo de video juegos con Unreal Engine 4

  1. set92

    Tengo un problema con el tutorial y es que en el paso de añadir el HeroCharacter al Blueprint mediante las custom classes no me aparece.
    Es decir, le doy en la toolbar a Blueprints – New Class Blueprint y busco en Custom Classes el HeroCharacter pero no aparece, he probado a hacer todo desde 0 pero me sigue sin aparecer y obviando ese paso y creando la clase y el personaje no funciona, ya que cuando le doy a arrancar al nivel sigo teniendo una camara flotante.

    Ya de paso aprovecho para preguntar una duda, hay algun tipo de debug o puedo poner algun texto en el codigo para que me vaya diciendo en tiempo de ejecucion los valores de las variables y cosas asi?

    Responder
    1. nan2cc

      Hola set92,

      Para crear el Blueprint del HeroCharacter, después de que crees la clase C++ mediante el editor File/Add Code To Project y la implementes según las indicaciones del tutorial, asegúrate de cerrar el Editor, Compilar y Ejecutar nuevamente el proyecto. Después de esto en el Content Browser, New/Blueprint, en la sección Custom Classes, tendrás la clase HeroCharacter y podrás crear el Blueprint que herede de esta clase. Pero tienes que cerrar, compilar y ejecutar el código antes. Puede que sea ese el problema que estas teniendo.

      En cuanto a tu otro pregunta. Sí, desde el código puedes usar el método AddOnScreenDebugMessage de GEngine que te permite imprimir en la pantalla un texto de un color determinado y mantenerlo en pantalla un tiempo determinado. Ejemplo:

      GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Blue, “Texto a imprimir en la pantalla”);
      

      El método espera los siguientes parámetros:
      Key: Un identificador numérico único para prevenir que el mismo mensaje salga en distintas líneas.
      TimeToDisplay: El tiempo en segundos que estará el texto en la pantalla
      DisplayColor: El FColor con el que saldrá el texto
      DebugMessage: El texto a mostrar

      Para incluir el valor de variables en el texto que imprimes, puedes usar el método Printf de la clase FString, que te permite formatear un string. Por ejemplo

          FString a = FString(TEXT("Unreal Engine 4"));
          float b = 3.14f;
          int32 c = 5;
          GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Blue, FString::Printf(TEXT("Prueba de Printf: a es un string = %s, b es un float = %f y c es un int = %i"), *a, b, c));
      

      Saludos

      Responder
        1. nan2cc

          Hola marta, en realidad uso MAC y como IDE XCode, pero si mal no recuerdo para compilar en Visual Studio, después de tener cargado el proyecto En el panel Solution/Games/TuProyecto y ahí clic derecho Build, si usas una versión moderna del unreal con eso será suficiente y el editor recargará los cambios. Si usas una versión vieja, cierra el editor y en el VS despues de dar clic derecho selecciona Debug/Start new instance, esto compilará y te abrirá el editor después de compilar. Espero esto te ayude. slds

          Responder
    1. nan2cc

      Hola marta, probablemente estas usando una versión del Unreal distinta a la que se usó en el tutorial. Este tutorial fue desarrollado con una de las primeras versiones, en ese momento el Template Basic Code si creaba también el PlayerController. En las versiones más recientes dejaron de crearlo por defecto. Para solucionar esto tienes que crear la clase tu desde el Editor/Add Code to Project y crear una clase que herede de Player Controller. slds

      Responder
  2. Alex

    Hola, en primer lugar agradecerte muchísimo que hagas estos tutoriales, pero me ha surgido un pequeño problema, y es que por más que añado el código para que rote, no rota. Compilo y recompilo pero nada, querría saber si me podías ayudar. Te dejo el código que tiene mi fichero HeroCharacter.cpp :

    #include “UE4Demo.h”
    #include “HeroCharacter.h”

    AHeroCharacter::AHeroCharacter(const class FPostConstructInitializeProperties& PCIP)
    : Super(PCIP)
    {
    //Por defecto esta propiedad viene en true para el Character.
    //Pero en nuestro modelo de desplazamiento, no queremos que el personaje rote en base a la rotación del Controller.
    bUseControllerRotationYaw = false;

    //Configuración del componente CharacterMovement

    //Al estar en true habilita para que el character se rote en la dirección del movimiento al comenzar el movimiento.
    CharacterMovement->bOrientRotationToMovement = true;

    //Factor de rotación para la propiedad anterior.
    CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f);

    //Bajamos un poco el valor por defecto de MaxWalkSpeed para que el personaje camine un poco más lento.
    CharacterMovement->MaxWalkSpeed = 400.0f;
    }

    void AHeroCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
    //Le dice al motor que cuando detecte las entrada de tipo MoveForward que llame al metodo AHeroCharacter::MoveForward
    InputComponent->BindAxis(“MoveForward”, this, &AHeroCharacter::MoveForward);

    //Le dice al motor que cuando detecte las entrada de tipo MoveRight que llame al metodo AHeroCharacter::MoveRight
    InputComponent->BindAxis(“MoveRight”, this, &AHeroCharacter::MoveRight);
    }

    /**
    * Se llama cuando se detecta la entrada de tipo MoveForward (Cuando el usuario toca las teclas W o S).
    * Determina la dirección en la que está el personaje y le aplica un movimiento (positivo o negativo) en esa dirección
    *
    * @param Value Value es igual a 1 cuando se detecta W y -1 cuando se detecta S
    */
    void AHeroCharacter::MoveForward(float Value)
    {
    if ((Controller != NULL) && (Value != 0.0f))
    {
    //Obtiene la rotacion actual
    const FRotator Rotation = Controller->GetControlRotation();

    // Crea el vector de direccion a partir de hacia donde está rotado y aplica el movimiento
    const FVector Direction = FRotationMatrix(Rotation).GetUnitAxis(EAxis::X);
    AddMovementInput(Direction, Value);
    }
    }

    /**
    * Se llama cuando se detecta la entrada de tipo MoveForward (Cuando el usuario toca las teclas A o D).
    * @param Value Value es igual a 1 cuando se detecta D y -1 cuando se detecta A
    */
    void AHeroCharacter::MoveRight(float Value)
    {
    if ((Controller != NULL) && (Value != 0.0f))
    {
    //Determina la dirección del movimiento hacia los lados. Notar que solo nos intereza la rotacion en el eje Y
    const FRotator Rotation = Controller->GetControlRotation();
    const FRotator YawRotation(0, Rotation.Yaw, 0);

    // Crea el vector de la dirección y aplica el movimiento
    const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
    AddMovementInput(Direction, Value);
    }
    }

    No creo que esté ahí el problema pues he copiado lo mismo, pero lo dejo por si fuera de ayuda.
    Muchas gracias.

    Responder
  3. Carlos

    Hola en mi GameMode me da un error al compilar con este código, me dice Redefinition of “AtutorialEnEspanolGameMode”

    AtutorialEnEspanolGameMode::AtutorialEnEspanolGameMode(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP) {

    PlayerControllerClass = ADemoPlayerController::StaticClass();

    //Obtiene en PlayerPawnBPClass.Object la referencia al HeroCharacterBlueprint creado y configurado desde el Editor
    static ConstructorHelpers::FObjectFinder PlayerPawnBPClass(TEXT(“Class’/Game/Character/HeroCharacterBlueprint.HeroCharacterBlueprint_C'”));

    //Inicializa el atributo DefaultPawnClass con el HeroCharacterBlueprint creado y configurado desde el editor
    if (PlayerPawnBPClass.Object != NULL)
    {
    DefaultPawnClass = PlayerPawnBPClass.Object;
    }
    }

    Sabrías que puede ser?

    Responder
  4. Daniel Ocheda

    a los que tienen el problema de que no rota, es porque ahora la rotacion se accede de una forma diferente

    cambien las lineas:
    CharacterMovement->bOrientRotationToMovement = true;
    CharacterMovement->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
    CharacterMovement->MaxWalkSpeed = 400.0f;

    por estas otras:

    GetCharacterMovement()->bOrientRotationToMovement = true;
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
    GetCharacterMovement()->MaxWalkSpeed = 400.0f;

    Los de unreal van muy rapido cambiando cosas, tanto que a veces el codigo queda obsolete muy rapido.

    saludos !

    Responder
  5. Daniel

    Hola Fernando, estoy siguiendo tu tutorial y me encuentro con que la clase UE4DemoPlayerController no está creada. Creo entender que das por supuesto que esta clase ya se crea automatiicamente como lo hace UE4DemoGameMode, pero en mi caso no la veo creada…
    He intentado realizar los pasos varias veces antes de preguntarte pero siempre tengo el mismo resultado.
    Me puedes echar un cable?

    Gracias, tu tutorial es de lo mejorcito :)

    Responder
    1. Daniel

      De hecho el archivo UE4DemoGameMode creado no me coincide con el que describes.
      Es mas incompleto:

      // Fill out your copyright notice in the Description page of Project Settings.
      #include “UE4Demo.h”
      #include “UE4DemoGameMode.h”

      Si añado el código de tu ejemplo, ahí ya me está pidiendo incluir a EU4DemoPlayerController.h que como te comentaba, no parece que se haya creado.

      Muchas gracias

      Responder

Responder a paul Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>