Skip to content

Smart Shop

The in-game shop is the place to generate money for your game! A good store usually has a variety of items players need during the game. For the convenience of navigation, developers usually split all the content into different pages, such as Gems, Gold, Limited Offers, Super Packs, Event Items, etc. Each page contains several slots with different prices.

Follow the instructions to add a Store to your game:

  1. Add the LiveOps package to your game.
  2. Open Game Store by clicking the store button(to the right from the LiveOps header).
  3. Edit Store Pages and Store Slots in the Store cell of the table.
  4. Each Store Page has a Condition to be available and a list of Store Slots.
  5. Each Store Slot has a Condition to be available, referencing the Store Item and a Visual Badge.

Screenshot

You can preview your work using our Demo project. It should look like this:

Screenshot

Slot Types

Balancy has several built-in slots:

Name Description
Store Slot Default Slot
First Purchase Bonus Such a slot gives a bonus when purchased for the first time.
Periodic Slot Such slots can be purchased at limited times during the specified period. For example, a maximum of 2 times a day.
Slot with Cooldown Once the slot is purchased, it'll be set on the cooldown. While on cooldown, you can't purchase it again.

First Purchase Bonus

One of the most effective conversion methods is the first purchase bonus. Players get double rewards for the same price. Players can usually double each Store Slot, which pushes them to purchase every slot, growing your ARPU and LTV. Such an offer has no time limitation. Thus, players are always tempted to make the first purchase with a bonus.

Screenshot

As you can see, only several minutes separate you from a compelling monetization method. Take a look at what this feature looks like in Mobile Legends game.

Screenshot

Free Items

Daily Gifts and Bonuses are a great way to make players visit your game and the shop daily. While collecting rewards, they'll create a habit of constantly checking the shop, and the chances to find and purchase something valuable grows.

Section for programmers

  1. Use the following code to access the Store config and read all active Store Pages and Slots.

    var smartConfig = Balancy.DataManager.SmartObjects.SmartConfig;
    var pages = smartConfig.ActivePages;        
    foreach (var page in pages)
    {
        foreach (var activeSlot in page.ActiveSlots)
        {
            //TODO write your code here
        }
    }
    
  2. Visit the Payments section to read how to purchase Store Items and check availability.

  3. The store can be updated at runtime due to Conditions being actively used in Store Pages and Slots. You should subscribe to such events and handle them:

    smartConfig.OnStoreUpdatedEvent
    page.OnStorePageUpdatedEvent
    
  4. Another way to track the changes in the Store is to register LiveOps Listener:

    ExternalEvents.RegisterLiveOpsListener(new LiveOpsStoreEventsExample());
    

Visit the Programmers Section and learn how to subscribe for important events.

Example:

  1. Find the Prefab called ExampleStore and place it in the Scene.
  2. After the game starts and Balancy is initialized, call the following method(winStore is the link to the WinStore script on the ExampleStore gameObject):

    winStore.Init(DataManager.SmartObjects.SmartConfig);
    
  3. Enjoy the demo. And remember - you can use the source code we provided as you wish.

Custom Store

Sometimes you need to have several Stores with additional parameters. It might be required for very complex games with a lot of content and different places to sell goods. Follow the next steps to create multiple stores:

  1. Create and inherit a new Template from 💰Game Store Base. Let's call it MyStore for example.
  2. Add new parameters. I'll add Name - LocalizedString and Condition - Logic.
  3. Add several documents to the table, and you'll get something like this:

Screenshot

I'll be using the Condition to show different stores for players, depending on their level. Next, you need to ask your engineer to add logic to make it work for your case.

  1. First, you need to init the store document:
var myStore = LiveOps.Store.InitCustomStore(store) as MyStore;
  1. When you are done working with the store, don't forget to clean it up:
myStore.Clear();

Read here how to work with Conditions.

Below is the complete example:

using System;
using System.Collections.Generic;
using Balancy;
using Balancy.Models;
using Balancy.Models.SmartObjects.Conditions;
using Balancy.SmartObjects;

public class MyStoreManager : IConditionsListener
{
    public static event Action<MyStore> OnStoreChanged;

    private static MyStoreManager _instance;

    private readonly List<MyStore> _activeStores = new List<MyStore>();

    public static void Init()
    {
        if (_instance == null)
        {
            _instance = new MyStoreManager();
            _instance.SubscribeForStores();
        }
    }

    public static void Clear()
    {
        _instance?.UnsubscribeFromStores();
        _instance = null;
    }

    private void SubscribeForStores()
    {
        var allStores = DataEditor.MyStores;
        foreach (var store in allStores)
        {
            var myStore = LiveOps.Store.InitCustomStore(store) as MyStore;
            _activeStores.Add(myStore);
            LiveOps.General.ConditionSubscribe(myStore.Condition, myStore, this, PassType.False);
        }
    }

    private void UnsubscribeFromStores()
    {
        foreach (var store in _activeStores)
        {
            LiveOps.General.ConditionUnsubscribe(store, this);
            store.Clear();
        }

        _activeStores.Clear();
    }

    public void ConditionPassed(object data)
    {
        Refresh();
    }

    public void ConditionFailed(object data)
    {
        Refresh();
    }

    private void Refresh()
    {
        var firstStore = FindTheFirstStore();
        OnStoreChanged?.Invoke(firstStore);
    }

    private MyStore FindTheFirstStore()
    {
        foreach (var store in _activeStores)
        {
            if (LiveOps.General.CanPassCondition(store.Condition) == PassType.True)
                return store;
        }

        return null;
    }
}

All you need to start working with the following class is to Subscribe for the Store change and call Init method:

MyStoreManager.OnStoreChanged += OnStoreChanged;
MyStoreManager.Init();

In my example, there is only one flaw: when a player changes its level, both Stores invoke the Refresh method, so you'll be notified twice. It's not a big deal, but I'll leave it to you to fix it as homework.