Last week I continued working on Vectorball, a project I hadn't been working on for about four months due to other obligations. It was already quite far in development, gameplay-wise at least, and I spent countless hours playing it just for fun.
So I looked at my list of things that were still missing and decided that randomized unlockables would be a good thing to implement. I started out by making a list of all things you could possibly unlock in the game:
- Game Modes (such as Season or Tournaments)
- Challenges (basically specific predefined levels to beat)
- Additional Character Slots
- Items (that can be carried by players and apply passive effects)
- Item Slots (players start out with just one available slot but can get up to five)
- Team Buffs (which can be activated when playing a tournament, e.g. your team's goal will be a little smaller)
That's quite a lot - and I reckon that's a good thing. The more variety there is, the better.
My main motivation working on the whole randomized bonus system was to provide the necessary motivation for the player to keep on playing the game. There should be a sense of progress combined with randomization - i.e. luck - in order to keep it unpredictable and engaging.
There's a chance to get one of these unlockables each time you score a goal with one of your players as well as after each win. At this point however two issues came up:
First, different events require different drop qualities and probabilities (e.g. scoring a goal should yield less rewards then winning a game or even a full tournament, simply because the latter happens not as frequently); and second, I wanted a bit of control over when things are unlocked without giving up the random nature of things.
This is necessary to avoid scenarios in which a player has to play for hours simply to unlock the basic game modes or a second character slot.
Controlling the Random
Let's first talk about control. There are certainly innumerable ways to deal with this, but this is what I did:
Within the code I created a (non randomized) list of specific unlocks together with data about when they are supposed to occur (as in after how many previous unlocks) and what's the probability for them to be activated once that point has passed, as the following table shows.
Item Slot - Player #1 - 5 - 50%
Character Slot - / - 8 - 20%
Game Mode - Tournament - 12 - 30%
Team Buff - Smaller Goal - 17 - 20%
(sorry for the formatting, tables don't seem to work here)
So let's have a look at the first one, an additional item slot for player #1 (of course the first player - at this point there is just one character slot so unlocking an item slot for any other player character wouldn't make any sense). After four random unlocks this one is considered for the first time (hence the 5 in the third column), and has a chance of 50% to be picked. I introduced this chance simply to make sure the predefined unlocks wouldn't always show up as the n'th unlock, but still appear to be somewhat random. So in this case there's a 50% chance for it to be picked - if it is, it will be awarded to the player and then removed from this list. If it isn't, a random drop will be awarded to the player and it remains in the list and will again have a 50% chance to be picked the next time something is unlocked.
This system is obviously quite simple but combines randomization and control in a reasonable way.
Qualities and Probabilities
I mentioned before that certain events, such as scoring a goal, winning a match or winning a tournament cause potential rewards, but based on different probabilities. I started off simple by defining somewhat arbitrary values for these cases: 5% for scoring a goal and 35% for winning a match. Winning a tournament can yield up to three rewards with 150%, 100% and 75% probability respectively.
You might wonder now 'why 150%? That doesn't make any sense!', and while you're certainly right with that, there's a catch: The probability is first multiplied with a factor that's based on how many unlocks were granted already. This factor is defined as 0.98#previous unlocks, so starts out as 1.0 and gets reduced by 2% after each unlock. Consequently after 50 unlocks you'll have only ~36,4% the chance for a reward that you had in the very beginning.
This behaviour very simply is supposed to keep the motivation curve high in the beginning while avoiding reward inflation in the long run. Later on, you want (and have) to work for your rewards.
These probabilities are used to determine whether a reward shall be awarded at all, at this point we don't know yet what kind exactly. If the player is lucky and is given a reward, at this point the table introduced earlier comes into play: if any item from the table is picked, it will be given to the player and that's it. Otherwise however, a random reward will be generated.
Random Reward Generation
We start out determining which kind of reward it will be. Again I used probability values that seemed to make sense without putting too much thought into them: 10% for a new item spot, 5% for a team buff and 85% for an item, although these values are in fact a bit more in depth and item spots get less likely the more are already unlocked, and team buffs can only be unlocked if there are any left, of course. Afterwards the type and attributes of whatever is generated are picked more or less randomly, with a tendency for weaker values however. That means items are not equally distributed regarding their quality, but you'll get goot items much more rarely.
There really isn't all that much to it - after a basic understanding of the system's requirements it can be put in place quite quickly and without complicated algorithms. This very basic system described above combines a variety of useful features that surpass basic randomness:
- there's an element of control, I can make sure certain unlocks are picked early on
- the amount of unlocks steadily decreases which hooks the player early on without giving all the unlocks away too soon
- unlock quality and quantity vary depending on the event causing them
Despite about 12 years of game dev experience, this was actually the first time I implemented such a system and realized how useful it really is. It's absolutely worth the effort. Although I, being player and developer in one, could technically unlock all the items and buffs with a single line of code, I actually keep playing the game in order to earn the progress. Time will tell if actual playtesters find the system similarly engaging, but I'm reasonably optimistic and would recommend anyone to consider adding a reward system based on controlled randomization to pretty much any game, as it does make a huge difference.