Hallowfall

Introduction

Hallowfall is my most recent project, a 2D roguelike inspired by soulslike games. I chose the roguelike genre because it’s well suited for a solo developer. Its reusable content and system driven design present both creative opportunities and meaningful programming challenges. This project has been the perfect opportunity to establish the groundwork for core systems. My initial goals were to refine existing mechanics, improve code maintainability, and build a scalable foundation for roguelike gameplay. From procedural world to diverse abilities and adaptive enemy AI, I'm hoping that one day the game grows into a rich and challenging experience.

Player Architecture

To handle growing complexity around the player character, I designed a scalable, state driven architecture centered on a Finite State Machine (FSM) managed by a PlayerController. The system emphasized clean separation of concerns and event driven communication, ensuring that each behavior existed in an isolated state while remaining decoupled, extensible, and responsive.

Procedural World Generation System

The Procedural World Generation System is implemented using a dynamic zone based architecture, where the game world is divided into manageable zones that are procedurally generated, activated, and deactivated based on player proximity. Each zone is responsible for generating terrain, props, and gameplay elements according to defined profiles and procedural rules. This system was developed to optimize memory usage, ensure seamless exploration, and allow for unique, replayable game environments. The core idea revolves around a ZoneManager for high level management and a ZoneHandler for zone specific generation.

Enemy AI System

The Enemy AI System mirrors the Player Architecture in its overall design, built on a foundation of Finite State Machine (FSM) control, event driven communication, modular components, and isolated systems. The key difference is in the way state transitions happen: enemies react to real time data such as player proximity, health thresholds, or environmental conditions, rather than relying on direct input handlers like the player. This makes enemy behavior responsive and adaptive.

Enemy Pathfinding

The Enemy Pathfinding has evolved with the game. I felt it deserved a dedicated section to explain my thoughts and efforts behind it. Initially, I used the built in Unity NavMesh to handle enemy pathfinding. However, after completing the first iteration of the World Generation System, I realized that NavMesh would need to be baked at runtime dynamically, causing noticeable performance issues. After exploring some workarounds, I developed a custom pathfinding system using Flow Field Pathfinding. By modifying my CellGrid system from the World Generation section, I successfully integrated the new pathfinding solution.