Thursday, August 5, 2021

Fading Light Devlog 3: Cutting Room Floor

Activated Abilities

One of my personal least-favorite things about the tower defense genre is that it's usually about a minute of gameplay (choosing which towers to build where) followed by however long of just watching the game play itself as your towers attack the creeps walking down the path. Trying to avert this pitfall was one of my main goals with Fading Light, since reversing the roles doesn't automatically fix the problem. I knew I wanted Fading Light to always be a game that you actively played rather than set up and watched. Therefore, the spells you cast were always going to be in the game to some degree, though it took some thinking and iterating before I landed on which ones belonged where.

However, an idea recently occurred to me while brainstorming new creep ideas: add one-use abilities to creeps, activated by clicking on them (while not aiming an ability). Such as clicking on a fairy to cause them to phase shift for a second or two, letting them pass through bullets and pickups without triggering them. I started prototyping this and realized it would, however, be opening up a huge can of worms for the game. This example ability would require me to:

  • Code the ability's core functionality (click on fairy; fairy becomes phase shifted; fairy returns to normal). This is something totally new that doesn't exist in the game yet, so it would require some experimentation or rejiggering of existing code to enable.
  • Add some sort of cooldown or charge system so that you can't just spam-click your fairies for permanent invulnerability. This already exists in Fading Light for the spells you cast from the UI but it doesn't exist in the context of being bound to units, so it would essentially be an entirely new system.
  • Add visual feedback. The easiest part of this would be implementing the graphics; the far harder and more time-consuming part is deciding how it should look. Not just so it looks nice aesthetically, but also so that it communicates whether the ability is ready to use, currently active, or on cooldown/out of charges. If it has more than one charge, or combines charges and cooldown, these also need to be differentiated.
  • Add some tutorial or introduction to the concept of clicking on units to activate abilities. This is a brand new mechanic to Fading Light, and potentially one massively important to succeeding, so the player needs to know how to work it.

Additionally, there's the expectation -- whether self-imposed or from the player -- that this type of mechanic would be expanded to more than one unit. A system like that would feel wasted on only one creep, since each creep type is meant to be specialized or used in certain situations. This means the process would have to be repeated a few times; not necessarily for every creep type, but for enough that it feels like a core mechanic of the game. Not only does this massively increase the work I would have to do, but it also massively increases the complexity of the game, both under the hood and from the user's perspective.

I don't mean to make this sound like a herculean task, or like something that shouldn't be done. Rather, I lay this out to explain why I think it just isn't worth it to implement right now. I think if the system was done well it could enrich the game, but it's the sort of major gameplay overhaul that may necessitate a total rethink of level design or some other core system. And, though it's par for the course in game dev to spend lots of time and energy on features you end up cutting, I'm not confident enough in this feature's healthiness for the game to want to take that risk.

The risk that I foresee is that, by adding activated abilities to most creep types, the cognitive load on the player is increased to a point that doesn't fit the game. I'm not saying most players can't handle it, I'm just saying it would befit a game with more content that players get more invested in than a free tower defense on itch that an amateur made in his spare time in under a year. People are willing to master games like League of Legends, but less willing to master some random person's personal indie project. It happens for sure, but I fear a lot of people will play the game, see that it requires more investment than they are willing to give, and then stop playing sooner than they would otherwise.

Maybe I'm overthinking things, but in short, I think this feature is better saved for a future project. I still think it's valuable to discuss things like this because game dev is full of hard decisions and big challenges, and it's a critically important skill to know which battles are worth fighting.


Ammunition Overhaul

The main features I did implement since my last update include the new Buzzsaw Tower, the addition of idle animations to tower sprites (not just sprites or particle effects tied to their weapon), and the clarification of the ammo bar. The yellow ammo bar that only showed you what vague proportion of its maximum ammo the tower had left was always meant to be a placeholder, since it kind of sucked. When the tower is at full ammo it's impossible to tell how many shots it has, and even when it shoots it's hard to eyeball how much of the bar a single shot took out. Additionally, it didn't communicate how long it took for a tower to regenerate ammo (or even that it was regenerating).

