| Context | Academic team project with stakeholder direction |
| Role | Game programmer – Project Coordinator (planning & deadlines) |
| Team size | 4 |
| Tools | Unreal Engine – Blueprint scripting – Git – Trello |
| Duration | 11/2024 – 02/2025 |
View the sourcecode on GitHub: [https://github.com/SamLeguijt/AbyssalSurge-Backup]
*Note: This is a backup of the repository due to the orginal on GitLab having visibility restrictions
Project overview
This project is a team-based first-person shooter developed in Unreal Engine over the course of 10 weeks. Inspired by DOOM, the goal was to create a fast-paced combat experience while having full creative freedom over the game’s mechanics, world, and scope.
Abyssal surge combines the fast paced gameplay of DOOM with ability-driven combat inspired by Witchfire, set in a dark-fantasy world. Players make use of various weapons and abilities to defeat different enemies while navigating through the world using their movement mechanics.
Responsibilities
As group, we were all responsible for designing the core game loop and it’s mechanics. Besides, each member had their own responsibility as developer to contribute equally. Additionally, I took on tasks related to our team process which naturally evolved over the course of the project.
Overall, my main responsibilities throughout the project included:
- Brainstorming and giving feedback on design elements such as mechanics, narrative, scope and overall project goals
- Getting to know Unreal engine and understanding the basics of blueprint visual scripting
- Contribute to the development process by working on smaller individual tasks
- Keep track of upcoming deadlines and important deliverables; making sure our team was prepared for these moments
- Creating a weekly goal and corresponding planning
- Nudging team members on their progress with their tasks; stepping in or communicating to the team if assitance was needed
Key contributions
For this project, I mainly worked on the design and implementations of the enemies within the game. I designed three different, rather simplistic enemies with their own behaviour and worked on implementing them using built-in Unreal engine features. I focussed on a data driven implementation for the enemies, where enemies can be configured at a central place without having to make changes to the blueprints themselves.
To summarise my contributions:
- Designed and implemented a resuable BehaviourTree all enemies use, consisting of 3 basic subtrees; Attack, Engage, Patrol
- Implemented seperate BehaviourTasks for each attack and movement strategy
- Designed and implemented an Enemy blueprint that is used for all enemies, handling damage,
- Implemented an enemy data table to configure enemies; Mesh, animations, SFX, attack/movement/engage properties and other settings
- Implemented a reusable spawner to spawn enemies on a delay and in waves (adjustable)
- Implemented three enemies, including SFX and animations:
- Melee skeleton that chases the player and attacks from close range
- Barbarian that lunges towards the player and attacks upon landing
- Ranged mage that fires projectiles to the player’s expected position and teleports away when getting close to the player



Reflection
Looking back on my implementations for the different enemies, I have mixed feelings. Overall, I’m happy with the data-driven approach and how easy that makes adding a new enemy. Encapsulating attack and movement behaviours inside individual BehaviourTasks allows for flexibility and extensibility without touching the core blueprints. The three implemented enemies are a solid showcase of how this system can be used to create a set of varied enemies, where adjusting the exposed properties allows for easy configurations and making changes to exisiting enemies.

However, there are a number of things I would do different next time. For starters, I would spend more time learning Unreal Engine’s built in features and how they can and should be used. Although I used a BehaviourTree in combination with a Blackboard, I did not fully capitalise on all its capabilities and benefits. Taking my time to understand how and how not to use it could have been beneficial to the overall codebase. Furthermore, the current implementation with the earlier mentioned three subtrees limits the extensibility and requires more exposed properties to adjust and add new behaviour, something I already noticed when working on the lunge attack.
Besides Unreal’s features, I would use my knowledgde of code architecture and programming design patterns to design a system with a better overall architecture, where users are not limited to using a single blueprint. Additionally, I would seperate behaviour and data more instead of creating a single data table with all configurations settings of an enemy, as seen in the image on the right.
At the time, exposing all properties inside this data table seemed like a good approach to create a modular system where values can be easily adjusted. However, looking back I’ve realised the flaws with this mindset. While exposing many properties allows for full control and being able to adjust everything, it can add a lot of unnecessary complexity where others are now required to understand every property and how it affects the outcome. Although documentation can help, being mindful of the tradeoffs between flexibility and usability is a key takeaway I have learned from this.
Additionally, a more obvious flaw with the implementation of this specific data table is using enums, booleans and other values to decide the use of specific attack and movement behaviours. For instance, in the current implementation, the attack an enemy uses is decided by the ‘AttackType’ property inside the datatable. When set to Lunge, the LungeData struct is used to execute the desired attack. This approach heavily restricts extensibility, because a different form of attack now needs to be added into the Enum, a new data struct for that attack needs to be made, and the data table needs additional rows to include the new data struct. A far better approach would be the use of a strategy that encapsulates an attack inside its own behaviour and exposes the properties it uses. This data table could then store a reference to one of the strategies.
Overall, this implementation was a good learning experience for designing flexibile, scalable architecture. Within the time constraints, scope and experience with the engine this worked well and was an usable solution for out project. In future projects however, I would aim to make more use of architecture principles in combination with the engine’s built in features to design a more scalable and flexible system.
Retrospective
One of the primary challenges during this project was understanding Unreal engine and Blueprint scripting. Being completely new to the engine, it was overwhelming at first. I decided to jump straight into the blueprints and encouraged myself to just start small and see where it goes, something I have learned from previous projects I should just do when getting stuck. This worked, but looking back, wasn’t the best approach for me. Because there are many resources available to help beginners with the engine, next time I would take a step back and work my way through the basics. This would help me get a good understanding of the core concepts, where I can delve more in depth in certain topics that are relevant for the project at hand.
As project coordinator, I enjoyed being in a leading position where I would be in charge of managing the planning and keeping the team on track. Creating weekly goals and discussing individual tasks with the team was very motivating, over time I became more comfortable in taking initiative and checking in on progress with others.
At the same time, I noticed I can sometimes be too rigid and structured in how I approach these coordinating responsibilities. Checking in on others often felt overly focused on the tasks instead of just a check in. In future projects, I would like to work on being more confident and natural in my communication and interactions with others, approaching others in an open and friendly way instead of feeling hesitant or overly formal.
Not only will this make me more comfortable in a leading role, but also help build a stronger trust within the team. I believe a good leader is someone who you can trust and rely on while having a good connection with. Being able to naturally and confidently initiate conversations regarding work is something I see as an important step for me to be able to be in a leading and coordinating role.
