✦ Longform Writeups ✦

In retrospect, it’s funny that I wanted a feature so bad that I was willing to reverse engineer a game with no modding documentation and no prior personal modding experience.
I started this whole thing because I wanted custom playlists. UNBEATABLE has rudimentary song filtering, but it’s limited to a few preset categories. I wanted a custom category where you could add and remove songs freely.
Unity, the engine the game is built on, was new to me and I had zero experience with C#. Yeah, I may have done a college course on .NET programming, but that was basic af.
I would say my perseverance boils down to two things. One: my absolute love for the game. I didn't mind staring at absolute gibberish code for hours if it means I'm contributing to something I care deeply about. Two: said gibberish was not obfuscated at all. It might not have had any comments, a proper file structure, or a debugger, but at least the variable and class names were original. It’s the dual blessing of being built in Unity and running on Mono.

Playlist mod in action
JeffBezosControllerwants to have a word with you. The game's real-time UI state controller... I think?
It took me a good two to three hours of just staring at the code to figure out the relationships between the files. The language was easy enough. Just plain old class based strongly typed syntax. But the hard part was figuring out which file did what. I didn't have access to a debugger, so I didn't know which scenes were handled by which controllers. To my luck, the D-CELL Games devs did an amazing job naming the classes. But that doesn't mean the occasional ritual to the decompilation devil wasn't necessary.

Screenshot of DnSpy. Too scared of the IP police to show code
public void FuckedCoroutineFix() { this._thisCantKeepWorking = 1 }now ain't that cursed?
Many times I’d decompile a class with dnSpyEx, edit a method, recompile it, and everything would work perfectly. But if I tried to edit that same method again and hit recompile, the tool would throw a C# compilation error.
Surprisingly, the error wasn’t even on a line I wrote. It was on one of the game’s original lines that compiled just fine five minutes prior. So I’d revert the file, make both changes at once, and it would compile perfectly. The truly cursed part is how the errored line was identical to the one that failed before.
I’ve come to the conclusion that dnSpy is possessed by some kind of demon, and the only way to appease it is to make all your changes in one go. The fucked up part is that even then, it isn’t consistent. Sometimes the demon would let me make many consecutive changes before crawling back out of hell.
Fact that
AustinsThrowawayQuicktimeCrestActionis far more important thanThankUAustinn
One of my biggest challenges was figuring out how to save the playlist data. My first idea was to hijack the existing save system. But if the game updated and that system changed, the mod could fail catastrophically and corrupt the player's save file.
Luckily, the game already splits its save data into many smaller files. So instead of hacking the existing system, I extended it by adding a brand new save file. That way, if an update ever nukes everything, all the player is left with is a useless save file they can safely delete without losing their progress. Having this file be a part of the existing save system meant it would be uploaded to Steam Cloud, making the mod work seamlessly across multiple devices.
I also stumbled upon a slightly concerning realization while implementing this. Steam doesn't vet the files being uploaded to their cloud. I noticed that if I nuked my custom save file while the game was closed, Steam would just quietly resurrect it the moment I launched the game. You literally cannot permanently delete the file unless you do it while the game is running. I'm not smart enough to fully map out the exploitative potential for malicious modders here, but it’s definitely an interesting and slightly terrifying quirk. I hope Steam scans the files for viruses, fingers crossed lol.

Screenshot of save file
"It's like when you have huge boobs and try to look at your feet. Can't see your feet."
~ Clef, one of game's protags
I was a naive child to think my inline dnSpy edits would easily translate into a fully-fledged mod. It’s true I had a working edit, but that didn't make it distributable. I was a single game update away from all my changes getting nuked.
For this, I had to learn a whole new paradigm of modding: using a mod loader (MelonLoader) and a method patching library (Harmony).
I got caught in so many problems translating my existing edits. I was mainly bugged by methods where I only wanted to change a single line. With Harmony, I sometimes had to rewrite the entire method just to change that one line. It was a nightmare to translate all the existing method calls and private variables, especially since the original variables were often read-only.

MelonLoader template for Visual Studio
Too bad
class HahaHehe : MonoBehaviour { 40 lines... }isn't used by the game at all.
I learned more about how Unity and game dev actually works in these two weeks of breaking things than I did in my entire college program. If you want to use the mod, the link is below.
For other devs looking to mod UNBEATABLE, the source code's on GitHub. I've commented the important parts, but feel free to ask me any questions. Be warned that I have no idea if there are better ways to do things. Just don’t blame me if the decompilation devil follows you home k.
Link to mod: https://github.com/blekmus/unbeatable-mods
Email me: dinil@pm.me
Discord: blekmus
All logos and other assets credited to D-CELL GAMES and their respective owners.