Implementing the Ouya payment framework

The Ouya examples provide a really good stub class for your In-App Purchase needs, we'll import that in to our project as a base for the code. The file is located in the folder where you installed the Ouya Unity repository to in Chapter 2, Setting Up Unity and the Ouya Plugin. From inside that folder navigate to AssetsOuyaExamplesScripts and drag the OuyaShowProducts file in to the Scripts folder in our Project panel. Double-click on it to edit it in MonoDevelop, and have a look at the method names to become familiar with the method names that we will need to call and respond to. At the moment we're going to use the script as it is. There is some code already in the script that will build a Graphical User Interface (GUI) and display a menu system for seeing your products.

Back in Unity, open your SetUp scene and add a new, empty game object to it. Call it IAP and drag your OuyaShowProducts script on to it. We need to make sure that this new, empty game object persists across all scenes as well as OuyaGameObject, so let's create a script that we can use for both the game objects.

Create a new C# script and call it DontDestroyOnLoad. Edit the script as shown in the following code:

using UnityEngine;
using System.Collections;

public class DontDestroyOnLoad : MonoBehaviour {

  // Use this for initialization
  void Awake () {
    
    // Make it so this object persists
    DontDestroyOnLoad(this);
  }
}

Save the script and drag it on to your IAP game object and OuyaGameObject. This will make sure that they persist across all scenes. The final thing we need to do before we can see some results is to let OuyaGameObject know about the names of the products it will need to request information about initially. To do this, click on OuyaGameObject in Unity and the Inspector panel will show the word Purchasables in Ouya Game Object (Script). If this isn't expanded then expand Purchasables and you'll see a Size property, change it to 1. In the Element 0 label add SokobanUnlock.

If you want to sell multiple products in the future you'll need to increase the size of the Purchasables array and add the names to it. With the exception of the DEVELOPER_ID, you can see how the Inspector panel should appear in the following screenshot:

Implementing the Ouya payment framework

Make sure Ouya is connected to the Internet and run the game on it. You will see that there is now some text and three buttons on the screen. You have to wait until the In-App Purchase system is initialized before you call anything on it. You can see the status in the top-left of the screen. When you see the IAP is initialized message, you're good to go. Using the mouse-like area of the Ouya controller to bring up a mouse pointer, click on the Get Products button and you'll see your Sokoban Unlock appear. Click on the Purchase button next to it and you'll be presented with the In-App Purchase screen for the Ouya.

Note

If your Ouya developer login ID is the same as the account you logged in to your Ouya with, then you won't be charged for your In-App Purchases.

How to manage your purchases

While testing your code to check if In-App Purchases works, you'll need to buy it over and over again, thankfully Ouya took this in to consideration and made it easy to manage any purchases you have made of your own products. After you have bought your In-App Purchase, and providing your Ouya developer login is the same as the account you logged in to your Ouya with, you will be able to see your purchase on the Ouya Developer website: https://devs.ouya.tv/developers/purchases.

Getting the list of products

As we know our In-App Purchases are now set up correctly on the website and we can start to properly implement them in our game. Double-click on the OuyaShowProducts script to open it in MonoDevelop and scroll to the bottom of the file. You'll see a method called OnGUI, when you find it comment out the whole method using /* and */. This is a way of commenting out entire blocks of code without having to use // on every line.

Let's create a method that will get our products and store them in an array. At the top of our file, where the variables are defined add the following line of code:

bool iAPDone = false;

We create this Boolean as we're going to have an if statement that we only want to be called once. The if statement will need to called in the Update method. The method should be written as following:

void Update () {
  
  // Is the IAP engine initialized and have we NOT called
  // this code previously?
  if (OuyaSDK.isIAPInitComplete() && iAPDone == false) {
    
    // Make it so we don't call this code again
    iAPDone = true;
    
    // Create a List (like an array) to store our products
    List<OuyaSDK.Purchasable> productIdentifierList = new List<OuyaSDK.Purchasable>();
    
    // Loop through all the purchasables specified in the 
    // OuyaGameObject
    foreach (string productId in OuyaGameObject.Singleton.Purchasables)
    {
      // Add the product name to the List
      productIdentifierList.Add(new OuyaSDK.Purchasable(productId));
    }
    
    // Initiate a request to get the reciepts.
    // This will be used to check if we have already bought 
    // any of these items
    OuyaSDK.requestReceiptList();
    
    // Get the information about the products in the List
    OuyaSDK.requestProductList(productIdentifierList);
  }
}

