Devlog 2: Playable Prototype
Welcome back! Did you survive the first Devlog? If not, fret not, we’ve come up with a different approach this time! The structure will be a bit different. Just like last time, we’ll give you an update on both the art and technical sides. However, the technical section may have been a bit too heavy last time, so we’ll keep it short and concise this time around!
For those of you who did enjoy the deep dive, don’t worry, after the closing thoughts, you’ll still find a more detailed technical explanation!
This week was all about, you guessed it, prototyping! But that’s not all. We also worked on our Art Bible and Tech Document. As for the prototypes, this time we focused on creating a more solid, playable version, something we could easily tweak and experiment with to see if our core game idea wasn’t just feasible, but also fun!
ART
Hey hey, this is Laurens,
I have been working on putting down a basic art bible for this project to get a grasp on how we are gonna do this whole thing, wiiith an example page right here below! (Own images in bible to be added once we have an asset per section ready, for now with imagery found online)
After some fucking around and finding out when it comes to the in game assets, I feel I've found a pretty solid pipeline, Since our primary asset focus will be set on a lot of weaponry that is only viewed from pretty far away, we shouldn't overcomplicate things.
The Characters on the other hand deserve a bit more attention, since they'll be in close ups at times, splash art, and will be bigger on screen.
A pipeline for the enviroment art will still follow. See yall next week!
Prototype
This week, we focused on player controls and fighting — putting together all the basics for a brawler-type game! Let me walk you through what’s been done, the decisions we made, and the ones still left to figure out:
- Jumping
- Dashing
- Shooting
- Knockback and Self-Knockback
- Arena Knockout
- Level Reset
Let’s get into it.
The mechanics
Dylan
For jumping, we’re aiming for fast, high-velocity, high-friction jumps. We want the players to POP, aligning with the fast-paced, action-heavy feel of the game. However, we decided to restrict movement to some extent. Since the jumps are fast, we want to avoid introducing overly high-skill dodging by allowing players to dodge mid-air or pull off unpredictable aerial maneuvers.
That being said, we still want to maintain high mobility, so we opted for omni-directional dashing — meaning players can dash in any direction on a full 360-degree axis. This should help us strike a balance between predictability, skill, and mobility.
That said, we also kept an alternative option: limiting dashes to just left and right for playtesting, so we can compare and see which approach feels better. And so Dashing was born:
Initial Results
For dashing, players can currently dash anywhere at any time. Right now, it’s cooldown-based, but we’ll be tweaking it. During playtesting, we’ll decide whether to keep it this way or switch to requiring players to touch the ground to reset their dash.
The dash itself behaves as expected so far, but the default jump feels too "floaty" for the type of gameplay we want. We plan to tweak it further and, if needed, implement a custom jump system to better match the game’s pace and feel.
Next up — Violence!
Other than the challenge of aiming in 2D space with a 3D character, there isn’t too much to dive into here. It’s simple, press RB and shoot!
Now with Health!
And of course, what’s shooting without health?

And Finally… Ragdolling on Death!
Currently, ragdolling applies a random force, but in the future, we plan to customize it to react to the bullet’s impact force and location, so deaths will feel even more chaotic and satisfying!
Eternal Carnage
Now that we can murder each other, we need a way to reset the level so we can murder each other forever!
Jokes aside, the level reset system is mostly there to make sure we can detect when all players are dead, which will trigger the transition into the next phase, choosing the Chaos Factor.
But that’s a story for another day. 😉

Let’s Make the Combat More Chaotic!
Time to crank up the chaos — let’s add knockback to others and a kickback to the weapon!
Weapon kick:
Perfect! Although it’s a bit exaggerated for entertainment purposes right now, the values are fully tweakable so we can fine-tune them for better customization and playtesting.
Arena Knockout
With the core movement and fighting in place, it’s time to add Arena Knockout!
For now, we decided to let players go off-screen without instantly dying. Instead of just killing players the moment they leave the screen, we opened up the arena and surrounded it with a deadly outer sphere — if a player drifts too far and crosses that boundary, they’re out!
The original idea was to allow players to fight their way back into the arena if they got knocked out. An on-screen indicator would show the player’s position and how close they were to the arena’s edge. This whole system is modular and tweakable and subject to change. However the indicator hasn’t been implemented yet!
With the fighting fundamentals in place, There was one recurring theme throughout all of this — playtesting. This prototype was all about getting the core mechanics working and making sure they were customizable, so we could playtest and fine-tune the gameplay to match our target experience.
To make iteration even faster, we also added an in-game implementation to tweak values directly while playing!

Weapon throw/catch
Alessandro
Let's now work on throwing and catching weapons. The second part of this prototype was already covered for Unity in this post, so we will just need to port it to Unreal.
To do this, we first create a new character: the shooter. His job is going to be to bombard our player at fixed intervals.
Next up we implement all the catching mechanics, giving us the first half of the prototype. It looks like this.
Let's say we don't just want to take it from this *shooter guy*, we want to fire back. The throw mechanic consists of being able to apply a directional force to our currently held item. To give a better directional control, we're first going to map a controller's analog stick using Unreal's Input Mapping Context tool. Let's give it a try.