The new ammo bar fixes all these issues. Instead of using a simple Slider, it uses a Grid Layout Group that automatically tiles a number of ammo pip objects equal to the tower's maximum ammo. Each pip has two sprites: an empty sprite covered up by a full sprite. These pips are put into an ordered list, so when the tower fires a shot it looks at the rightmost pip that's full and makes it empty (it hides the full sprite, revealing the empty one beneath). When the tower begins regenerating ammo, it looks at the leftmost pip that's empty and slowly fills it up (each frame it changes the Fill Amount of the full sprite so it corresponds to the internal timer keeping track of how long it takes to regenerate ammo). With a few safety features to handle edge-cases, it works like a charm and looks much prettier while also communicating far more information at a glance.

It isn't perfect -- the pip sprites are quite small which can make them hard to read, but I couldn't really make them any bigger without having them obscure the tower or be significantly larger than the tower's health bar. But it's a huge improvement and I'm very happy I found a way to make it work the way I originally imagined when I was first concepting Fading Light.


The Wonders of Tweening

By the way, can I quickly sing the praises of tweening? Short for "in-between", a Tween is just an object that, via script, changes a value towards a target value over time. There are a couple niche areas where this actually has a tangible benefit, such as animating UI elements in Unity, but for the most part this is just a convenience improvement for the programmer.

Let's take an example: I use a Tween to animate a bullet traveling from a tower towards a Wisp when it activates its new Absorption ability. The bullet should seek the Wisp (and nothing else), be destroyed when it reaches its target or when its target dies, and report when it hits its target. At first, I thought about using my existing Bullet script (used for when towers fire bullets at creeps, or when a volatile creep explodes on death), but that has a lot of overhead for an effect that's almost purely graphical. 

Here are all the values I have to set when instantiating a Bullet. This isn't even covering the myriad of other methods a Bullet has for its intended purpose. It would be easy enough to take all the irrelevant fields and default them to 0, or null, or whatever, but the fact that so much data and functionality is being ignored or overwritten implies that this isn't the best tool for the job.

Here's what the Absorption graphic Tween looks like.

That's it. Granted, I'm using the free Unity asset DOTween, which has already written all the functionality a Tween needs in a very convenient and easy to use package, but for this purpose, I could have written a script to do the same thing: each frame, update the graphic's local position so that it's a little bit closer to (0,0) than it was the previous frame. When it hits (0,0) exactly, tell the script that it's reached the end. But this involves math and coding that costs time. There's no particular need for me to reinvent the wheel here, so I might as well use this shortcut. The important thing is that I know approximately what DOTween is doing, and if I wasn't using DOTween I would know how I would code things on my own. Assets like this are best used as a tool to save yourself time and hassle, not as a crutch or as a substitute for knowledge or coding ability.

I use Tweens elsewhere too, like to have lights dim, brighten, or pulse over time, or to slide the various menu panels on- and off-screen.

Here's a Unity hot tip that I feel barely qualified to write about: If you want to animate anything in your UI (i.e., anything on a Canvas), use Tweens to do it instead of Unity's built-in animator. This is because one of the optimizations that Unity uses is to only redraw elements of a Canvas when they become "dirty" -- i.e., when they change. If it doesn't change from frame to frame, it doesn't get redrawn and it doesn't cost the CPU any thinking time. But Unity's animator "dirties" the entire Canvas every frame when you use it with any of the Canvas's child objects. By itself this probably won't tank your game's performance, but it's a completely unnecessary waste of resources that can be easily averted by just Tweening a UI element's position, rotation, color, or whatever. With DOTween, it's usually just one line of code.

 

Burnout

Finally, in slightly sadder news I've been feeling increasing burnout on Fading Light. I'm not necessarily abandoning the project, but I think I'll take a break from it for a while so I can do some game jams and maybe prototype my next project. It may very well be that my passion for Fading Light never returns. In this case, the game is "good enough," even if it didn't reach as far as I originally planned. I learned so much by making Fading Light that my time was not wasted, and it was, for the most part, quite fun. So my next update will probably be on a brand new project or topic, which is exciting to think about! I hope to see you then.

No comments:

Post a Comment

Post-Mortem: Protect & Serve

 A couple weeks ago I participated in my first ever game jam! This is something I've wanted to do for over a year now, but in the beginn...