Posted March 10, 2025 by Diji69
#2.5D #Action #Brawler #Brawlstorm #Coop #Couch #Couch-Coop #Devlog #Fighting #Item Catching #Prototype #Prototyping #Unreal
Welcome to the third week! Short intro this time around, we'll adopt last week's structure as it was well received. Lots to talk about today so let's get into it straight away!
Laurens
Hey hey!
From the artists side we got some new thingies to proclaim, we have found a (relatively) cohesives style! Shape language, color schemes, screen filters, etc, are now all working together to create a retro, PS1 esque feel, but put into a modern jacket. This has been the result of the artbible and shader tests. (Examples below)
We can't really show the entire art bible at the moment, but we will be able to give more detailed updates and examples soon since we will be hitting production next week! Enviroments and shader work from Mathis and characters and props from Me,
That's it for this short art section, onto the expansive (And impressive) work from our programmers!
Dylan
Following last week's progress, we aimed to deliver a playable demo this week. To recap, last week we introduced:
A lot was completed this week:
Following last week's work, a couple of issues needed to be adressed before pressing on. Let's tackle them in order:
These fixes smoothed out gameplay, making playtesting faster and more reliable. With all of that out of the way, let's tackle the new additions.
For the prototype, a simple nametag was added to each player. While this helps with identification, it isn't an ideal solution. The names are too similar, requiring a brief search to locate your character. In the future, player differentiation will be improved with distinct outlines and textures, allowing for instant recognition at a glance!
The arena knockout system was completely reworked. Previously, a sphere collider was used to detect when players strayed too far, instantly eliminating them. However, this method was both problematic and not quite what we wanted.
This allows for more precise detection, ensuring that players who step outside the play area (the Dead Zone) have a brief timer-based window to return. If the timer runs out while they’re in the Dead Zone, the player is eliminated.
To enhance clarity, an on-screen indicator was added to track the player and visually represent the time remaining. After some quick math and testing, the initial prototype result was as follow:
Later iterations refined it further, ensuring that the indicator updates properly and disappears once the player is eliminated.
The initial play space was too small, so an option was added to adjust the camera distance for playtesting.
After experimenting, we settled on a balanced distance. Large enough to give players space to move, but not so big that fights became a game of tag.
Bullet behavior was refined to feel more natural:
However, this tweak inspired a new weapon idea, the Bounce Gun! Instead of disappearing on impact, its bullets ricochet off surfaces, creating chaotic battlefield dynamics. The changes will be refelcted in later section with other gifs! With the visual aspect done, we can finally tackle having a playable game!
Now for the big one, the core game loop. The goal was to create constant action with no downtime, aligning with our target experience.
The loop, originally designed by Sam and refined further by myself, follows this structure:
To keep things exciting, players can even fight each other during the podium phase!
Chaos Factors! Yes indeed, Sam is in charge of a gameplay mockup so stay tuned!
And finally, after a few rounds… a winner is declared! After some quick mockups, the prototype podium was born
completing the full gameplay cycle.
From start to finish, players are always in the action, fighting to the death until a winner emerges. But with the foundation set, it was time to add more mechanics...
Previously, we discussed implementing custom jump mechanics, but due to time constraints, we opted to tweak Unreal Engine’s default movement component instead. By adjusting key variables, we achieved a jump that felt snappy yet slightly floaty, while still allowing airborne control.
It’s not perfect, but it works for now, so let’s move on to enhanced violence!
Melee combat is a core mechanic, after all, this is a brawler, not a shooter. To make melee combat feel natural:
With that, unarmed combat was born!
But punching while holding a weapon doesn't feel right, does it?. Naturally, the next step was throwing weapons. However, before we could throw weapons, we needed a way to pick them up, and to pick them up, we first had to spawn them...
Ahhh there we go, weapons now rain down onto the battlefield, as if hurled by an unseen overseer eager to escalate the chaos. While the timing of weapon spawns still needs fine-tuning to feel less predictable, the core system is in place.
With weapons now littering the stage, players need a way to grab and wield them. What good is a battleground full of weapons if no one can use them?
Perfect!
Now, with a simple pickup mechanic, players can seamlessly transition from punching to gunfire the moment they grab a weapon! So let's add the ability to throw them!
Right now, throwing only discards the weapon, but we’re working on:
With this, every discarded weapon could become a deadly projectile leading to even more chaotic and dynamic combat.
This week, we aimed to deliver a playable demo of the game! Most core mechanics made it in, with only minor adjustments and missing features left to be implemented.
Rather than repeating what’s already been covered, here’s what’s still left to complete the game:
We promised a demo, and we delivered! While far from perfect, it proves that our core gameplay is fun and with more time and effort, it can be fun!
If you’d like to try it for yourself, a link to the demo is attached to this post!
This week also marked the finalization of our design decisions. With the team having a clear vision of the game, we can now move into full production starting next week.
Next week, we’ll be presenting our demo to our supervisors. If they see its potential, we’ll transition into productio, starting from scratch to develop the game properly with all systems in place.
That means our artists will finally get to shine, bringing the game’s visual identity to life!
That wraps up this week’s devlog! If you’re here for more technical details, stick around below. Otherwise see you next week!
Just like last week, let’s take a deeper dive into our systems and mechanics—what worked, what didn’t, and what we learned.
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!
Not much to say here, writing quick and dirty code (especially AI-generated code) comes with bugs and unexpected behavior. Still, we managed to fix most of them to keep development moving.
One notable bug involved player colliders staying in the world after ragdolling. Since player characters use separate physics bodies for ragdolling, the collider remains active even after the player is knocked out.
At first, I disabled the collider when a player entered ragdoll mode. Simple, right? Well… no. Disabling the collider meant that the collider would fall through the map. While that might seem fine but inefficient at first, Unreal Engine has something called KillZ.
KillZ is Unreal Engine’s death plane, anything that drops below the specified Z value is automatically destroyed. That meant if the collider fell through the map, the player would be deleted entirely.
Lowering the KillZ value I hear you say? Unfortunately it wouldn’t fix the issue, just delay it until the player fell further. Instead of disabling it entirely, I moved the collider below the map, out of the way, but still existing.
This fixed the issue of the collider being in the way! And so I used a similar method to handle the player’s mesh falling out of the map, ensuring it gets teleported somewhere safe instead of being outright deleted. To avoid the player 0 being destroyed and messing with the camera.
For assigning player nametags, I opted to handle it through the game mode. Since the game mode creates players and controllers in a consistent order, I added a short delay to ensure all players existed before looping through them and assigning names in order. This works for now, but relying on Unreal’s consistency in assigning controllers and creating players in the same order isn’t ideal.
For production, my plan is to shift this responsibility to the controller itself, allowing it to assign a name to the player it possesses instead. This approach would make the system more reliable and independent of any potential inconsistencies in Unreal’s player creation process.
As mentioned earlier, the arena system was completely reworked. Last week, I talked about how the OnDeath
function was being triggered when reloading the level, this issue is now resolved with the new system.
The new approach uses overlap events to start and stop a timer:
OnDeath
is triggered.
This method is much simpler than the previous system and eliminates the major issues we ran into before.
To help track off-screen players, I implemented an on-screen indicator. The logic for this was entirely done in Blueprints, and the indicator itself is a simple widget containing an arrow. Each player gets their own indicator when the game starts.
This implementation was heavily inspired by a video from Verter Construction, but I simplified certain steps based on our needs. It's also important to note that all of it was done in the tick function but it can all be moved to an event based sytem, saving on precious frames. Here’s a breakdown of how it works:
This streamlined method provides a precise and reliable off-screen indicator without unnecessary complexity.
There isn’t much to add regarding map scaling, bullet adjustments, game loop, or jumping. Jumping was simply fine-tuned using Unreal’s built-in variables. While it’s not exactly what we want yet, it’s close enough for the demo.
With that, let’s move on to Punching!
We already had an existing attack system, all we needed was to add functionality for unarmed combat. This was done using a simple boolean state to check whether the player had a weapon or not.
For the actual punching mechanics, we used a mix of Blueprints and C++.
We started by assigning a sphere collider to the player’s hand and binding an overlap function to it.
OverlapAll
.
The next step was handling the broadcasted event in Blueprints.
ResetPunch()
.
ResetPunch()
(handled in C++) unlocks the ability to attack again.
While a "Do Once" node is included, it’s technically redundant—the event cannot be triggered again before ResetPunch()
runs. But having a safeguard in place doesn’t hurt.
And with all that we have Punching! But there’s another potential approach that might be more efficient: tracing the animation using animation events. However, for now, our current method works perfectly.
One notable advantage of our setup is that, because the animation montage plays before pitch adjustments, we can blend the punch animation dynamically, allowing attacks on a full 360-degree axis.
For now, I’ll skip talking about the weapon pickup and throw mechanics since they’re still in a basic state and not fully implemented. Right now, they simply attach and detach weapons to the player while toggling collision and physics.
That wraps up this week’s devlog!
I Hope you enjoyed this deep dive. If you have any questions, comments, or better ideas, let us know!
See you next week!