DevBlog_01: Terrain Generation

Lyudmil Pashayanov
5 min readFeb 15, 2024

--

Me (game developer) and a friend of mine (artist) are creating a single-player, Tower Defense, Exploration game in Unreal Engine 5.

Tower Defense with a twist: The player will not be dragging and dropping defenses on a map from the game interface, like in traditional TD games. The player will be a character gathering resources, building defenses and defending along with the defenses he builds (think of: Orcs Must Die X Minecraft).

Exploration: Every time the player replays a level, the layout of the level will be different. The goal is to make the player explore every time the level starts and not allow him to memorize locations and strategies. Every level play through must be unique.

Discover the process behind creating the terrain in our game:

As there will be a building mechanic in the game, we wanted to make the terrain grid-based and not hide the grid from the player.

Each level’s flooring is created by arranging various types of ‘cell chunks’ adjacent to one another. Think of the type of chunks as types of landforms: hills, valleys, plains, etc.

Flat chunk, created out of 100 cells (tiles)
Several Adjacent Flat and Hill Chunks used to create the terrain in the game

Chunk code design:

UML Class Diagram: Chunks

ChunkManager: Responsible for generating the world.

Chunk: Base class from which the different Blueprint Chunk assets inherit and are constructed.

Cell: Holds information about the cell, shows/hides and animates the mesh.

Chunk creation:

The UE5 editor is not a place, where you can easily design and create these landforms (it’s also not intended to be), that’s why each chunk is designed and constructed in Autodesk Maya.

Attempt 1:

I thought that simply importing the Chunk.fbx into UE5 and then just attaching the custom Cell class component to the meshes in the newly created blueprint, will be enough to achieve the latter code design.

But apparently, in UE5 you can not bulk/mass add components in a Blueprint asset, as seen in the video below:

Can not add Cell class to multiple statics meshes at once. I have to add one component at a time…

Attempt 2:

I’ve also tried to do the same through code: adding the Cell class component to the Chunk blueprint hierarchy from the constructor function. However, when the constructor runs, the data of the blueprint is not yet available:

#include "ImportedChunk.h"

// Pseudocode to run inside the constructor function
void AImportedChunk::GetChildrenOfImportedChunk()
{
if (RootComponent)
{
TArray<USceneComponent*> ChildComponents;
RootComponent->GetChildComponents(ChildComponents); // Feed the ChildComponents array.

// Iterated through ChildComponents array and add the custom Cell class.
for (USceneComponent* ChildComponent : ChildComponents)
{
// ChildComponents is empty and we never get inside this loop.
}
}
}

Solution:

At the end, I imported only the cell.fbx and used it to construct the whole Chunk blueprint from code.

In order to achieve the chunk landforms designed in Maya, I only needed to know where and how to place each cell in the chunk. For that we created a python script for Maya, to export the chunk landform data (the location, rotation and mesh type of each cell) into a JSON file:

JSON data for the creation of the Hill_Chunk

💡: What I have found surprising, is that you can not have .txt files inside an UE5 project.

Therefore, if I want to have a JSON file with config data, I had to convert that file into so called “Data Table” asset, in order to use it in code:

Data Table asset for my Hill_Chunk JSON data

Now each chunk landform blueprint asset should have its own JSON config data, so it knows how to construct itself.

💡: Something that I didn’t like about Unreal, is that you can’t reference assets (in my case the JSON config data) in the blueprint asset and use these references in the constructor:

Unable to use references in constructor

Therefore, I had to use ObjectFinder class in the constructor, so I can get the JSON data that I want to use. The following function will have to be improved in the future, but for now it does the job :)

// I know it is prone to human error to get assets by their name,
// but this was the only approach I could find working for now.
ConstructorHelpers::FObjectFinder<UDataTable> AChunk::GetGridConstructJsonPath() //TODO: Find a better way to reference the different Chunks Data.
{
static ConstructorHelpers::FObjectFinder<UDataTable> DataTableFinderHill(TEXT("/Script/Engine.DataTable'/Game/LyudmilContent/ChunksJSON/chunk_data_HillChunk.chunk_data_HillChunk'"));
static ConstructorHelpers::FObjectFinder<UDataTable> DataTableFinderFlat(TEXT("/Script/Engine.DataTable'/Game/LyudmilContent/ChunksJSON/chunk_data_FlatChunk.chunk_data_FlatChunk'"));

TArray<FString> Substrings;
GetName().ParseIntoArray(Substrings, TEXT("_"), true);
FString blueprintName;
for (int i = 0; i < Substrings.Num(); i++)
{
if (Substrings[i] == "BP")
{
blueprintName = Substrings[i + 1];
break;
}
}

if (blueprintName == "HillChunk")
{
return DataTableFinderHill;
}
else if (blueprintName == "FlatChunk")
{
return DataTableFinderFlat;
}

return DataTableFinderFlat;
}

After figuring out all these intricacies related to Unreal, we now have a nice, flexible system to creating different types of chunk landforms, just by using a JSON file. (Would be interesting to try and ask ChatGPT to produce some JSON data and see what landforms it will produce)

Cells Animation:

As main part of the game is Exploration, I wanted to make the experience of it fun, ‘mysterious’ and enjoyable:

  1. The player never knows whats out there in the world, unless he decides to go and check.
  2. The world is generated and unveiled in front of the player’s eyes (or I should say: underneath his feet):
The evolution of the terrain generation
Testing different style

This animation functionality was achieved with the following interaction between the Chunk and the Cell class:

Sequence Diagram: Interaction between Cell and Chunk to trigger showing of a cell.

DevBlog_01 of my exploration/tower defense game ends here. We have a lot of stuff planned for the future and day by day we are implementing them.

The cell mesh is about to change and next thing in the planning is to implement interactables in the world: rocks to collect, trees to cut, fences and towers to build🌄:

Concept art for the upcoming DevBlog :)

Thanks for reading and reaching the end. Here is some cake for u 🍰.

--

--

Lyudmil Pashayanov
Lyudmil Pashayanov

Written by Lyudmil Pashayanov

Software/game programmer with 4 years of experience in the game and tech service industry. I have great passion for creating legendary, well-engineered games!

No responses yet