• Register
Post tutorial RSS Balancing a Game the Right Way: Make Stats Designer-Facing

Tips on how to structure you game to make balancing and tweaking much, much easier!

Posted by on - Intermediate Design/Concepts

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?

Bathroom Manager Prototype
Truly, a Game of Thrones

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.”

Game Design Balancing: Patience
The white rings are the ever-depleting patience.

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

Theme Hospital Radiator
Awkwardly placed radiator in Theme Hospital = optimal heat distribution!

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

Diablo 3 Weapon Durability
Noooooooo, mah Stats!

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.

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? Check out the my next game Karaski: What Goes Up...

Or Follow at Twitter Facebook

Karaski: What Goes Up... is a an open-ended, story-driven stealthy adventure onboard a sabotaged 1920s Airship - who is the saboteur, who can be saved?! Deus Ex meets Clue with a bit of Telltale!

Karaski Indie Game Airship Promo Art

Post a comment
Sign in or join with:

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.