Project Lunaris
A project I'm currently developing for Segritude games, Working as a Unreal Engine Programmer, Using Blueprints and C++
I’m working as C++ programmer on an Unreal Engine 5 survival RPG inspired by Enshrouded and Valheim. I work across UE5 C++ and Blueprints, owning multiplayer/replication and core gameplay systems (AI, party system, world map & waypoints/compass, interaction, and UI/UX). My focus is a modular, data-driven architecture with safe pointers (TObjectPtr/TWeakObjectPtr), const-correctness, and early-out guards—plus ongoing profiling and optimizations to keep Gameplay smooth and the codebase scalable.
The map/compass is fully modular: attach a UMapMarkerComponent
to any Actor and it auto-registers on the Map and Compass.
Designers can tweak the icon, size, color, and visibility directly in the editor—no hardcoded links. Below is the waypoint add flow,
which converts a screen click into a world-space marker and safely spawns it.
void UWorldMapUI::AddWaypoint(const FVector2D ScreenPosition) const
{
const UMapSubsystem* MapSubsystem = UMapSubsystem::Get(this);
if (!IsValid(MapSubsystem) || MapSubsystem->RegisteredMarkers.Num() >= 3)
{
LOG_WARN(MapSystemLog, "Cannot add more than 3 waypoints. Remove one first.");
return;
}
if (!MapTexture)
{
LOG_ERROR(MapSystemLog, "MapTexture border is null!");
return;
}
const FGeometry Geo = MapTexture->GetCachedGeometry();
const FVector2D LocalPt = Geo.AbsoluteToLocal(ScreenPosition);
const FVector2D Size = Geo.GetLocalSize();
if (LocalPt.X < 0 || LocalPt.X > Size.X || LocalPt.Y < 0 || LocalPt.Y > Size.Y)
return;
const ULandSubsystem* LandSubsystem = ULandSubsystem::Get(this);
if (!IsValid(LandSubsystem)) return;
FVector WorldPos = LandSubsystem->TextureToWorld(LocalPt, Size, 0.f);
if (UMapSubsystem* MSS = UMapSubsystem::Get(this); IsValid(MSS))
{
WorldPos = MSS->ProjectToGround(WorldPos, 100000.f, 20.f);
}
if (IsValid(MarkerClass))
{
FActorSpawnParameters Params;
Params.Owner = GetOwningPlayer();
if (GetWorld()->SpawnActor<AActor>(MarkerClass, WorldPos, FRotator::ZeroRotator, Params))
{
LOG_INFO(MapSystemLog, "Spawned Marker at %s", *WorldPos.ToString());
}
else
{
LOG_ERROR(MapSystemLog, "Failed to spawn Marker actor!");
}
}
}
UMapSubsystem
. If invalid or at the 3-waypoint cap, exit early to keep UI readable and avoid spam.GetCachedGeometry()
+ AbsoluteToLocal
to map the click into the map widget’s local coords, then bounds-check.ULandSubsystem::TextureToWorld
so UI stays dumb; all terrain/UV mapping logic lives in the land subsystem.UMapSubsystem::ProjectToGround
snaps to terrain with a bounded trace (depth/step), so markers never float.MarkerClass
at the resolved position and set Owner
to the local player for clean lifetime/relevance.UMapMarkerComponent
auto-registers to Map/Compass. Icon, size, color, and visibility are editable per instance.const
and cheap; invalid state bails immediately, keeping frame time predictable.IsValid(...)
checks; store UObjects as TObjectPtr<>
in owners, and external actor refs as TWeakObjectPtr<>
to avoid dangling refs.ULandSubsystem
handles mapping, UMapSubsystem
manages registration and projection.UMapMarkerComponent
to any actor you want visible.BeginPlay()
.Got any Suggestions or queries? Reach out or check out the game on Play Store.