Daily rewards

Daily rewards are becoming an increasingly popular game mechanic used across all genres of games, and are especially popular with free-to-play titles. They offer an engaging way of bringing players back every day while letting them earn a variety of items, ranging from purely cosmetic skins and avatars to inventory items and in-game currency.

Cloud Code's ability to easily integrate with other Unity services makes it an excellent choice for building the logic around daily rewards. You can define items and currencies in Economy, probabilities in Remote Config, and write the underlying algorithm in Cloud Code. This allows you to alter the logic of daily rewards on the fly without the need to update the game client.

For example, you can:

  • Reduce the availability of some items
  • Increase the number of items that get rewarded
  • Include additional validation that can prevent players from receiving duplicates of rare items
  • Alter the items and probabilities through Remote Config Campaigns

Setup

The following example shows how to define multiple pet toys as inventory items in Economy. You can define the daily reward parameters in Remote Config before tying it all together with a Cloud Code script.

Economy

The first step in creating this game mechanic is to define the rewards with the Inventory Item type in Economy.

Navigate to the Unity Cloud Dashboard and select Economy from the left navigation bar.

Create the following inventory items in Economy:

  1. Inventory item Choco with ID TOY_CHOCO
  2. Inventory item Jojo with ID TOY_JOJO
  3. Inventory item Kiki with ID TOY_KIKI

You must publish the Economy configuration before using it in Cloud Code scripts.

Remote Config

You can use Remote Config to define the daily rewards parameters as a custom JSON value under the key DAILY_REWARDS_VARIABLES:

JSON

{
  "rewards": [
    {"id": "TOY_CHOCO", "probability": 10},
    {"id": "TOY_JOJO", "probability": 65},
    {"id": "TOY_KIKI", "probability": 80}
  ]
}

Save the key-value pair so that it is available in Cloud Code scripts.

Daily rewards script

Once the configuration is in place, you can write a simple script that interacts with Economy and Remote Config to gift a random toy to the player using a simple weighted random algorithm:

JavaScript

/*
 * Retrieve the daily rewards configuration from Remote Config
 * Select a random item from the configuration and gift the item to the player in Economy
 * Note: the Economy configuration needs to be published and Remote Config values need to be saved before they are available in Cloud Code scripts.
 *
 */

const { InventoryApi } = require('@unity-services/economy-2.4');
const { SettingsApi } = require('@unity-services/remote-config-1.1');
const _ = require('lodash-4.17');

const REMOTE_CONFIG_VARIABLES_KEY = 'DAILY_REWARDS_VARIABLES';

module.exports = async ({ context }) => {
    // Initialize the Economy and Remote Config API clients using the player credentials
    const { projectId, environmentId, playerId } = context;
    const inventoryApi = new InventoryApi(context);
    const remoteConfigApi = new SettingsApi(context);

    // Fetch the daily rewards configuration from Remote Config
    const remoteConfigResponse = await remoteConfigApi.assignSettingsGet(
        projectId,
        environmentId,
        'settings',
        [REMOTE_CONFIG_VARIABLES_KEY]
    );

    // Extract the daily rewards from the response
    const dailyRewardsConfig = remoteConfigResponse?.data?.configs?.settings?.[REMOTE_CONFIG_VARIABLES_KEY];
    const dailyRewards = dailyRewardsConfig?.rewards;

    // Pick a random reward from the options
    const reward = selectRandomReward(dailyRewards);

    // Gift the reward to the player
    await inventoryApi.addInventoryItem({ projectId, playerId, addInventoryRequest: { inventoryItemId: reward.id } });
    return { reward: reward.id };
};

// Select a random item based on the probability of each option
function selectRandomReward(options) {
    if (!_.isArray(options)) {
        throw Error('Invalid daily reward options');
    }

    let sumOfProbabilities = 0;
    options.forEach((option) => {
        sumOfProbabilities += option.probability;
    });

    let random = _.random(0, sumOfProbabilities);

    for (let i = 0; i < options.length; i++) {
        if (random < options[i].probability) {
            return options[i];
        }
        random -= options[i].probability;
    }

    throw Error('Unable to select a daily reward');
}