Comments have been left in the code to provide a line by line explanation but the overview is:

  • Has the In-App Purchase engine initialized and not been called before
  • Set a Boolean so this code won't be called again
  • Create List to store any products we need to get information on
  • Loop through the Purchasables array in OuyaGameObject
  • Add any Purchasables to List
  • Get the list of receipts to see if any of the products have already been bought
  • Get information about all the products listed in productIdentifierList

Limiting your levels

If you're just dealing with an entitlement In-App Purchase then it's easier to build the game completely and then add in the In-App Purchase code afterwards. We've added three levels to our game already so that's a good place to start. We're going to limit it so there is only one level until you pay to unlock them all. Double-click on your Sokoban script to open it in MonoDevelop and, at the top of the script where the variables are defined, add the following line of code:

int trialLevelAmount = 1;

We now need to modify our MovePlayer method. Scroll to the bottom of the method and find the if (haveFinishedLevel()) condition. We need to edit it as shown in the following code:

if (haveFinishedLevel()) {
  
  currentLevel++;
  
  if ((PlayerPrefs.HasKey("purchased") && currentLevel < levels.Length) || currentLevel < trialLevelAmount) {
    Invoke("LoadNextLevel", 1.0f);
  } else {
    currentLevel = 0;
    Invoke("LoadTitleScreen", 1.0f);
  }
  
  PlayerPrefs.SetInt("currentLevel", currentLevel);
}

You can see that the if statement that we perform now is slightly different. We check if the player has purchased the full unlock and whether the current level is less than the full array of levels, if the game has not been purchased we only check if the current level is less than the trial-level amount. This means that the player will be sent back to the title screen when they have finished all the levels if they have bought the game, or when they finish the first level if they haven't bought it.

We have called a new method, LoadTitleScreen, which we also need to create. It's very simple, add the following code:

void LoadTitleScreen () {
  Application.LoadLevel("TitleScreen");
}

Unlocking levels for people who have paid

If the player has already paid for the unlockable levels we need to make sure they are always available. We'll achieve this by using two systems; first we'll check if int has been set in PlayerPrefs. Secondly, we'll download the receipts and see if this product has been purchased previously. We have to do both as if the game is deleted from the user's Ouya then the PlayerPrefs information will be deleted. You'll remember earlier that in OuyaShowProducts we added the Update method and, in there, called the OuyaSDK.requestReceiptList method. When the receipts come down from the server, OuyaGetReceiptsOnSuccess is called. There was already a stub method in place so let's expand on it:

public void OuyaGetReceiptsOnSuccess(List<OuyaSDK.Receipt> receipts)
{
  // Clear the current receipts List
  m_receipts.Clear();
  
  // Loop through all the receipts and verify we have one 
  // with our SokobanUnlock identifier in
  foreach (OuyaSDK.Receipt receipt in receipts)
  {
    if (receipt.getIdentifier() == "SokobanUnlock") {
      
      // If we have previously purchased the 
      // SokobanUnlock then store it in the PlayerPrefs
      PlayerPrefs.SetInt("purchased", 1);
    }
    m_receipts.Add(receipt);
  }
}

The method will pass a list of receipts, all we need to do is loop through all the receipts and see if any of them have the identifier of SokobanUnlock. If they do, then we know that the user has purchased the game and we can set int in PlayerPrefs.

Buying your product

The majority of the hard work has already been done by this point; we have our trial-level amount code, we have our receipt checking, the only thing left to do is to create a mechanism to actually buy the game. As we now drop the game back to the title screen when we finish the demo or the full game, the title screen is a perfect place to offer the game for sale. It's good User Experience (UX) to not offer the purchase to people who have already bought the game. The tasks are to add a new menu items to the title screen, call the buy method if that item is selected, and hide the item if the game has already been purchased. Let's start with the first of those.

