3D Tilemap Navigation System

For a pet project I am working on a simple randomly generated 3D tile map using a procedural mesh. I was struggling for a bit to find a good way to utilize the Navigation System. I have decided to post my solution here, as this principle is not very well documented.

I found it is possible to extend the UNavRelevantComponent to modify navigation data on a 3D tilemap. The tile map is a relatively simple actor containing a procedural mesh and an array of tile data, which is built using SimplexNoise. For the sake of completion these are the relevant structs:

struct FTile
{
	FTileType TileType;
	float Height;
};

struct FTileType
{
	UMaterial* Material;
	bool Traversable = true;
};

The tile information is then stored in a simple one dimensional array on my custom ATileMap. This data is created using a map generator. Exactly how it is created isn’t important for this.

TArray<FTile> Tiles;

As stated before, a procedurally generated mesh is generated from this tile data. The tile array indexes are converted to XY positions and vice versa. Now we have a procedural mesh with nice tiles. The question is how can we make these tiles untraversable based on the Traversable property? By default the navigation system will simply mark the whole mesh as traversable. After some digging around I found the UNavModifierComponent and UNavRelevantComponent which can be used to add navigation information to an actor. I created a UTileMapNavModifierComponent to be added to the TileMap actor, providing additional nav information.

class UTileMapNavModifierComponent : public UNavRelevantComponent
{
public:
	virtual void GetNavigationData(FNavigationRelevantData& Data) const override;
	void CreateNavModifiers(FCompositeNavModifier& Modifiers) const;
};

void UTileMapNavModifierComponent::GetNavigationData(FNavigationRelevantData& Data) const
{
	this->CreateNavModifiers(Data.Modifiers);
}

void UTileMapNavModifierComponent::CreateNavModifiers(FCompositeNavModifier& Modifiers) const
{
	ATileMap* TileMap = Cast<ATileMap>(this->GetOwner());

	for (int i = 0; i < TileMap->Tiles.Num(); i++)
	{
            // Skip tiles that are traversable
		if (TileMap->Tiles[i].TileType.Traversable)
			continue;

            // Calculate tile world location
		FVector2D Position2D = TileMap->IndexToXY(i) * TileMap->TileDimension;
		FVector Position(Position2D.X, Position2D.Y, 0);
		Position += TileMap->GetActorLocation();

		FTransform Transform;
		Transform.SetLocation(Position);

            // Create a small box that is marked as blocking navigation
		FBox Box(FVector(0, 0, 0), FVector(TileMap->TileDimension / 2, TileMap->TileDimension / 2, 10.0f));

            // Add the box with the specified transform to the nav modifiers
		Modifiers.Add(FAreaNavModifier(Box, Transform, UNavArea_Null::StaticClass()));
	}
}

Hope this will help someone in the future.

Answered in original question

Hey, this looks decent! What is the best way to reconize navigation by using colors? I am making a top view 2D game map.

So i want it that the streets are reconized as navigation by color. Any idea?