Blog

Estructura de un Juego de Unreal Engine



11 de abril de 2023

Unreal Engine

En el mundo de los videojuegos, Unreal Engine se ha convertido en una herramienta fundamental para muchos desarrolladores, pero uno de los desafíos que se enfrenta al trabajar con esta plataforma es comprender su estructura. Una de las cosas que lo hace confuso es la existencia de varios objetos y abstracciones similares, que puede hacer difícil distinguirlos y entender cuál es el objeto más adecuado para una tarea específica. Por ello es beneficioso tener un buen conocimiento de cómo el motor arranca y se crea la estructura de un juego.

El arranque de un juego en Unreal Engine se divide en dos etapas: el arranque del motor y el arranque del juego en sí.

Arranque del Motor

El primer paso se puede resumir en precargar los módulos básicos del motor, los módulos específicos del juego y los módulos de los plug-ins. En esta etapa se inician todos los sistemas base del motor y se prepara todo para entrar al bucle de juego, el Game Loop. Una vez los módulos y sistemas están cargados correctamente, se inicia una instancia del motor en un objeto global llamado GEngine (clase UEngine), junto con la creación del objeto Game Instance (clase UGameInstance), que guarda configuraciones e información global del juego, y el objeto que representa al jugador local (clase ULocalPlayer), el usuario.

Arranque del Juego

En la siguiente etapa, el objeto GEngine es responsable de arrancar el juego de Unreal Engine. Su primera función es abrir el paquete que representa el mundo inicial del juego (clase UWorld), que contiene el nivel, objetos en el nivel llamados actores, componentes, reglas y controladores del juego. Esto crea e inicializa el primer nivel (clase ULevel), que contiene información relacionada con las reglas y los controladores que el jugador usa en el juego. Cada vez que se cambia de mundo, los objetos relacionados al mundo anterior se destruyen y se crean nuevos objetos relacionados al nuevo mundo.

Al abrir el mundo se crea un objeto llamado Game Mode (clase AGameModeBase) que corresponde al modo del juego. El Game Mode se encarga de guardar las reglas del juego y definir el estado del jugador, por ejemplo si gana o pierde. Es normal que un mismo mapa tenga diferentes modos de juego, por ejemplo un juego de carreras puede utilizar la misma pista para jugar una carrera de 3 vueltas o para tratar de hacer la vuelta más rápida. En estos casos se utiliza el mismo mapa pero 2 Game Modes distintos que dependen de estas reglas de juego, uno para la carrera de 3 vueltas y otro para la vuelta rápida. A su vez, el Game Mode crea un objeto que se utiliza para guardar el estado de la partida durante la sesión de juego, Game State (clase AGameStateBase). El Game State se utiliza para guardar información relacionada a la partida como marcadores entre jugadores, tiempo de juego o rachas de ganar o perder. El Game Mode utiliza la información guardada en el Game State para poder definir qué procede según las reglas del juego.

En esta etapa también se crea un objeto para manejar conexiones de red (clase AGameNetworkManager), pero esto solo es relevante para aplicaciones que manejan múltiples instancias conectadas del juego, como un juego en línea, por ejemplo.

Se crea el Jugador

Con el Game State creado, se procede a crear el jugador. El Game Mode guarda también la información del controlador que el jugador utiliza y el personaje que el jugador controla en el juego. Primero se crea el objeto que representa el controlador del jugador Player Controller (clase APlayerController), que a su vez crea un objeto que guarda información del jugador durante la sesión de juego, el Player State (clase APlayerState). Luego, el motor conecta este controlador con el objeto que representa al jugador local (ULocalPlayer)

El Player Controller y Player State tienen una relación similar a la del Game Mode y el Game State. El Player Controller se utiliza para procesar los tipos de controles y las preferencias del jugador; ahí se define la interfaz entre el jugador y el personaje que controla. El Player State se utiliza para guardar información como las vidas del jugador, dinero acumulado, objetos en el inventario, poderes que tenga activos, etc.

