I developed this system for a project during my 2nd year at Futuregames Stockholm for a course in Advanced Game Design. The assignment was to design a boss-fight in a group, and we were four developers in this group. While the rest of the group designed other aspects of the boss-fight, I designed this system. After the course was finished, I decided to recreate my system in Unity using C#, as a programming exercise.
3 Weeks - August 2025
Technical / Systems Designer
Unreal Engine 5.6, Blueprints, Unity 6, C#
Solo developed
Initial Concept and Prototype
The initial concept for the boss fight was to make a 3D Bullet-Hell Boss Fight, taking inspiration from games such as Returnal and Enter the Gungeon. We also decided that we wanted a mostly fixed pattern of attacks, to better tweak the challenge and reward memorization of the attack patterns.
I started quickly prototyping and designed a simple projectile system, a parry mechanic, and an action/attack system. The projectile system at this point only supported the projectile moving in a determined Vector Direction, which in turn would be the basis for the action/attack system and the parry mechanic. The action/attack system determines how many projectiles to spawn in, their position, and their direction, and the parry mechanic reverses the projectiles direction, causing them to move the opposite way.
The GIF to the right is an example from the first week of development.

Action/Attack System, Design and Implementation
The Action/Attack system came as a solution to a problem. This project was only supposed to be a simple prototype, but I wanted to be able to tweak the Attack Patterns timing and allow other designers to work on it without needing to do additional scripting.
The Action/Attack system takes a Data Structure (struct) as an input, which holds all the necessary variables for an attack. It then interprets those values, and performs the attack with the specified timing and delay defined in the struct. These structs are stored in data-tables for each of the phases of the boss-fight. When the boss transitions to it's next phase, it finishes it's current action/attack, and then loads the next phase's data-table.
The most central variable in the struct is the "Action Type" Enum. Depending on it's value, the Boss executes different functions to perform the attack. The Arc Attack, for instance, would have the Action Type of "Arc". The boss would then execute it's Arc Attack logic, which for Vector Math purposes is very different from a Shotgun Blast Attack.
Some values are universal in the struct, such as the "speed" value. Certain values are however only used in specific attacks, and those values are stored in a separate struct so as to not bloat the struct with too many unused variables taking up space. The Arc Attack, for example would use the universal variables for defining it's projectiles' speed and damage, but uses it's own specific variables for calculating the Arc's angle and how many Projectiles to spawn in the Arc.
Let's go through an example of the logic flow.
The Boss loads in the correct Data-Table for it's phase. Then it starts looping through the defined Structs. The first attack in this example is a Wall Attack (projectiles stacked on top of each other in a grid pattern). The Boss sends the Struct through a function to determine it's Action Type, and the Switch Case inside calls the Wall Attack event with the Struct as an Input. Then the Projectiles are spawned in with the specifications inside the struct, and is sent forward. The boss then delays for the determined time, and continues to loop through the Data-Table.

The Attacks
For this system I designed and implemented several different attacks that affect the player in different ways.
The Arc Attack shoots X amount of projectiles at the player in an arc, with slight delay between projectiles.
The Wall Attack shoots a grid of projectiles at the player assembled by Rows and Columns.
The Shotgun Attack shoots X amount of projectiles at the player with a random variation (determined by a Spray Value in it's struct)
The Slam Attack doesn't shoot a projectile, but it slams the Boss down into the ground X amount of times, sending out a shock-wave every time.
The Meteor Attack shoots X amount of projectiles upward in slightly random directions. These projectiles are different, and they fall to the ground. When they land they send out shock-waves.
The Simple Attack shoots a projectile directly at the player. This was the first attack I prototyped, if you can believe it.

Blueprints of the Meteor, Shotgun, Arc, and Wall Attack Patterns
Boss Action Loop
Rework and Refactor into C# (Work in Progress / On Hold)
After this project was finished, I started remaking parts of the system in C# for Unity. The reason behind switching engines is that I wanted to remake the Character Controller into something more custom, and I wanted to write a Finite State Machine in C# for it.
This project has since been put on hold, and I have yet to finish it. My plan is to refactor the C# action/attack logic from asynchronous methods to Unity's coroutines, that are more thread-safe and less prone to cause bugs and issues. One slightly catastrophic bug I encountered while testing was that projectiles kept spawning in the scene even outside of runtime. This would not happen with coroutines, but can definitely happen with asynchronous methods and operations.
Reflection
This system was fun to develop. If I were to make it again, I would probably collapse more logic inside of Functions and Macros instead of putting it in the Event Graph, and I would rely less on helper variables for the Event Graph loops. I would also design an Object Pooling system inside a helper class to avoid the performance hits from larger attacks and intricate patterns.
If I continue on this project Unity, I would incorporate the previous teachings and also try to write a custom tool with a GUI for creating attack patterns.



