Implementing a Gacha system

Design Goal: A Configurable Player Experience

BallBuilder is a physics puzzle game where players launch balls to complete objectives. I wanted to create a system where players could deeply customize their experience through unique ball effects. Each ball would have passive abilities that influence gameplay—some subtle, some significant.

Once I committed to unique ball effects, the next question was progression. Should each ball be a binary unlock? That felt flat. Instead, I designed a multi-level upgrade system where each ball can be leveled up, making its effect incrementally stronger. This creates longer-term engagement and more meaningful choices about which balls to invest in.

What is a Gacha System?

For readers unfamiliar: a gacha system is a randomized reward mechanism common in mobile games. Players spend currency to "pull" or "summon" from a pool of possible rewards, with different rewards having different probabilities. The name comes from Japanese capsule toy machines (gachapon).

The key design tension is between monetization and fairness. Pure randomness can feel exploitative. Good gacha design includes mechanisms that guarantee progress over time, even with bad luck.

Ball Rarity Tiers

Balls in BallBuilder are divided into four rarity tiers:

  • Common (~10 balls): No special effects. These are visually interesting but functionally identical to the default ball. They exist partly as collectibles and partly to populate the gacha pool.
  • Rare (~11 balls): Modest passive effects. Useful, but not game-changing.
  • Epic (~7 balls): Significant passive effects that can influence how you approach puzzles.
  • Legendary (3 balls): Highly impactful effects. These don't break the game—skill still matters—but they open up new strategies.

Shards Instead of Direct Unlocks

Rather than unlocking balls directly, players earn ball shards. Collecting enough shards of a specific ball unlocks it, and additional shards level it up. This creates granular progress—even a "bad" pull contributes toward something.

Summon Pools

There are two primary summon pools:

Common Pool

The common pool costs fewer gems and contains Common, Rare, and Epic balls (no Legendary). The probability distribution:

  • Most likely: 1-3 Common shards
  • Less likely: 1-3 Rare shards
  • Even less likely: 1-3 Epic shards
  • Bottom ~10%: 10 shards of Common, Rare, or Epic (decreasing probability in that order)

Every pull yields some progress. The question is how much.

Rare Pool

The rare pool costs more gems but includes Legendary balls and has better odds overall. The structure mirrors the common pool—1-3 shards or 10-shard bundles—but the probability weights shift toward higher rarities, and Legendary becomes possible.

Pull Options

Players can pull in three ways:

  • Single pull: One summon
  • 10-pull with gems: Ten summons at once (slight efficiency bonus)
  • 10-pull with coins: Ten summons using coins instead of gems

The Evolution of Coins

Coins went through several design iterations. Originally, they were the primary currency for unlocking balls. When I introduced the shard-based gacha system, coins lost their purpose.

The solution: coins became an alternative currency for gacha pulls. Players earn coins naturally through gameplay—collecting them in levels and community-created levels. This creates a free-to-play progression path where engaged players can interact with the gacha system without spending premium currency (gems).

Gems remain valuable for other systems: upgrading the cannon, upgrading skills, and other components. Coins now have a clear, distinct purpose.

Pity System

Pure RNG can be frustrating. A player could theoretically pull hundreds of times and never get what they want. Pity systems guarantee minimum outcomes after a certain number of pulls.

BallBuilder's pity thresholds:

  • Common Pool: Every 30 pulls guarantees a Rare 10-shard bundle. Every 50 pulls guarantees an Epic 10-shard bundle.
  • Event Pool: Every 50 pulls guarantees the featured Legendary ball.

This means dedicated players can plan. If you save up enough gems for ~100 event pulls, you're virtually guaranteed to get the featured Legendary at least twice—once from pity, and likely once or more from the 2% base rate.

Event Banners

Legendary balls are difficult to obtain in the standard rare pool. To give players realistic opportunities to target specific Legendaries, I'm planning periodic event banners—perhaps every two to three months.

During an event, one Legendary ball is "featured" with a 2% summon rate (significantly higher than normal). Combined with the 50-pull pity guarantee, players who save resources can reliably obtain featured Legendaries.

Events add complexity to the backend. The system needs to store event definitions (which ball, start date, end date) and conditionally display the event banner when the user's current time falls within the event window.

Probability Implementation

The probability code is straightforward. Generate a random number between 0 and 1. Map ranges of that number to outcomes:

  • 0.00 - 0.50: Common 1-3 shards
  • 0.50 - 0.70: Rare 1-3 shards
  • 0.70 - 0.85: Epic 1-3 shards
  • ...and so on

(These are illustrative ranges, not the actual values.)

Critically, these probability thresholds are returned from the backend via the Profile API—the same mechanism described in my previous post about unified backend configuration. This allows me to adjust probabilities without deploying a client update.

Transparency

Players can tap an information icon to view the exact probabilities for each summon pool. No hidden rates. This is both ethical design and, in some jurisdictions, legally required for games with randomized purchases.

Handling Excess Shards

Once a ball is fully leveled, additional shards of that ball become "generic shards" of the same rarity tier. I considered several options here—converting to gems, fractional conversion rates—but settled on a generous system to reward engaged players:

  • Generic shards can be applied 1:1 to any ball of the same rarity tier
  • Upgrading: 10 generic shards of one tier combine into 1 generic shard of the tier above (e.g., 10 Epic generic shards → 1 Legendary generic shard)
  • Downgrading: 1 generic shard converts to 2 generic shards of the tier below

This ensures that every pull has value, even after completing certain balls. Collectors who want to max everything have a path to do so—it just takes time and continued engagement with the system.

Summary

The gacha system balances several competing concerns:

  • Randomness creates excitement, but pity systems prevent frustration
  • Premium currency (gems) drives monetization, but coins provide free-to-play progression
  • Rarity creates aspiration, but event banners make Legendaries achievable
  • Excess shards could feel wasteful, but the generic shard system keeps them valuable

The underlying probabilities are server-driven, allowing balance adjustments without client updates. And full transparency—viewable probability tables—keeps the system honest.

Comments

Popular posts from this blog

Solving Aspect Ratio Problems For Good!!

Designing a Scalable Community Content System

Customizing the playing experience with special ball effects