Thursday, May 20, 2021

Project Breach #6 - "The Demon Update"

 Project Breach #6
"The Demon Update"

The Transformation
Its been over a month since my last update and to say a lot has happened would be an fairly massive understatement. Between then and now I published a video titled "The Dangers Of Being Public" (link here), in which I said the following:

"I’m not opposed to pivoting a game's direction if I feel it’s necessary. With the upcoming demo for Project Breach, I feel that some people might misinterpret this. But hear me out. That's the whole point of a demo, to figure out what's fun, what works, and what doesn't. If it turns out that controlling pawns RimWorld style isn't fun for a tactical game, then I see nothing wrong with changing the game direction or even changing it entirely. The cool thing about building everything the way I have is that its all been built very generically, which means everything I've made applies to all sorts of different games. If I decided the game was to be an RPG or a survival horror, nothing I've made so far would really need to change to accommodate that. I have an armor system, I have a weapons system. Most games would benefit from these things. No work will have been lost. The map editor, weapons system, even enemy AI will be just as useful on any other project as it will be for this one."

I've often said "I've been making an engine not a game", but it was only while making that video I realized I had never said it online. Even builds of the game refer to it as "Perlinia Engine 3".

I kept working on the game but it wasn't feeling any closer to being fun to play. I kept thinking that a tactical game like this just doesn't work with RimWorld controls because you need more precise commanding than that. So I was faced with three options:
  1. Scrap the engine: It sounds unbelievable but after 3 months of work and the game still feeling like it wasn't coming together, this was tempting. Also the fact that I was working on a 2D game instead of one of those beautiful 3D ones I see other indie developers posting on Reddit. But I knew in my heart that the problem wasn't the engine itself but rather that the idea just wasn't working, so I was dedicated to using this engine no matter what.
  2. Redo the controls: Maybe "A Rainbow Six Siege style game but top-down with RimWorld style controls" just doesn't work. But perhaps with another control system it would?
  3. Pivot the game: What if the player controlled a pawn like a normal person instead of an RTS? But leave all the other programming the same? It'd take me awhile to program all new systems for the player to use (I don't want them actually controlling a pawn, just controlling a body with systems similar to a pawn), but it just seems like it'd be more fun.
Any of these options was a major dedication that would require lots of work. But in the end, I went with #3 and I'm so glad that I did.

I started off creating a sort of horror-feeling map where you moved slowly and had very limited ammunition but I quickly realized that I wanted something more like a power fantasy.





I also realized that the existing weapons & enemies were definitely balanced for an RTS-style game and not for one where you were controlling a player. So I deleted all existing weapons and enemies, grabbed some demon textures I had laying around, and made a demon map. It was insane how well it instantly worked. It only took half a day to program a new AI script for the demons to use, a ranged demon enemy, a weapon for the player to use and a map to test it all on. And after that went so well, I worked on the map some more & added a melee demon enemy, and here we are:







Player Body
It took about half a month to program a body for the player to control that had all the same systems as a pawn like equipment, inventory, visuals, combat, movement, health, a new camera and more. I could've potentially just had the player control a pawn as they already existed, but I wanted the player to use completely separate systems so that way they could be changed & polished to better suit a player without effecting pawns. This has meant I've been able to more finely polish player movement & combat than what would otherwise be possible & I think that the positive feedback from testers has shown that it works.

New Pawn AI
I'm proud of how the tactical AI I programmed in the last update turned out. There are still some problems with it but overall it works really well. But enemies that hear gunshots, investigate, take cover, etc. just doesn't match a game about running around killing demons. I remember watching an Extra Credits video (link) about developing AI that best suits the game which sometimes just means having a few simple AI rather than 1 complex AI system. So I thought I'd do just that, after all, the enemies in DOOM felt fun to play against and they boiled down to "Wander in place, chase the player where we last saw them & attack the player when we have sight". So I created my own pawn brain to mimic those behaviors. 

They don't wander yet because after just implementing the last 2 they already felt more fun to play against with this new style of game. This less complex behavior also means they're easier for the CPU to handle. I didn't delete the old pawn brain so I or any modders can use it in the future, I'm glad I had the foresight to write the system in a way that supported multiple brain types!

UI
Most of this speaks for itself from the previous screenshots. There's a new player UI, weapon UI, and game cursor. But something I haven't shown yet is the engines new error screen:




Although not all errors are going to be so straightforward. Sometimes you just mistyped something in the mod file, in which case you'd get a generic JSON error. But at least this error screen tells you which script you made the mistake on:




Having all the games default content be its own mod has let me see things from the perspective of potential modders, so from pretty early on I've implemented systems for debugging what could go wrong when developing mods. For awhile those have been restricted to just being error messages that wrote to the console and I had every intention of keeping them that way & modders would just need to check the games player log to see what went wrong. But I decided that it wouldn't take long for me to implement something easier for modders to see what went wrong so I made the UI. It'll also serve handy in the future as being a popup for potential important errors that could occur in the game.