¿Y el Personaje?

Normalmente, los juegos tienen un personaje que el jugador controla, aunque no siempre es el caso. A esta toma de control se le llama poseer en Unreal Engine, un controlador posee un personaje. Cuando el Player Controller se termina de crear, se define cómo proceder para que el jugador interactúe con el juego:

  1. El jugador debe poseer un personaje, el juego crea un personaje (clase base APawn) definido en el Game Mode y lo conecta al controlador.
  2. El jugador inicia el juego como espectador, el juego crea un objeto espectador (clase base ASpectatorPawn) que permite al jugador navegar en el mundo pero no interactuar con él
  3. No hacer nada, el proceso de creación y posesión de personajes se maneja después de iniciado el juego.

Cuando todo está creado, se procede a correr la función de BeginPlay (iniciar juego) de todos los actores y componentes del juego, y se entra oficialmente al Game Loop.

Al inicio puede ser bastante información pero una vez entendido, el proceso de arranque revela qué objetos se crean primero y permite entender las responsabilidades que cada uno debe tener sobre las reglas del juego. Si bien es flexible, Unreal Engine no deja de ser un framework de software grande con varios sistemas y partes que funcionan tras bambalinas, por lo que entender cómo funciona puede ayudar a definir qué tipo de información manejar en qué sección y qué partes ignorar.

Conceptos

En resumen, estos son los elementos estructurales de un juego en Unreal Engine.


GEngine

Representa el motor de juego en sí y se encarga de abrir y cerrar los mundos, además de controlar la funcionalidad del juego. Creado al iniciar el juego y destruido al cerrarlo.

API UEngine


Jugador Local

Representa a los jugadores conectados directamente al motor, el juego inicia con al menos uno. Maneja las conexiones entre el usuario y el motor. Creado al iniciar el juego y destruido al cerrarlo.

API ULocalPlayer


Game Instance

Clase que representa la instancia del juego, guarda configuraciones e información global del juego. Se crea al abrir el juego y se destruye al cerrarlo. No se destruye cuando se cambia de mundo. Útil para guardar información del juego cada vez que se cambia de mundo.

API UGameInstance


Mundo

Paquete que contiene información del mundo en curso, incluyendo nivel (ULevel), controladores, y modos de juego. Representa el mundo del juego.

API UWorld


Nivel

Contiene información del nivel o mapa y los objetos que hay en él, es el área de juego. Se crea al abrirlo directamente y se destruye al cerrarlo. Un mundo puede contener múltiples niveles a la vez.

API ULevel


Actor

Clase base de los objetos que pueden existir en un mundo. Pueden contener componentes para modificar su comportamiento. Existen mientras que el mundo que los contiene está en curso. Se crean y destruyen dependiendo de su comportamiento en el juego.

API AActor


Game Mode

Guarda información sobre las reglas del juego, controlador del jugador y personaje del juego. Se usa para definir el estado del jugador durante el juego. Se crea al abrir un mundo y se destruye al cerrarlo.

API AGameModeBase


Game State

Guarda información sobre el estado global del juego. Se crea al abrir un mundo y se destruye al cerrarlo.

API AGameStateBase


Player Controller

Representa la interfaz entre el jugador y el juego, permite al jugador interactuar con el mundo. Puede poseer personajes en un mundo. Se crea al abrir un mundo y se destruye al cerrarlo.

API APlayerController


Player State

Guarda información sobre el estado del jugador como dinero, marcador, vidas, etc. Se crea al abrir un mundo y se destruye al cerrarlo.

API APlayerState


Pawn

Clase base de actores que pueden ser poseídos por un controlador. Existen mientras que el mundo que los contiene está en curso. Se crean y destruyen dependiendo de su comportamiento en el juego.

API APawn

Si te interesa saber mas...

Puedes escribirme a me@rodaraujo.com.



Rodrigo Araujo Soria, 2023