Infinite Runner
An endless runner built in Unreal Engine 5 — my first shipped Unreal project.
Status: Prototype complete — polishing for itch.io release
Overview
A fast-paced side-scrolling endless runner where the player dodges, slides, and jumps through procedurally generated obstacle courses. The difficulty ramps continuously; the goal is to outlast your previous best distance.
Motivation
After two years of Unity, I wanted to learn Unreal Engine. An infinite runner was a scoped enough project to learn the engine without drowning in complexity:
- Unreal C++ basics — actor lifecycle, components, input handling
- Procedural generation — how to make levels that never repeat but always feel fair
- Difficulty curves — mathematical models for scaling challenge over time
Technologies
| Tool | Use |
|---|---|
| Unreal Engine 5 | Engine |
| C++ | Gameplay systems |
| Blueprints | Visual scripting for prototyping |
| Niagara | Particle effects (dust, sparks) |
| Git + GitHub | Version control |
Screenshots
(Screenshots will go here — static/img/infinite-runner/)
Features
- Procedurally generated obstacle chunks (no two runs identical)
- Four movement mechanics: run, jump, double-jump, slide
- Increasing speed over time — from comfortable to frantic
- Combo multiplier: survive consecutive obstacles without slowing
- High score system with local leaderboard
- Replay viewer — watch your run back at the end
Architecture
GameMode
↓
LevelGenerator → ChunkPool
↓
PlayerPawn ← InputComponent
↓
MovementComponent
↓
ObstacleDetector → GameMode (death event)
ScoreManager ← TimerComponent
↓
LeaderboardSave (SaveGame)
Key design decision: Chunk-based generation. The world is built from ~30 handcrafted chunk assets. The generator selects and sequences them using a weighted randomizer that adjusts weights based on current difficulty — harder chunks appear more frequently as distance increases.
Interesting Problem: Fair Procedural Difficulty
Problem: Pure random chunk selection produced runs that were unfair — sometimes brutal at the start, sometimes easy 5 minutes in.
Investigation: I graphed the difficulty profile of each chunk (obstacle density × required reaction time). Then I modeled the intended difficulty curve as a function of distance.
Solution: A DifficultyBudget system: each chunk has a difficulty score (1–10). The generator maintains a rolling 5-chunk window and only selects a new chunk whose score falls within [target ± 1.5]. Target is derived from distance via a smooth exponential curve.
Outcome: The game now feels consistently fair at the start and consistently difficult at high distances — without the generator ever repeating the same sequence.
Development Timeline
| Phase | Duration | What happened |
|---|---|---|
| Unreal basics | 2 weeks | C++ setup, actor system, input |
| Core movement | 2 weeks | Jump, slide, double-jump, death |
| Chunk generation | 3 weeks | Pool, sequencer, difficulty budget |
| Score + leaderboard | 1 week | Save system, UI |
| Polish | Ongoing | Particles, camera shake, juice |
Lessons Learned
- Blueprints first, C++ when stable. Prototyped all movement in Blueprints, then ported to C++ once the design was locked.
- Chunk design matters more than the algorithm. The generator is only as good as the chunks it draws from. Spent 40% of generation time tweaking chunk content, not code.
- Unreal's
SaveGamesystem is simpler than I expected. JSON was my first instinct; the built-in save system handled everything I needed without extra code.
Future Improvements
- Mobile controls (swipe gestures)
- Additional biome themes (snow, desert, space)
- Online leaderboard
- Power-ups (magnet, shield, score boost)
- Accessibility: adjustable speed cap
Play the Game
➡ Play on itch.io (link active at release)
→ GitHub Repository (source code)