Skip to main content

Description

A regenerating currency system limits how much a player can play in a given time window, similar to the lives or hearts mechanic in many mobile games. In this example, Lives (LV) deplete during combat and regenerate at a rate of one life every five minutes, up to a maximum of five. Players who run out of lives must either wait or spend Gems (GM) to purchase additional lives immediately. All game logic—including the outcome of battles, life deductions, and Gem grants—runs in CloudScript. This prevents clients from faking results or bypassing the life check.

How it works

1

Authenticate

The client calls an authentication method (for example, LoginWithCustomID) to obtain a valid session ticket.
2

Trigger a battle

The client calls ExecuteCloudScript with FunctionName: "Battle" to simulate gameplay.
3

Battle checks for available lives

The Battle CloudScript handler calls server.GetUserInventory to retrieve the player’s current Virtual Currency balances and recharge times. If the player has zero Lives, the function throws an error that includes the number of seconds until the next life regenerates.
4

Calculate battle results

If the player has at least one Life, the script:
  • Generates a random Gem reward between GEM_MIN (10) and GEM_MAX (20) and credits it via server.AddUserVirtualCurrency.
  • Rolls a random number to determine if the player loses a Life (CHANCE_TO_DIE = 0.3333). If so, one Life is deducted via server.SubtractUserVirtualCurrency.
5

Return results to the client

The script returns a result object containing gemsFound and lostALife so the client can update the player’s display.
6

Lives regenerate passively

PlayFab’s built-in Virtual Currency recharge mechanism automatically adds Lives back over time (one every five minutes) up to the configured Recharge Max of 5, without any additional server calls.
Players can spend Gems to purchase lives directly from the catalog using the standard PurchaseItem Client API call—no additional CloudScript is required for that flow.

PlayFab building blocks

  • Accounts — player authentication and session management
  • Virtual Currency (LV) — Lives, the play-limiting resource; configured with a recharge rate and cap
  • Virtual Currency (GM) — Gems, the premium currency awarded during battles and used to buy lives
  • Catalog — purchasable life items priced in Gems
  • CloudScriptBattle handler enforcing life checks and calculating outcomes

Setup

1

Create the Lives virtual currency

In Game Manager, go to Economy > Currencies and select New Currency. Enter:
PropertyValueDetail
CodeLVAbbreviation for the Lives currency
NameLivesDisplay name
Initial Deposit1Players start with one life
Recharge Rate288Recharges once every 5 minutes (24 hr × 60 min ÷ 5 min = 288 units/day)
Recharge Max5Maximum lives a player can hold
Select Save Currency.
2

Create the Gems virtual currency

Select New Currency again and enter:
PropertyValueDetail
CodeGMAbbreviation for the Gems currency
NameGemsDisplay name
Initial Deposit5Starting balance for every new player
Select Save Currency.
3

Upload the catalog

Go to Economy > Catalogs and select Upload JSON. Select Catalog.json from the PlayFab-JSON folder of this recipe. The catalog contains the purchasable life items priced in Gems.
4

Upload the CloudScript

Go to Automation > Revisions, select Upload New Revision, choose CloudScript.js, and select Save as revision.

The CloudScript

The Battle handler contains all gameplay logic and relies on two helper functions for Virtual Currency operations.
// Configuration constants
var CHANCE_TO_DIE      = 0.3333; // ~33% chance to lose a life per battle
var GEM_MAX            = 20;     // maximum Gems found per battle
var GEM_MIN            = 10;     // minimum Gems found per battle
var LIVES_CURRENCY_CODE = "LV";
var GEMS_CURRENCY_CODE  = "GM";

handlers.Battle = function(args) {
  // Retrieve the player's inventory and VC balances
  var inventoryResult = server.GetUserInventory({ "PlayFabId": currentPlayerId });
  var userVcBalances  = inventoryResult.VirtualCurrency;
  var userVcRecharge  = inventoryResult.VirtualCurrencyRechargeTimes;

  // Enforce the life gate
  try {
    if (!CheckLives(userVcBalances)) {
      throw "No lives remaining. Purchase additional lives or wait: "
        + userVcRecharge[LIVES_CURRENCY_CODE].SecondsToRecharge + " seconds.";
    }
  } catch(ex) {
    return JSON.stringify(ex);
  }

  // Award Gems
  var gemsFound = Math.floor(Math.random() * (GEM_MAX - GEM_MIN + 1) + GEM_MIN);
  AddVc(userVcBalances, GEMS_CURRENCY_CODE, gemsFound);

  // Possibly deduct a Life
  var rollOfFate = Math.floor(Math.random() * 10 + 1);
  var lostALife  = rollOfFate <= Math.floor(10 * CHANCE_TO_DIE);
  if (lostALife) {
    SubtractVc(userVcBalances, LIVES_CURRENCY_CODE, 1);
  }

  return JSON.stringify({ gemsFound: gemsFound, lostALife: lostALife });
};
function CheckLives(vcBalances) {
  return vcBalances != null
    && vcBalances.hasOwnProperty(LIVES_CURRENCY_CODE)
    && vcBalances[LIVES_CURRENCY_CODE] > 0;
}

function AddVc(vcBalances, code, qty) {
  server.AddUserVirtualCurrency({
    "PlayFabId": currentPlayerId,
    "VirtualCurrency": code,
    "Amount": qty
  });
}

function SubtractVc(vcBalances, code, qty) {
  server.SubtractUserVirtualCurrency({
    "PlayFabId": currentPlayerId,
    "VirtualCurrency": code,
    "Amount": qty
  });
}

Running the example

1

Install the PlayFab Unity SDK

Download the PlayFab Unity 3D SDK and import it into a new or existing Unity project.
2

Import the recipe package

Import RegeneratingCurrencyRecipe.unitypackage from the Example-Unity3d folder (or download it from the PlayFab-Samples GitHub repo).
3

Open the scene

In the Project window, open Assets > PlayFab Recipes > RegeneratingCurrency > Scenes and add the scene to your Hierarchy.
4

Set your title ID

Select the Main Camera. In the Inspector, set Play Fab Title Id to your PlayFab title ID.
5

Run the scene

Press Play. Call-by-call status updates are displayed in the console.

Build docs developers (and LLMs) love