Back to projects

Project: Abduction

2023-2024

A solo-built first-person horror prototype in Unreal Engine 5: a facility that is generated fresh every run by a C++ level generator, and a creature that hunts you through it

Overhead wireframe of a procedurally generated floor layout

A generated floor from above: rooms dropped onto a grid and joined by hallways

Dim storage room lined with metal shelving, lit red by emergency lighting

A storage room under emergency lighting

Concrete stairwell with a handrail and red-lit steps

A stairwell, placed and connected by the generator like any other room

First-person view of the player climbing a ladder under red light

Climbing a ladder in first person

Long white corridor with a checkered floor and a shadow cast on the wall

A lab-area hallway, routed between rooms with A* pathfinding

Empty room with red-trimmed double doors at the far end

Locked sliding doors at the end of a room

Corridor junction with framed pictures along the walls

A hallway junction

About this project

Project: Abduction is a first-person horror game I built by myself in Unreal Engine 5. You wake up inside a facility you've never seen before, and neither have I: the layout is generated when the level starts, so every run is a different building. To get out you have to bring the place back to life (restore power, open locked doors, find the information you need) while a creature called C-117 hunts you through the halls.

I did every part of it myself: the C++ and Blueprint code, the 3D models, the animations, the sound, and the UI. The only things I took from asset packs were a few textures and a small amount of utility logic that wasn't worth rewriting.

The game is a shelved prototype. The core systems work, but I ran out of time to finish it. I was busy with school, college and scholarship applications, and the rest of life. The following summer I got really into robotics and never came back to it.

Procedural generation

This was the part I cared about most, and the hardest part to get right. I went through three attempts: a Blueprint generator, an experiment with Wave Function Collapse, and finally a generator rewritten from scratch in C++, which is the one the game uses.

How the C++ generator builds the facility:

  • Two grids. The building volume is divided into a 3D grid of 4 m floor tiles, and a second, coarser grid of room cells laid over it (each room cell is 5 x 5 tiles). Rooms are placed on the coarse grid and hallways are routed on the fine one
  • Seeded. Every random choice comes from one seeded random stream, so the same seed always rebuilds the same building, which made bugs reproducible
  • Rooms. The generator is given a list of room types. Each type says how many to spawn, whether it goes in a random cell or a fixed spot, how high in the building it is allowed to appear, and whether its size is random. Each room is its own actor, and it claims the tiles it sits on so nothing else can overlap it
  • Connecting rooms. On each floor the generator starts from one room and repeatedly attaches the closest unconnected room, measured from door to door, until every room on that floor is joined. This is the same idea as a minimum spanning tree, and it guarantees no room is left unreachable
  • Hallways. The two areas of the facility lay their hallways differently. In the lab area (the white hallways), each connection is routed between the two chosen doors with my own implementation of the A* pathfinding algorithm, searching the free floor tiles in 2D, one floor at a time. In the testing area, hallways are simple L-shaped runs between rooms
  • Stairwells. A stairwell is spawned alongside the other rooms and treated as a special room: a 2 x 2 tile shaft that runs up through the floors above it. Because it counts as a room on every floor it passes through, the hallway step connects it on each one, and that is what links the floors together
  • Walls. Nothing places walls by hand. For every hallway tile, the generator checks the four tiles around it and puts a wall on any side that has no floor. Rooms build their own walls and swap in a doorway piece wherever a hallway was attached
  • Instanced meshes. Floors, walls, and ceilings are added in batches as instances of a few static meshes, with a separate set per area so each part of the facility has its own look
  • Hidden until ready. The level is hidden while the building is generated and shown when the generator reports that it's done

The grid dimensions, tile size, room cell size, seed, and the list of room types are all exposed in the editor, so I could tune the layout without recompiling. A debug mode draws the grids and the connections between rooms.

The game

Getting out

  • Tasks are spread across the generated rooms: cranking a generator to restore power, keypads, a three-dial combination lock, and levers
  • Information pickups (notes and folders) give you the codes and context you need
  • Goal markers and a compass point you toward the rooms that matter, since nobody can memorize a map that changes every time

C-117

  • Driven by a behavior tree and Unreal's Environment Query System
  • It doesn't simply know where you are. It searches "hotspots", which are created whenever the player interacts with a room: solving a puzzle, breaking down a door, or turning on the facility's generators. Making progress is what gives you away
  • It can't be killed. Shooting it only stuns it, and it slowly recovers before it comes after you again

The player

  • First-person movement with sliding, vaulting, rolling, and climbing ladders
  • A pistol with magazines you have to find and manage, plus a melee attack
  • Camera animation for nearly every action (landing, reloading, slamming a door, taking damage) so the body feels like it has weight

Sound

  • I recorded and mixed the creature's voice and footsteps, the doors, and the interface sounds myself
  • Footsteps change with the surface underfoot, and each kind of sound has its own falloff so you can judge how far away something is

Tools and technology

  • Unreal Engine 5 (C++ and Blueprints)
  • Behavior trees and the Environment Query System (creature AI)
  • Instanced static meshes (generated level geometry)
  • UMG (HUD and menus)
  • Blender (models and animation)
  • Adobe Audition (sound recording and mixing)
  • Substance Painter, Substance Designer, and Photoshop (texturing)