Adding a new menu item

In Unity, double-click on your TitleScreen scene to edit it. We're going to add some more text just like we did earlier to navigate to GameObject | Create Other | 3D Text. Change the name of the new game object to Purchase Instructions. Click and drag the new text in to the Main Camera's game object and then change the following settings:

  • Set Position to X: 0 Y: -5 Z: 50
  • Set Text to Press A to Purchase
  • Set Anchor to middle center
  • Set Font Size to 50

You will also have to edit the Play Instructions game object to get it positioned correctly with the new menu entry:

  • Set the Y of the Play Instructions game object to 5

Test your game inside Unity and your title screen should look like the following screenshot:

Adding a new menu item

The buy method

We now need to create a method that is going to purchase our product upon pressing the A button on the Ouya controller, the best place for this is within our OuyaShowProducts script. Create a new method in the script called BuyFullGame and add the following code:

public void BuyFullGame () {
  if (PlayerPrefs.HasKey("purchased")) {
    // The game has already been brought, don't continue
    return;
  }
  
  foreach (OuyaSDK.Product product in m_products)
  {
    // Is this the product we want to buy?
    if (product.getIdentifier() == "SokobanUnlock") {
      OuyaSDK.requestPurchase(product.getIdentifier());
    }
  }
}

First we check that we haven't already bought the game, obviously we don't want to be able to purchase it twice. After that we loop through all the objects that we stored in our m_products list earlier when we called OuyaSDK.requestProductList. The m_products list is created for you by the code in the OuyaShowProducts script. This will then bring up the Ouya purchase dialog that you saw earlier and, upon clicking on PURCHASE, will trigger the OuyaPurchaseOnSuccess method.

To hook up the A button, we need to edit our ControlsTitleScreen script. Double-click on the ControlsTitleScreen script to edit it in MonoDevelop and go to the Update method. We're going to add an else condition to the if statement:

if (Input.GetKeyDown(KeyCode.Space) || OuyaInput.GetButtonDown(OuyaButton.O, player)){
  Application.LoadLevel("GameScreen");
} else if (OuyaInput.GetButtonDown(OuyaButton.A, player)) {
  
  GameObject iap = GameObject.Find("IAP");
  OuyaShowProducts showProductsScript = iap.GetComponent<OuyaShowProducts>();
  showProductsScript.BuyFullGame();
}

Here we have added a check for the A button, and if that is pressed, we find the IAP game object. As previously stated, the Find operation is expensive, but as this won't be called often it's fine to use in this instance. Once we have found it we need to get a reference to the OuyaShowProducts script that's attached to it, that's what the GetComponent method achieves. As we made our BuyFullGame method public, it means we call it from this script.

Once a purchase has been successful the OuyaPurchaseOnSuccess method will be called. Modify the method as shown in the following code:

public void OuyaPurchaseOnSuccess(OuyaSDK.Product product)
{
  PlayerPrefs.SetInt("purchased", 1);
  
  Application.LoadLevel("TitleScreen");
  
  // Once the purchase is complete get a list of all receipts
  OuyaSDK.requestReceiptList();
}

You can see that on a successful purchase we now store a value in PlayerPrefs, reload the TitleScreen scene, and request the receipt list. This last step is done for completeness. You'll see why we reload the scene in out next section.

Hiding menu items

We've got a functioning method to buy our level now but the message when you load the game still has the option to buy it. We need to detect if the app has already been purchased and hide the purchase option if it has. The first step for this is to delete your purchases in case you have already purchased the product, this can be done at https://devs.ouya.tv/developers/purchases.

Create a new script in the Scripts folder and call it HideIfPurchased. Click and drag the script on to our Purchase Instructions game object and then double-click on the file to edit it in MonoDevelop. Edit the Start method as shown in the following code:

void Start () {
  if (PlayerPrefs.HasKey("purchased")) {
    this.transform.gameObject.SetActive(false);
  }
}

We simply check if we have a value for purchased in our PlayerPrefs, if we do then we hide the game object. If you recall, we set purchased to 1 and reload the TitleScreen scene when OuyaPurchaseOnSuccess gets called.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.22.179