Campaigns
There's now a "Campaigns" file in mods so you can create your own custom campaigns too if you should choose.




Campaigns can be a series of maps related to each other (a story) or just a pack of different maps. All you have to do is have a campaign name, a thumbnail for it to use, and then all you have to do is write down what maps it'll include in order. When the player launches the game, any campaigns that are loaded from mods will check if they have a save file & if they don't, create one. That's right the engine now supports saving player data too!




Map Editor
The map editor is now a separate application from the main game. This was necessary in order to implement campaigns. The problem before was that since the map editor was a part of the game, you couldn't cache maps because you had to assume they might be edited. But reading all map files every time you need to access map data is extremely slow & led to opening the campaign screen taking ~5 seconds. That doesn't sound like much but consider there were only ~6 maps in the game at the time, as that number increases it'll get worse and worse. So now loaded maps are stored in RAM (cached) when the game is loaded so their data can be quickly accessed in-game.




Now, since I'm developing an engine more than a single game, I've almost always taken the harder option among many easier alternatives. The engine didn't need to have multiplayer which doubles development time, and I didn't need to make the multiplayer super secure by using the server-side authoritative model. It certainly didn't need to have mod support which also increased development time. I didn't need to go as far with mod support as I did, etc. But I did it anyway because this engine might be used for many games to come, and I want it to be the best it can be. I was presented with a similar dilemma when I wanted to add a win trigger to the level. It would've been easy to just program a collider that when the player touched it made the level end in victory & then to have the player place it in the map editor. But I'm so close to being done with most of the major engine features & being ready to focus on just the game, so why take the easy route now?