BUT beware, you can risk hitting yourself in the head!
Wall jumping
For our game we decided to give the players the cache to dodge and make incredible trick shots using the wall jumping mechanic.
Jumping on a wall will stick the character to it and jumping once again will propel the character in the desired direction.
Overview
Dylan
This week, we set out to create a playable prototype featuring our core mechanics, with high customizability in mind to allow for fast and efficient playtesting!
Our goals were to implement:
- Jumping
- Dashing
- Shooting
- Arena Knockout
- Knockback and Weapon Kick
- Level Reset
- Weapon throw/catch
- Wall Jumping
- Picking up and Throwing Weapons
- Fighting with Fists
- Spawning Weapons
- Testing Different Arena Scales
- Easy and Efficient Variable Testing
We managed to complete 9 out of 12 goals. Turns out, documentation for the project took up more time than expected!
Closing thoughts
Even though we didn’t reach our 12 goals for this week, we still made solid progress!
What we accomplished so far already highlighted some design choices we hadn’t fully considered, as well as some important technical and code-related decisions we’ll need to refine moving forward. So...
What’s Coming Next Week?
Next week is all about playtesting and fine-tuning our mechanics to match the desired target experience. On top of that, we hope to finish the remaining 5 mechanics and playtest them as well.
All this work leads up to our ultimate goal for next week — a playable demo! That’s right, next week we aim to deliver a playable demo showcasing our core mechanics!
That wraps up this week’s devlog!
But as promised, if you’re here for more technical details, stick around below. Otherwise — see you next week!
More Technical!
Welcome to the promised deep dive into the more technical side of our mechanics, how they work and how they were implemented.
In the following sections, you’ll also find code snippets to illustrate my thought process and workflow. However, please keep in mind that most of this code is purely for prototyping purposes and is by no means good code.
On top of that, a lot of this code was AI-generated to speed up the prototyping process. I want to highlight this because the code doesn’t follow many of the rules and guidelines outlined in our Tech Document, including one of our most important rules:
NO AI CODE IN PRODUCTION
This is strictly for prototyping, so with that disclaimer out of the way, let’s jump in!
Jumping
Jumping turned out to be pretty straightforward. Unreal Engine already comes with a Jump component built into the Character Movement Component, so all we had to do was call Jump()
when the jump button is pressed and then tweak some values! Here’s an example of how we make sure jumping only happens in a valid state:

Tuning the Jump
We still need to experiment with different variables to find the right feel for the jump, one that fits our fast-paced, snappy gameplay.
That said, even though this built-in system is simple and effective, it’s already becoming clear that it won’t fully deliver the gameplay feel we’re aiming for, no matter how much we tweak the values. Because of that, we’ll likely leave the jump as-is for now, and revisit it later with a custom implementation, once the rest of the core mechanics are solid. Which bring us to the next section Dashing!
Dashing
Dashing wasn’t quite as straightforward, but it didn’t prove too much of a challenge either. There’s always the option of using a dashing plugin, but where’s the fun in that?
For dashing, we considered two main approaches:
- Directional Dash
- Free Dash (Omni-Directional Dash)
Directional Dash
This would only allow the player to dash straight ahead, meaning you could only dash left or right. This restricts mobility and keeps movement predictable, which can be good for balance, but we felt it was too limiting for the high-mobility experience we want.
Free Dash (Omni-Directional Dash)
This option allows players to dash in any direction they want, full 360-degree dashing. This compensates for the restricted jump mobility we’ve built in, keeping movement dynamic and chaotic (in a good way).
We also kept the option to toggle between both systems for future playtesting to see which fits better once all mechanics are in.
With the existing aim mechanics, the actual dash mechanic is as simple as:
Launch the player in the direction they’re looking.
Convenient, right?
Shooting
Shooting turned out to be a lot more troublesome than expected, despite having previous Unreal experience with shooting systems. There were quite a few surprises along the way.
Firing Logic
Getting the player to shoot wasn’t too difficult, just a matter of broadcasting and listening for events tied to the fire button. We opted for a timed function to handle fire rate.
Obviously this code is not great, but that’s what prototypes are for!
One important takeaway was realizing we’d need to differentiate between automatic and semi-automatic weapons pretty early on. Their firing logic was starting to interfere with each other, so splitting them up will be critical when we move beyond prototyping.
Bullet Spawning
Here’s where things got interesting and where I learned something new about Unreal Engine.
No Constructor Parameters
You can’t pass parameters into a constructor when spawning an actor at runtime. This was a bit of a headache. The takeaway from this code snippet are:
- Bullets don’t know anything except their own logic.
All variables like speed, damage, and even sprite/mesh come from the weapon itself, making weapon creation very modular. - A reference to the player character exists in the bullet.
This is costly and inefficient, and something we’ll definitely need to rethink before production. It’s likely that shooting will be reworked into a more event-driven system instead.
Bullet Direction
Originally, we used an arrow component attached to the weapon to determine the bullet’s rotation and direction. This worked — but only in theory.
Since the arrow was in 3D space, it gave the bullet some unwanted freedom on the Z axis. Worse, when we forced it into a 2D plane, the results were segmented and inconsistent, it is likely some information got lost, and shooting felt awkward.
Unfortunately, I don’t have footage of this stage because I replaced it quickly, but here’s the solution:
Instead of using the gun’s arrow component, I pulled the player’s pitch directly (which was already locked to a 2D plane).
This worked perfectly but highlighted two issues:
- Efficiently passing player data down the chain (player → weapon → bullet)
- Animation offsets — the gun’s visual position didn’t always match the actual firing angle.
Here’s a quick visual example:
In the image, you can see the bullet follows the player’s pitch, not the gun’s actual direction. That’s because the current aiming animation is just a quick placeholder, thrown together in about 5 minutes.
The end result:
- The gun doesn’t quite align visually with where the player is actually aiming.
- This will need to be carefully adjusted once animations and aiming systems are more polished.
Knockback
Knockback is handled through a component. Every player has their own KnockbackComponent, and the beauty of this approach is that the component doesn’t care who or what caused the knockback. All it needs to know is:
- How much knockback?
- In which direction?
This gives us nice decoupling and keeps the code cleaner. It also makes it easy to apply knockback from anywhere, whether it’s from a bullet, a punch, or a random explosion.
There’s one extra variable that came out of prototyping:
void UKnockbackComponent::DoKnockback(const FVector direction, const int knockbackStrength, bool isSelfKnockback)
Why isSelfKnockback
?
Turns out, different knockback sources behave better with different approaches.
- For one big push knockback (like getting hit by a bullet or a BIG gun), using
LaunchCharacter()
works really well. - For self-inflicted knockback (like from firing a Minigun),
LaunchCharacter()
has a major flaw, it resets player velocity, causing it to float in the air instead.
The Hybrid Approach
The solution?
A combination of both systems, tuned depending on the situation. This gives us the flexibility to have smooth knockback for both external hits and self-knockback, without messing up player momentum.
Arena Knockout
As you’ve seen in the main devlog, we went with a sphere-shaped boundary around the arena. Players can leave the screen temporarily, but once they fully exit the boundary, they die.
The detection itself is done using End Overlap events on a collision volume surrounding the arena.
(Think of it as a reverse collision wall. Instead of keeping you in, it watches for when you leave.)
Unexpected Problems
Problem 1: Death Handling
When a player dies (exits the arena), we trigger their OnDeath event. This handles the ragdolling of the player and overall "death animation" if you will. Originally the Actor was being deleted after calling the OnDeath event. Destroying the actor immediately caused a whole cascade of issues, so we added a delay before the actual destruction.
We also added a backup death plane under the map to catch any rogue actors falling into the abyss.
Sounds good, right? Well…
Some validity issue arrose. in other words, dangling pointers! Not good!
The temporary workaround?
We decided to leave dead players floating in the void forever (for now), rather than destroying them directly.
Proposed Long-Term Solution
Instead of destroying the player, we could:
- Mark them as dead.
- Disable their logic.
- Teleport them to an offscreen "graveyard" area where they can wait in peace for the next level.
This would avoid most of the dangling reference and camera issues.
Problem 2: The Biggest (and Weirdest) Issue
Overlap Event Firing on Level Reload
This one’s still a bit of a mystery. When we reload the level (or load a new one), the OnDeath event fires again for players being destroyed during the transition causing a crash because of deleted PlayerController Handles.
Why? good question! No idea!
My best guess is as follow:
I even tried adding validity checks before calling the event which leads me to speculate that the components get destroyed first leaving the player in a "valid" or "existing" state. But the overlap event still triggers before the actor fully dies.
Temporary Fix
For now, the hacky fix is:
Manually find and destroy the DeathSphere before we reload the level.
It’s ugly, but it works for now. Definitely something we’ll revisit before moving to production.
Final Words
That wraps up this week’s Technical Deep Dive! Hope you enjoyed following the chaos. If you have any questions, comments, or better ideas than leaving dead players to float in existential limbo, let us know!
See you next week!
Files
Get [Group26]Brawlstorm
[Group26]Brawlstorm
Status | In development |
Authors | Diji69, SamDK, Mkyv2210, InquisitiveOctopus, alessandromanzini |
Genre | Fighting |
Languages | English |
More posts
- Devlog 5: Square 2?25 days ago
- Devlog 4: Back to Square 1!32 days ago
- Devlog 3: Game Demo!39 days ago
- Devlog 1.2: Aiming & Ragdolling52 days ago
- Devlog 1.1: Item catch prototype53 days ago
- Devlog 1: Research & Prototype54 days ago
Leave a comment
Log in with itch.io to leave a comment.