Tips on how to structure you game to make balancing and tweaking much, much easier!
I’m currently prototyping a silly management sim about public restrooms – keep the impatient cafe hipsters happy, stave off the hobos in a library, and prepare for the lunch hour rush! Is your bathroom good enough even for the Pope’s tooshie?
As I mentioned before, there is a lot of variables to take into account! From per-patron stats like happiness, temperate tolerance and homophobia, to global stats about cleanliness and comfort level. Once I got all the systems in I realized – this is really hard to make sense of!
From a balancing standpoint, what does “Patience Depletion Rate” really mean? How can I juxtapose radiator’s “heat range” against person’s “heat tolerance level?” I was struggling with adjusting my stats and variables until I had an epiphany.
The problem wasn’t my system – the problem was my naming conventions.
My variables made logical sense for the game code, but not for the designer. I set out to rename all my stats, shifting from “how does this work” to “what makes most sense to me?”
Example #1: Measuring Patience
One important variable is a person’s patience. If they have to wait too long to make a poopoo or wash their hands, they will get increasingly impatient and angry. I start off with everyone at 100% Patience that slowly drains as they wait, multiplied by my crucial “Patience Depletion Rate.”
Logical right? But not easy to balance! Adjusting the “depletion rate” was a blind guess until it felt right. Combined with 10 other similarly ambiguous variables, trying to make the whole system work together was a nightmare.
Patience = CurrentPatience - PatienceDepletionRate * DeltaTime
So I redid my calculations to replace Patience Depletion Rate with WaitTime, or how long it takes before happiness hits zero and person storms off disgruntled. The math got marginally more complex, but the designer’s job much easier.
Patience = CurrentPatience - (1 / WaitTime) * DeltaTime
Now it was easy to make sense of it! “Ok so a minute is how long a person will stand waiting! Half a minute will drop them to half patience.” Now I had something tangible to balance.
Example #2: Radiator Heat
Another problem were my radiators, modeled after beloved Theme Hospital. A person has a certain temperature min and max they tolerate and outside of that their comfort decreases. Too few radiators spaced too far and it gets cold, too many and it gets too hot. Tracking a temperature is a simple matter of a “HeatStrength” variable on the radiator, right?
Foreach( radiator ): TotalTemp += HeatStrength / DistanceToRadiator
Yet a nightmare to balance – “so, uhh, how far can a person stand from a radiator? What if I have 2?” I couldn’t even imagine having more in my head. So I changed the stat to HeatRadius.
Foreach( radiator ): TotalTemp += (HeatRadius - DistanceToRadiator)/HeatRadius * 100%
Boom. At half the distance, half the heat. Right next to it, full heat. Note I also change from “degrees” to % as unit of measurement since, effectively, that’s all a designer cares for – what is the range of comfort? A 50%-90% of distance is easier to think of than 65F – 85F.
(Minor note: I ommited Clamp to 0-1 range for the heat radius calculation for brevity. Don’t forget if you dont want negative values!)
Example #3: Weapon Durability and Degradation
Let’s tackle something more useful for most devs, an RPG where weapons slowly break over time. A simple “depletion per use” rate seems sufficient, right?
OnUse: Durability = Durability - DepletionRate
But again, arbitrary! Lets change it to:
OnUse: Durability = Durability - ( 1 / UsesBeforeBroken )
Bam – now whatever value I set I instantly know this is how many times the weapon can be used. I don’t need to do any mental math to make sense of my system, the system does it for me. And for the player, I can easily multiply UsesBeforeBroken by something to obfuscate it a bit.
Summing Up
The point I am driving here is – name your balancing config variables to make sense for your designers, not the code. You can always convert between different style of stats, but make your code do the conversion, not your designers. Few extra tips:
Keep variables direction consistent – either high is good or low is good. For example, Health (high good) or Weapon State (high good). Rename other stats to match, i.e. Fatigue => Energy, ItemUseCount=> ItemDurability etc.
Keep your math linear if you can – a lot of things in physics follow the Inverse Square Law, producing an exponential curve (i.e. 1/(Distance*2) ). Cheat it to be linear (1/Distance) if you don’t need complete accuracy, it is much easier to predict. When you double your distance, you cut the effect in half, not by four.
And lastly, think what units are easiest to make sense of! Oftentimes, a percentage rating is much easier to tweak than an arbitrary scale or, god forbid, the US metric system. You can always convert an optimal Temperature % to Fahrenheit if the game lore requires it, but make it easy on your developers. If you know all stats must be >50%, that takes a lot of needless mental math out of designer’s job!
Hope this is useful!
Intrigued? PLAY KARASKI NOW!
Or Follow at
Karaski: What Goes Up... is a an open-ended "Who-Dun-It" mystery adventure onboard a sabotaged 1920s Airship where the player is as likely a culrpit as the suspects. Deus Ex meets Clue with a bit of Telltale!
1/Distance is not linear.
Yes but you’re not actually balancing distance, you’re balancing MaxRange, so that’s the what you have to think of as your variable. It’s a bit tricky :)