So, I've been working on a new major feature for the map editor: Map Events! I used to play a lot of WarCraft 3 when I was younger & loved using their map editor. The map editor included a map events system that let you program events without using code. Now I'm not going to make it quite as complex as theirs (I'm just a one-man team after all!) but having something like that in the map editor would let me & other map makers make truly unique levels with different events.




Each map event boils down to having triggers & actions. The event which every map will need to add will be when the player touches an area trigger to make the level end with a win. Even though the map events system is complete, I haven't finished area triggers yet which is a priority for my to-do list, so soon players will be able to complete levels.

This was a more time-consuming undertaking than I originally thought mostly with figuring out how to get the data to save & load to maps properly. But I'm glad I went the extra mile to do it.

Improved Pawn Performance
With this game pivot I saw a great opportunity for improving performance. About 45% of the games CPU usage was pawns trying to determine targets. That may sound like it's a really unoptimized calculation but it's in my opinion just a testament of how well optimized everything else is. It is after all having to do many line of sight checks which involve physics & can be expensive.

Because it was such a major part of performance, I wanted to do something about it but after optimizing it so much last update I wasn't sure where I could make any major difference. But then I realized because the game pivoted I could make so in a pawn file it was optional if pawns could target other pawns. After all, if a pawn solely exists to attack the player, why should it check if other pawns are targets? So for each pawn you can now configure if they're able to target other pawns or the player:




How much performance does this save? Well tests showed that when pawns were set to not try to target other pawns, their performance improved 256~161% depending on how many pawns the level contained. That makes even more sense when you consider that because each pawn must at the very least perform a distance check to every potential target & then do a line of sight check if they're close enough. That means the CPU usage of the pawns combat system scales exponentially with the number of potential targets. That also means reducing the number of potential targets exponentially improves performance!

This doesn't mean the engine can't handle pawns which target other pawns, it just means if you use pawns that do you'll just have to use less of them to get the same level of performance.

Closing Notes
This update was pretty massive & required a lot of work but it's all really coming together. I've been letting some of my close family & a few other people play test a test level I made, and the feedback has been more positive than the testing was for any other game I've made. This makes me think I really have something good going.

There are 2 big things I want to finish before focusing on game content, those being finishing area triggers & adding a cinematics editor. The area triggers shouldn't take much longer since I'm already pretty far with them, it's the cinematics editor that's going to be time consuming. I want the game to be able to have cutscenes. This will be useful not just for while you're playing a level but for the start & end of a level too. I haven't decided how I want to tackle this problem & how in-depth I want to go with such an editor so I have no idea how long it'll take, but it's another one of those things I know I don't need to make but that I feel the engine could really benefit from & since I'm so close to the end, I might as well uphold my record of going the extra mile.

That's it for the major changes, but trust me there were a lot more. You may have already noticed some of them as there were many visual improvements to both the game overall, combat, and effects. If you want to know them all then be sure to read the full notes in the summary at the bottom of the blog. And as always, thanks for reading!

-Blake Gillman

Extras

>Lines of code written:
28,740 lines / 319 scripts.
(+6,661 lines / +74 scripts since last update)

Notes & Technical Extras

>Why does the engine support multiplayer, even though it may not use it?
I've been writing this engine to support server-side multiplayer even though the current demon game I'm making with it is unlikely to have multiplayer. Or maybe it will I'm not totally sure. But I'm writing things this way because like I said, it's not about this game so much as it is about the engine itself. This means that this or future games made using the engine will at least have the option should I choose to use it.

>So the whole engine is network-compatible?
I don't believe I've noted it elsewhere but because the voxel engine was written before I knew what I was doing with this engine, it actually has no built-in network support, it's all handled client-side. Early in the process when I decided to make it Project Breach this meant rewriting the mod support system & all related objects like walls. This was pretty difficult, and I had actually intended to take the easy way out & instead of properly rewriting things, just assigning all objects an ID when they're created & creating my own system which relayed messages to those objects over the network. But I stopped & realized I would essentially be recreating existing networking solutions but with less dedication & features. So I bit the bullet, created a new git branch, and did a proper rewrite. I'm so glad I decided to do this because I can't imagine what horror I'd be going through now if I still had to work with that custom system. And it'd definitely be close to impossible to rewrite now that the engine has gotten so far, so it's lucky that I decided to do it so early on. But the voxel system never retrieved such treatment. That's not a problem for this game since the voxels are used just as a tilemap at this point, but it does present a potential future problem since this engine is intended to work with all sorts of games. I'm however not too worried since it's a self-contained enough system to where it can be safely modified without effecting everything else, even if it'd be a lot of work. Because it works as it does now & because I need to at some point stop working on the engine and start working on the game, I've decided to leave it as it is for now & revisit it in the future.

>Major engine changes
You would be hard pressed to find the game developer who released a game & said they couldn't have done anything better, or they got in every feature they wanted to. Making games means making them good enough, as diminishing returns kick in & you can even get to a point where you've put in too much and made the game worse as a result. The same is true of this engine I've been making. It's many technical achievements wrapped up into one, a voxel system, a biome editor, a map editor, server-side multiplayer, and not to mention mod support. I don't think it's an exaggeration to say that even though the game I'm making with it is simpler than many other games I've made, this engine is my proudest technical accomplishment. That being said, I've learned many things along the way, how to do things better, not just minor changes but big ones. But at a certain point I have to know when to stop working on the engine and start making a game. I still have a couple of big things I want to add to the engine, but there are a couple of really big rewrites I want to do for parts of the engine as well that I'm holding off on because I know that going back & changing things all the time means a game never gets made.

That being said, I want to rewrite some big parts, and definitely plan to do so once I start working on the second game with the engine. The good news is that these changes will require a lot of work under the hood, but will only require mod developers to change a couple of lines in many of their mod files. That means that even with these updates, mods made for this game will likely be fairly compatible with the next game made afterward. I don't mean you just copy them from one game to the other & instantly work, but that the amount you'll have to change to get them to work won't be anything insane.

Blog Summary

>Notes used to create this post
There's too much to cover, so probably split this into 2 parts or just only touch on important ones.

Gameplay:
-Added player body & all necessary systems to have functionality similar to a pawn (Equipment, Inventory, Visuals, Combat, Aiming, Movement, Health and Camera)
-Added campaign files
-Added demon 1
-Added demon 2 "Melee"
-Removed all existing weapons
-Added CPC rifle, named after the CPB rifle from Deep Space
-Added Berlin Shotgun

Visuals:
-Created new stone path texture
-Added shadows to pawns
-Added pawn corpses
-Changed damage text colors
-Made so damage dealt to objects also creates damage text
-Added render scaling (default 150%) to fix texture flickering
-Created new projectile visuals (balls instead of long bullets)
-Along with new projectiles are new projectile visual features such as more tracer lighting options
-Added damage flash to pawns
-Added blood effect to pawns whenever they take damage
-Added post processing effect for when you deal damage
-Added post processing effect for when you take damage

UI:
-Added error screen to the game so that people who make mods have an easier time figuring out if something went wrong when mods are loaded
-Added player stats UI
-Added player weapon UI
-Added custom player cursor

Map Editor:
-Made so the editor is a separate .exe (So maps could be cached on startup)
-Changed map editor grid color
-Added new demon-related map objects like demon wall and floors
-Added map events system (Inspired by the WarCraft 3 map editor)

Other:
-Added metal door
-Created generic network-based inventory system so in the future all inventories can use a uniform system
-Added test music to the game which all maps use
-Made so how long a pawn takes to begin shooting at a new target can be adjusted on the weapon file
-Made so projectiles can choose to have a different version used by enemy pawns so that way a weapon can use different projectiles depending on if its equipped by the player or an enemy pawn.
-Added player save data to the engine so things like how much score you got on a level can be saved
-Optimized projectile performance
-Created new pawn "DOOM" brain
-Made pawns no longer deal friendly fire (This is now a setting in the engine that I can turn on & off)
-Make so the "auto destroy projectile range" of a weapon is separate from its max range (Max range is just used by pawns for combat logic)
-Added "Can target pawns" and "Can target players" to pawn template. That way performance can be saved if pawns aren't intended to target one or the other

Fixes:
-A lot, mostly network related stuff

1 comment: