Skip to main content

Integrate Simple IAP System

This guide explains how to replace the default shop in Tanks Multiplayer with Simple IAP System. The components used in this guide are directed at the multiplayer configuration using Unity Networking (Netcode), but can be applied to a project set up for Photon networking in the same way.

Problem description

You have set up your Tanks Multiplayer project as shown in the documentation PDF included in the package. After playing with the default project, you would like to integrate a more advanced shop solution, possibly supporting virtual currencies, localized prices or a complex database via Simple IAP System. Also, you have imported Simple IAP System and correctly configured it for a billing platform of your choice already.

Recreating the shop product prefab

Open the Intro scene of Tanks Multiplayer. The first thing we are going to do here is to create a new product prefab that can be used by Simple IAP System. Expand the Canvas > Shop > Window > Products game object and select one of the default shop products (e.g. ProductA). Remove its IAPProduct component and attach the ShopItem2D script instead.

All values of the ShopItem2D component will be empty in the inspector. Expand the product game object so you can see all of its UI elements and labels, then start assigning them to the ShopItem2D script in the inspector. The result should look like the following:

SIS010 SIS020

Lastly, you have to add OnClick listeners to the item buttons, so that they actually do something when pressed. On the buyButton, add a new listener and assign the ShopItem2D script on the root object, then choose its Purchase() method. On the selectButton, add a new listener and assign the ShopItem2D script on the root object as well, then choose its IsSelected() method at the top - note that there is another IsSelected() method in the dropdown further below, but you have to select the IsSelected() method under "Dynamic bool".

SIS030 SIS040

Drag & drop the modified product into the project panel in order to create a prefab. Give it a more descriptive name too, like Tank_IAPItem.

SIS050

Preparing the shop scene for Simple IAP System

Next, we are going to prepare the scene for our new shop. Delete all shop product game objects from the scene and only keep the "Products" game object. Remove its VerticalLayoutGroup component. Instead, attach a GridLayoutGroup and IAPContainer script to it. In the IAPContainer component, assign the ShopItem prefab you created earlier.

SIS060

As a category, assign the group which contains your Tank products - if you haven't created them before, you can do so now. Open the IAP Project Settings for creating your IAP product listing. You can delete all the unnecessary groups, only keeping one group for your IAPs as seen in the screenshot below. Please note the following points:

  • the identifiers of our tank products match the tank prefab names in our NetworkManagerCustom component (section "Registered Spawnable Prefabs"). This is so that we can map the player tank selection with our player prefabs via code later, for sending it across the network. If you have created different product identifiers on the App Stores, then you can map them in the "Overrides" tab per product.
  • make sure that the type of your tank products are set to "Non Consumable"
  • the first tank would be free, but for the others you want to add a "Costs" value

SIS070

Delete the "UnityIAP" game object from the scene (found under the "Managers" game object). We will not use that anymore, since the prefabs in Simple IAP System are a full replacement of it. Then, locate and drag & drop the prefabs of SIS into your scene: IAPManager, UIShopFeedback, Window - Message. With the UIShopFeedback game object selected, expand the "Window - Message" instance and assign it and its Text element to the UIShopFeedback component in the inspector.

SIS080

Doing some code changes

Since we have removed the UnityIAPManager and IAPProduct references from the scene already, we don't have to do any code modifications to them anymore. What we have to change is the default tank selection when players launch the game for the first time. Currently, this is done in the UIMain script, Start() method. To make use of Simple IAP System and grant players the free tank automatically whenever nothing is selected, we have to change:

if (!PlayerPrefs.HasKey(PrefsKeys.activeTank)) ...

to

if (!SIS.DBManager.GetAllSelected ().ContainsKey ("IAP")) 
{
SIS.DBManager.SetPurchase("TankFree");
SIS.DBManager.SetSelected("TankFree", true);
    SIS.IAPManager.GetInstance().RefreshShopItemAll();
}

Note that the string values above relate to your settings specified in the SIS IAP Settings editor window. "IAP" is the name of the group your tank products are located in, while "TankFree" is the identifier of the tank that should be granted for free.

Now that the default selection is set, and Simple IAP System handles the shop selection automatically, we still have to make the network aware of what the player selected. This happens in the NetworkManagerCustom script, GetJoinMessage() or AddPlayer() method (depending on the network solution used), where the selected prefabId is assigned to a join message. The join message expects an index value of the tank that is selected, so we first have to get the local selection again and convert it to the array index by comparing the player prefab names.

Note that you need to specify the IAP Settings editor group of your tank products in the DBManager.GetAllSelected() call again below. The final code looks like this:

Netcode

//constructs the JoinMessage for the client by reading its device settings
private JoinMessage GetJoinMessage()
{
string selectedTank = SIS.DBManager.GetAllSelected()["IAP"][0];
int selectedIndex = 0;

for (int i = 0; i < singleton.spawnPrefabs.Count; i++)
{
if (selectedTank == singleton.spawnPrefabs[i].name)
{
selectedIndex = i;
break;
}
}

    JoinMessage message = new JoinMessage();
    message.prefabId = short.Parse(selectedIndex);
    message.playerName = PlayerPrefs.GetString(PrefsKeys.playerName);
    return message;
}

PHOTON

//received from the master client, for this player, after successfully joining a game
[PunRPC]
void AddPlayer()
{
    string selectedTank = SIS.DBManager.GetAllSelected()["IAP"][0];
    int selectedIndex = 0;

for (int i = 0; i < playerPrefabs.Length; i++)
{
if (selectedTank == playerPrefabs[i].name)
{
selectedIndex = i;
break;
}
}

    //get our selected player prefab index
    int prefabId = selectedIndex;

    //get the spawn position where our player prefab should be instantiated at, depending on the team assigned
    //if we cannot get a position, spawn it in the center of that team area - otherwise use the calculated position
Transform startPos = GameManager.GetInstance().teams[PhotonNetwork.player.GetTeam()].spawn;
if (startPos != null) PhotonNetwork.Instantiate(playerPrefabs[prefabId].name, startPos.position, startPos.rotation, 0);
else PhotonNetwork.Instantiate(playerPrefabs[prefabId].name, Vector3.zero, Quaternion.identity, 0);
}

You should now be ready to go with Tanks Multiplayer + Simple IAP System! If you experience any billing related issues when testing on a real device, please have a look at our App Store guides and common errors on the Simple IAP System docs.