HomeProjectsAbout

Procedural City Generator


Tags: Unity, C#, Procedural Generation, Open World, Solo Project

Start: November 2023

Type: Solo project

Project Duration: 5 months


Summary

This project was my first deep dive into procedural world generation. I wanted to see how a city could build itself dynamically in Unity, using layered images to place roads, buildings, and water. Along the way I learned how to manage large-scale worlds, implement a floating origin to keep positions stable, and deal with performance bottlenecks during regeneration. It taught me a lot about balancing creativity with technical limits, and how to make complex systems feel responsive and believable.

Details

This was one of my first experiments in creating large, dynamic worlds. I wanted to see how far I could push procedural generation inside Unity while keeping it readable and modular. The project started in Godot but later moved to Unity for its stronger profiling and debugging tools. The generator reads layered images to decide where roads, buildings, and water should go. Each layer has its own interpreter script, allowing me to tweak parameters individually and see changes in real time. Roads are generated using a Binary Space Partition (BSP) system that helps define blocks and intersections, while building height is derived from a grayscale heightmap. To keep everything stable at large scales, I implemented a floating origin system that recenters the world as the player moves. Performance was the biggest challenge. Regenerating chunks caused heavy frame spikes, especially at higher detail levels. I mitigated some of this by spreading out instantiation over multiple frames, which reduced stutter but introduced some visible pop-in. If I revisit this project, I’d like to explore asynchronous generation and object pooling to keep things smooth, and perhaps use GPU instancing or impostors for distant geometry. Despite its rough edges, the project gave me valuable insight into how procedural content can be streamed, how data and design constraints influence performance, and how to balance technical ambition with practical iteration.

Source Code

Project Link