OUYA Game Development by Example Beginner's Guide (2014)
Chapter 7. Expanding Your Gameplay with In-app Purchases
In the previous chapter, Chapter 6, Saving Data to Create Longer Games, you learned how to expand your game with the saving and loading functionality using Unity's data storage tools. We also briefly touched on saving data with the OUYA API and why it's not ideal to save data related to your gameplay or user experience. OUYA's storage API is perfect, however, for tracking in-app purchases. In this chapter, you'll learn how to make your game more complex and dynamic using in-app purchases while letting your user choose which elements they want to purchase.
The latest generation of games brought with it a new revolution that changed games and re-playability forever: downloadable content, or DLC. As a developer, if you want to explore a new direction or add more features to a game that's already been released, you can upload it as DLC and your players can unlock the content by purchasing it in the marketplace.
DLC also provides a solution for players to pick and choose the features of the game they want to use. For instance, consider the Texas Hold'em poker game that featured two downloadable packages: one that enabled additional Five-card stud rules and one that enabled Omaha rules. Instead of being packaged in the main game and sold at a bundle price, the player can pay a small price for the core game and then download Five-card stud and/or Omaha only if they wish. Putting certain features of your game into separate downloadable packages will make more people willing to try your game, and features in packages that would normally overlap can instead be applied à la carte for a custom player experience.
In this chapter, we'll create a few different features to add to the cannonball game prototype we began in Chapter 5, Enhancing Your Game with Touch Dynamics. We'll discuss the following points:
· The different kinds of in-app purchases
· Setting up a product on the OUYA developer portal
· Coding in-app purchasing in your game
· Adding polish with Unity Asset Store packages
· Pricing your in-app purchases
· Monetization models
You'll need to use the OUYA developer portal to add products to your game before coding them, so we'll briefly review the developer portal in this chapter as well.
The different kinds of in-app purchases
As noted in Chapter 1, Experiencing the OUYA, the OUYA console was built around a free-to-try model that every game uploaded to the marketplace must adhere to. This means that your game must function at some level without the player having to purchase anything, which lets them determine whether they enjoy the game without having to purchase it based solely on the marketplace page. If the player enjoys the demo, they can unlock the game's full functionality by purchasing it from within the game.
The following is a screenshot of the game MirrorMoon EP, which features an option to unlock the full game from the pause menu:
Not all games have in-app purchasing in them, but a majority of those that do feature the "full game unlock" purchase option. One-time purchases such as a full game unlock are called entitlements.
Entitlements can only be purchased once per account and always remain tied to the buyer's account even if the game is uninstalled and then reinstalled. True to the name, these purchases entitle the user to the content forever.
Some examples of possible entitlement products include:
· Full game unlocks
· New level packs
· Character skins
· Additional items and weapons
Consumable items, unlike entitlements, are only usable for a limited amount of time or a certain number of uses. Consumables should never be required to complete your game, but they're good for letting your player take a shortcut or get past a hard section of the game if they want a little help. Imagine, for instance, a level-based game where you need to complete one level before advancing to the next; you could create a consumable item that allows the player to skip one level of their choosing, allowing them to buy it whenever they encounter a level that's too tricky.
Other games offer consumables that provide large amounts of in-game currency as a way to exchange money for what would otherwise require hours of gameplay. One such game on the OUYA marketplace, Guns'n'Glory WW2, features a page where you can buy Glory Coins in different bundle amounts as shown in the following screenshot:
The following are some other examples of consumable products:
· Level skips
· Single-use power-ups
· Special ammunition
· Time-limited upgrades
Consumable products are one of the most profitable ways to monetize your game because there isn't a limit on how many consumables each user can purchase, but be careful not to make them too powerful or too expensive because players may think the game's main purpose is to make money.
Setting up a product on the OUYA developer portal
In this section, we'll take what you've learned so far about in-app purchasing to create a series of products for your cannonball prototype that you created in Chapter 5, Enhancing Your Game with Touch Dynamics. These products will include an entitlement that unlocks a full version of the game and several consumables that add different abilities to the cannonballs you fire.
Time for action – preparing your game for in-app purchasing
In-app purchasing (commonly referred to as IAP in developer documentation) requires a properly configured project to work correctly. The first step of ensuring your configuration is making sure the OuyaGameObject has your developer ID in it. Perform the following steps to include in-app purchasing in a game:
1. Open a web browser and navigate to https://devs.ouya.tv/developers.
2. Use your OUYA account information to log in to the portal.
After logging in, your developer UUID will appear on the portal splash screen, depicted as a green highlight as shown in the following screenshot:
3. Copy the UUID value into your clipboard so that you can paste it later.
4. Open your TouchCannon Unity project.
5. Click on OuyaGameObject in the Hierarchy window to display it in the Inspector window.
OuyaGameObject contains a field for you to paste your developer UUID into, as shown in the following screenshot:
Now that your game is properly linked to your developer ID, you'll need to create an entry for the game on the developer portal.
6. Return to your web browser and click on the Games tab on the toolbar at the top of the developer portal.
7. Click on the Add a Game link to proceed to the game creation page.
8. Fill out the required information for your cannon game and click on Save.
After your game has been created, you'll notice a button next to its entry on the My Games page labeled Signing Key.
9. Click on the Download button underneath the label and save the key in your project directory under Assets/Plugins/Android/res/raw.
Your signing key gives your project access to the list of products on the developer portal, so now is a good time to create your first product.
10. Click on the Products tab on the toolbar at the top of the developer portal.
11. Click on the dialog that says New Product to begin creating and configuring a product for your game.
If you haven't fully completed the developer information page on your own yet, it will ask you to submit payment information and tax documents that ensure validity.
12. Click the on Payment Info link to proceed to the page where you can set your bank information. This account is where all of the money made from your in-app purchases will be transferred to.
13. Fill out the requested information. Make sure that the Location field is properly set to US or International (information required differs between the two).
The payment information page for US residents is shown below:
As you can see, not much information is required; the only two numbers required are the routing number and the account number. The account number is specific to your account only and can be found on your bank's website or by contacting your bank. The routing number is shared by all members of a bank in a certain region and can be found by simply searching the web for the routing number for your state or region.
14. Save your information and return to the Developer Info page.
15. Click on the Tax Documents link to proceed with the required legal paperwork to earn money on the OUYA marketplace.
The tax document you'll be required to fill out depends on your citizenship status, but the Tax Documents page will help you find the right one and let you submit it on the same page. Unlike the payment information, your tax information needs to be reviewed by the OUYA team, and they will send you an e-mail as soon as you've been cleared to start accepting purchases.
Once you finally reach the configuration page for a new product, the portal will let you define several different values for that product.
16. Set the Identifier value to E_FullGame.
The identifier is what we'll use to interact with this item in code. Note that we prefaced the identifier with the letter E, which we'll use to represent entitlement products.
17. Set the Name value to Full Game Unlock.
The name value is the forward-facing counterpart of our identifier; it's what our player will see when they're browsing the in-app purchases.
18. Set the Price value to $0.99 and the Type value to Entitlement.
The price here doesn't really matter because we're just creating this product for practice, but when you're adding products to any of your full games, make sure and think hard about this price before you set it.
Whatever be the price of your purchases, OUYA will take a 30 percent cut of the profits as a marketplace hosting fee. Make sure to take this into account if you're trying to set a monetary goal.
What just happened?
You've created your first product on the OUYA developer portal after taking care of the necessary tax documents and payment information. We haven't actually added the product to the game or written any code yet, but as you've seen, a little work is needed to get your game ready to handle purchases.
Above all, it's important to make sure the developer ID value on OuyaGameObject in your scene matches the UUID on the splash page of the developer portal and that the signing key of the game you're working on has been downloaded and stored inAssets/Plugins/Android/res/raw. Without either of these configured correctly, you will not be able to sell your products in your game.
Coding in-app purchasing in your game
In this section, you'll write the code to access the products you create on the OUYA developer portal. All of your products can be read and displayed using the OUYA ODK in Unity, so we'll first create a script that frames a purchase screen and then add elements to it.
Time for action – creating a purchase screen
To sell our product in our game, we first need a screen that offers the option for users to buy it. As a developer, you can put the purchase screen anywhere, but for this demonstration, we'll add it to a pause screen. Perform the following steps to create a purchase screen:
1. Create an empty GameObject to hold our pause screen code by clicking on Create Empty in the GameObject menu on Unity's toolbar.
2. Name the new object PauseManager in the Hierarchy window.
Your new object should now appear in the Inspector and Hierarchy windows as shown in the following screenshot:
Next, we'll create the pause screen window that will contain the purchase button.
3. Add a new GUI Texture component to your PauseManager object by selecting it from the Rendering category in the Add Component menu.
4. Use your preferred image editor to create a basic texture that reads PAUSED at the top and apply it to your GUI Texture component.
Make sure your texture is positioned at the proper scale and offset in the center of the screen and is easily visible as shown in the following screenshot:
The pause screen texture shown in the previous screenshot is a 800 x 600 image with -400 and -300 as the offset values for X and Y, respectively.
5. Create a new script called PauseScreen.cs, attach it to your PauseManager object, and open it in your code editor.
6. Add the following variable to your PauseScreen script above your Start function, which we will use to toggle the display of the pause screen on and off:
7. bool isPaused = false;
9. // Use this for initialization
10.void Start ()
Next, we'll need to bind input from the OUYA controller to the script so that it can toggle the paused state.
13. Import the OuyaInput.cs script from Chapter 4, Moving Your Player with Controller Input, to enable the controller input beyond the inherent touch functionality.
14. Add a call to your Update function that updates the controller API for every frame:
18. Add the following logic to call a ToggleGUI function whenever the OUYA system button is pressed:
23. if(OuyaInput.GetButton(OuyaButton.SYSTEM, OuyaPlayer.P01))
27. Add a definition for ToggleGUI in your PauseScreen script as follows:
31. Add an if/else statement to either display or hide the GUI Texture component based on the state of your isPaused variable as shown in the following code:
34. if(isPaused == false)
36. guiTexture.enabled = true;
40. guiTexture.enabled = false;
42. Add a line at the end of ToggleGUI that switches the isPaused boolean to the opposite value:
45. if(isPaused == false)
47. guiTexture.enabled = true;
51. guiTexture.enabled = false;
54. isPaused = !isPaused;
Now is a good time to check and make sure that this basic toggling functionality works before we add a button. However, we don't want our pause screen to start by default, so first we'll deactivate it.
55. Click the checkbox next to the GUITexture component in the PauseManager object's Inspector window to disable it by default until it is enabled by our script.
Your PauseManager object should now look something similar to the following screenshot in the Inspector window:
56. Build your game in the OUYA, and make sure that the pause screen can be toggled on and off using the OUYA's system button in the center of the controller.
Now that the pause screen is set up, we'll add a button to it to buy the game.
57. Add a definition to extend Unity's OnGUI function in your PauseScreen script:
61. Insert an early return that exits the function if the pause screen isn't active as follows:
66. Add the following lines to your OnGUI function to draw a button that will let the player purchase the game:
72. if(GUI.Button(new Rect(Screen.width / 2 – 50, Screen.height / 2 – 25, 100, 50), "Buy Full Game"))
74. //button functionality goes here
Your active pause screen should now look similar to the following screenshot:
What just happened?
You've successfully created a toggle able pause screen that contains a button that your player will be able to use to purchase the entitlement product that corresponds to your full game unlock. Everything is finally ready for you to insert your product into the game, so in the next section we'll be adding code that interacts with the product list that you edited in the developer portal.
Time for action – creating your first purchase function
The first step when integrating purchases is to mark any script that manages purchasing as a purchase listener. This tells the OUYA SDK that it will be handling at least one transaction and needs to be able to access the product list. Perform the following steps to create a function for purchasing:
1. Add the following lines of code to your class definition to enable it to listen for all IAP activity:
2. public class PauseScreen : MonoBehavior,
11. Add the following extension to your PauseScreen script's Awake function to mark it as a listener for all of the previous events:
12.void Awake ()
It's also good to unregister the object as soon as it's destroyed so that the SDK knows we're done with it. Conveniently, the Unity engine contains a built-in OnDestroy function that we can extend to implement the unregistration code.
18. Add the following definition to extend Unity's OnDestroy function:
Adding these interfaces to our script requires us to implement some mandatory functionality. First of all, we need to create a new line that tells Unity to include generic lists in our compilation.
25. Add the following using directive at the top of your PauseScreen script:
Next, we need to add definitions for several required functions. Don't worry about filling in the implementations for now; we'll add the functionality to the callbacks when needed.
28. Add definitions for the following functions to your script, with a return type of void for all of them:
· OuyaFetchGamerInfoOnSuccess(string uuid, string username)
· OuyaFetchGamerInfoOnFailure(int errorCode, string errorMessage)
· OuyaGetProductsOnSuccess(List<OuyaSDK.Product> products)
· OuyaGetProductsOnFailure(int errorCode, string errorMessage)
· OuyaPurchaseOnSuccess(OuyaSDK.Product product)
· OuyaPurchaseOnFailure(int errorCode, string errorMessage)
· OuyaGetReceiptsOnSuccess(List<OuyaSDK.Receipt> receipts)
· OuyaGetReceiptsOnFailure(int errorCode, string errorMessage)
Now that our script is a proper listener, we can interact with products by querying the marketplace. However, we don't want to query the marketplace before in-app purchasing has finished loading, so we'll add a boolean flag to keep track of its current status.
29. Declare the following variable after your isPaused variable:
30.bool isPaused = false;
bool isIAPReady = false;
31. Add the following logic to your Update function to manage your boolean flag for IAP:
34. if(!isIAPReady && OuyaSDK.isIAPInitComplete())
36. isIAPReady = true;
Now we're finally ready to send a purchase attempt whenever the player presses the Buy Full Game button.
38. Add the following variable to store the product:
39.bool isPaused = false;
40.bool isIAPReady = false;
41. Initialize the variable and assign it a product ID in your Start function:
44. fullGameUnlock = new OuyaSDK.Purchasable();
45. fullGameUnlock.productID = "E_FullGame";
Make sure that your product ID matches the identifier you set for it on the developer portal.
46. Return to your OnGUI function and add the following code to the button functionality region:
52. if(GUI.Button(new Rect(Screen.width / 2 – 50, Screen.height / 2 – 25, 100, 50), "Buy Full Game"))
54. //button functionality goes here
Our button now sends a purchase request to the marketplace, and we can handle all of the different outcomes from that request using the callback functions we defined earlier.
Callback functions can contain any sort of code you want, and they're useful for performing a certain set of actions whenever a predefined event occurs. For instance, if you want to display a "thank you" message after your player buys a product, you could add in GUI texture code to the OuyaPurchaseOnSuccess function.
You can also store and interact with the data that's passed into the callback function as a parameter. Be careful though, because if the function is triggered by an event that can't pass the proper data or the callback can't handle the data that it is passed, your game will trigger an error. To avoid this, write code to check whether your parameter variables are valid before directly interacting with them.
What just happened?
You've fully equipped a script to handle any kind of IAP operation your user can throw at it. The implementation of IAP can be tricky, especially considering how many configuration steps there are, which include:
· Adding listener interfaces to your class definition
· Defining callback functions for each listener
· Registering and unregistering the script as a listener
· Checking to make sure IAP has been initialized before any actions
· Including System.Collections.Generic at the top of your script
· Creating a Purchasable variable and using it to request a purchase
Have a go hero – initializing product variables dynamically
While your IAP code is now perfectly functional and acceptable, it's considered best practice to load the names and identifiers of your products dynamically so that they can be changed on the developer portal without necessitating any changes to the code base.
Right now, your Purchasable variable is hardcoded, meaning that if you changed the identifier in the developer portal, you would need to retype the productID variable assignment in your code. Instead of explicitly declaring the product, use the requestProductListfunction to get a collection of every product in your game, and then read the product ID from each element in the list to determine the Purchasable variables that you can send to requestPurchase.
Time for action – saving and loading successful purchases
As entitlements such as full game unlocks are only purchased once and are expected to be part of a game forever, we need to save the record of our purchase when it's made and check if it exists every time the game is booted up. This is where we'll make use of the OUYA storage API that we mentioned in Chapter 6, Saving Data to Create Longer Games, because the data stored in it can exist even after the game is uninstalled and reinstalled. This way, a full game will still be unlocked even on a second installation. Perform the following steps to save and load successful purchases:
1. Add the following lines to your OuyaPurchaseOnSuccess callback function to store a value for the passed-in product:
2. public void OuyaPurchaseOnSuccess(OuyaSDK.Product product)
4. OuyaSDK.OuyaJava.JavaPutGameData(product.name, product.identifier);
We used two properties of the product variable, the name and the identifier, to set the key and value of the data, respectively. This means that when we're checking whether it already exists, we can simply pass in any product name to OuyaJavaGetData and compare the return value to the identifier of that same product.
We've taken care of saving the data, so next we'll create some code to load this data. This code should verify the state of a purchase right when the game is loaded so that the game loads all of the content that the player is entitled to. We can check this data in two different ways depending on whether the OUYA is connected to the network.
Ideally, every OUYA is connected to the marketplace using whatever method they used to download the game originally, so first we'll attempt to check the data with an Internet connection.
5. Define a new function called LoadPreviousPurchases as shown:
6. void LoadPreviousPurchases()
Our LoadPreviousPurchases function will attempt to get a list of receipts of the previously purchased products from the marketplace.
9. Add the following line to the LoadPreviousPurchases to retrieve a list of receipts:
The next step is to expand our successful callback function to loop through our receipts and check if our full game unlock is in any of them.
13. Add the following lines to the OuyaGetReceiptsOnSuccess function to iterate through each returned receipt:
14.public void OuyaGetReceiptsOnSuccess(List<OuyaSDK.Receipt> receipts)
16. foreach(OuyaSDK.Receipt receipt in receipts)
20. Add the following lines to your foreach statement to check each receipt identifier against the ID of your Purchasable object:
21.public void OuyaGetReceiptsOnSuccess(List<OuyaSDK.Receipt> receipts)
23. foreach(OuyaSDK.Receipt receipt in receipts)
25. if(receipt.identifier == fullGameUnlock.productID)
27. //purchase exists
Now we can tell when the purchase exists, so we'll create a new boolean value that will reflect the lock state of the full game.
30. Add the following variable, isGameUnlocked, to your boolean values:
31.bool isPaused = false;
32.bool isIAPReady = false;
public static bool isGameUnlocked = false;
We marked this value as static because we'll want to access it easily from several different scripts.
33. Add a line to your OuyaGetReceiptsOnSuccess function that marks isGameUnlocked as true after finding a matching full game unlock receipt:
34.public void OuyaGetReceiptsOnSuccess(List<OuyaSDK.Receipt> receipts)
36. foreach(OuyaSDK.Receipt receipt in receipts)
38. if(receipt.identifier == fullGameUnlock.productID)
40. //purchase exists
41. isGameUnlocked = true;
Our game now checks the unlocked state of the game against the list of receipts, but what happens if the receipts can't be fetched due to a lack of connection or any other reason? We need to add functionality to the OuyaGetReceiptsOnFailure as well.
44. Add the following lines to the OuyaGetReceiptsOnFailure callback to check if our game has been marked as unlocked in storage:
45.public void OuyaGetReceiptsOnFailure(int errorCode, string errorMessage)
47. if(fullGameUnlock.identifier == OuyaSDK.OuyaJava.getGameData(fullGameUnlock.name))
49. //purchase exists
50. isGameUnlocked = true;
What just happened?
You now have functions that can verify the state of a game irrespective of whether the OUYA is connected to the Internet, thereby ensuring that your players get the full functionality that they paid for even if they're "off the grid."
To extend this functionality further, you can explicitly set the isGameUnlocked variable to false if the console is connected to the Internet and can't find the proper receipt. This will prevent hackers from inserting data into OUYA's local storage and tricking it into thinking they've unlocked the full game.
You can also store unlockables per-account using Unity's PlayerPrefs functionality that we used in Chapter 6, Saving Data to Create Longer Games. The OUYA storage API stores data per-app instead of per-account, so if you want to differentiate the unlockable functionality between accounts on the same OUYA, you'll have to use a combination of the storage API and PlayerPrefs.
Time for action – reflecting unlocked functionality in games
Coding in-app purchasing can be intimidating because it requires tricky code and doesn't allow for a lot of visual creation in the Unity editor, but at this point, the hardest part is behind you. Now, you get to create a functionality in your game that only gets called if the game is unlocked, and what you add to the full version of your game is completely up to you.
In this section, we'll add a different, special cannonball to our prototype that bounces on impact instead of landing firmly. Any user who has unlocked the full game will be able to fire this new type of cannonball in place of the standard one. Perform the following steps to display the unlocked functionality:
1. Create a new prefab called CannonballSpecial in your Prefabs folder.
2. Create a primitive sphere using the Create menu in the Hierarchy window and link it to your new prefab.
3. Create a new, unique material called CannonballSpecialMat in your Materials folder.
4. Import the Physic Materials package from the Asset menu and attach the Bouncy material to the Sphere Collider component of your CannonballSpecial prefab.
Your prefab should now look similar to the following screenshot in the Inspector window:
The only thing our prefab is still missing is a component that will make it affected by gravity.
5. Add a Rigidbody component to the CannonballSpecial prefab so that it's treated like a physical object as soon as we instantiate it.
Next, we'll turn to our code to incorporate the new cannonball into our existing functions.
6. Open CannonScript.cs and declare the following new variable after the original cannonball prefab:
7. public GameObject cannonballPrefab;
public GameObject cannonballSpecialPrefab;
8. Link the CannonballSpecial prefab to your new variable by dragging it into the new field in the Cannon prefab's Inspector window.
The new Cannon Script component on the Cannon prefab should now look similar to following screenshot in the Inspector window:
Next, we'll add some logic around the actual cannonball instantiation to pick an appropriate cannonball to fire based on the lock state of the game.
9. Add the following lines to replace your cannonball instantiation in the FireCannon functions:
10.void FireCannon(float xForce, float yForce)
13. GameObject newCannonball;
17. newCannonball = (GameObject)Instantiate(cannonballSpecialPrefab, cannonballPos, Quaternion.identity);
21. newCannonball = (GameObject)Instantiate(cannonballPrefab, cannonballPos, Quaternion.identity);
24. Test your new functionality with the game unlocked, either by setting isGameUnlocked to true manually in code or by building to the OUYA and attempting to purchase it in-game.
Don't worry about needing to spend money to test your in-app purchases; all purchases are free if you're using the same account that the game is registered under. However, if you have two separate accounts for developing and playing, make sure you're using the one for developing before attempting the purchase.
What just happened?
You've provided an upgraded base mechanic to your players that have unlocked the full game, which is the most simple and straightforward way to demonstrate the difference in-app purchases can make.
The more functionality you add to a product, the more likely your players are to buy it. Making a bouncy cannonball that's more likely to hit your target is a good start, but think about all of the different areas you could expand on in the full version of the game.
Adding polish with Unity Asset Store packages
In this section, we'll learn how to add a visual effect to your cannonball so that it enhances the visual complexity as well as the mechanical complexity.
Time for action – adding explosions to your cannonballs
What's a game without a few good explosions, right? You can make your cannon game much more visually appealing by adding some explosion effects to the special cannonballs. Making your own explosion effects can be tricky and time-consuming, but fortunately, there's a package on Unity Asset Store called Detonator that allows you to use basic pre-built explosion prefabs for free. Perform the following steps to add explosions:
1. Open the Window menu on Unity's toolbar and click on Asset Store to open the Asset Store window.
2. Sign in with your Unity account (or create one if you don't have one yet) to display the storefront.
Unity Asset Store features several handy packages and tools for building features outside of your own skill range. The store features code, art assets, editor tools and more, as shown in the following screenshot:
3. Type Detonator into the search bar in the upper-right corner of the Asset Store window.
4. Click on the package labeled Detonator Explosion Framework on the search results page to be taken to the store page for it, where you will see a Download button.
5. Click on Download to begin downloading the packaged files. As soon as the process has completed, Unity will automatically display an Import dialog for all of the new items.
6. Import the entire framework and close the Asset Store window.
Now we're ready to add one of the explosion prefabs to our special cannonball, but first we have to decide when it will explode. Making it explode as soon as it touches any surface will negate the bouncing functionality we coded, so we'll make a script that causes the cannonball to explode after a certain number of bounces instead.
7. Create a new script called CannonballSpecial.cs and open it in your code editor.
8. Add the following variable to track the number of times the cannonball bounces:
private int numBounces = 0;
9. Add a definition to extend Unity's OnCollisionEnter functionality where we will capture the bounces:
10.void OnCollisionEnter(Collision collidingObj)
13. Add the following line to increment the number of bounces every time the cannonball enters a collision:
14.void OnCollisionEnter(Collision collidingObj)
17. Attach the CannonballSpecial script to your CannonballSpecial prefab.
18. Add a new GameObject variable to the script to hold the explosion prefab that we're going to use:
19.private int numBounces = 0;
public GameObject explosionPrefab;
20. Link the Detonator-Simple prefab from the Detonator Explosion Framework folder to the Explosion Prefab field in the CannonballSpecial prefab's Inspector window.
The Cannonball Special script component on your CannonballSpecial prefab should now look similar to the following screenshot in the Inspector window:
21. Add the following lines to the CannonballSpecial script's OnCollisionEnter function to make it instantiate an explosion and then destroy itself after two bounces:
22.void OnCollisionEnter(Collision collidingObj)
26. if(numBounces > 2)
28. Instantiate(explosionPrefab, transform.position, transform.rotation);
31. Test your new code and watch as your special cannonballs bounce twice and then explode.
Your explosion will look similar to the one shown in the following screenshot:
What just happened?
Your special cannonballs are now accompanied by a satisfying boom whenever they explode; another example of a feature available to people who unlock the full version of your game. Get creative with your content! Make sure to add interesting features to attract the attention of free players, but don't be afraid to add some shock-and-awe functionalities to thank your paying players for their support.
You learned how to use Unity Asset Store in this section as well, which is an invaluable tool for developers to explore new ideas and download or purchase functionality that their fellow developers have created solely for the purpose of selling in a package. Who knows, maybe one day you'll be creating assets on the asset store yourself!
Pricing your in-app purchases
Pricing is a tough subject in game development. How do you put a concrete price on various elements of your hard work? Triple-A games typically stay close to a standard pricing, but when it comes to indie titles (and especially in-game content packs), pricing is entirely up to the developer.
There's no right answer to how much you should charge for your game, but here are a few tips to get you started.
Setting the price of your full game
When you're deciding how much it will cost your players to unlock the full game or any new DLC packages, there are a few aspects you should consider. These are complexity, length, and replay value, described as follows:
· Complexity: At some level, the work that you put into your game should be reflected in its price. This doesn't necessarily mean front-facing complexity but is more about the time and effort it took to create the game. You can usually sell a three-dimensional game for more than a two-dimensional game, charge more for a game that includes realistic physics simulations, and up the price for each additional mode that your game offers.
· Length: The price your player pays for your game should give them a proportional amount of expected play time. For instance, no matter how good your game is, it would be unreasonable to charge $10 for 10 minutes of play. It's a good idea to play through some games fully and note how long it takes to explore every facet of each before comparing their prices. Again, there's no set standard that links gameplay length and price, but use your best judgment to find a happy medium that's feasible for your audience and still earns you some money for your work.
· Replay value: Your game doesn't necessarily have to have a long story or extensive progression to garner a lot of play time. Some games keep players coming back with replay value, or the desire of the player to repeat the same level/procedure over and over. In Chapter 1, Experiencing the OUYA, you played Canabalt, which is an endless runner game built on replay value; the mechanics never change and the environments remain basically the same, but the player is expected to play several times to try to get the top score.
Replay value is commonly high in games that feature the multiplayer functionality, such as Towerfall. Note in the following screenshot how the level is simple enough to fit on one screen without panning, but it's replay value is high because pitting a player against another player is almost certain to create a unique experience every time.
Picking a monetization model
Just as there are two different kinds of products that you can sell in your OUYA game, there are two main monetization models that you can choose from to structure your in-app purchases: paygate and free-to-play. Both of these models focus primarily on one product type or the other, and they can make a big difference depending on the experience you're trying to convey. They are described as follows:
· Paygate: The paygate model is centered around the idea of a full game unlock entitlement. As the name implies, the player is met with a "gate" or "wall" after playing the game for a short time that asks them if they want to pay to unlock the full game. If they pay, the rest of the game is immediately unlocked. Payment isn't required, so players don't have to spend money on a game they don't enjoy, but if they don't pay, they are limited to the functionality of the introductory stages. Further functionality may be added to the game with entitlement products that represent the DLC content. Despite a strong focus on entitlement products, a game made under the paygate model can also feature consumables, such as potions and weapons, as long as they're still applicable to players who may own the full game but not any DLC.
· Free-to-play: Free-to-play games are built on the condition that it's possible to experience the full game without paying a cent. Consumables are typically abundant in free-to-play games but none are required to add functionality to the game; they only make certain aspects of the game quicker or easier for purchasing players. While games under the paygate model can use consumables, games under the free-to-play model can't really make use of entitlements because they create a major disconnect between paying and non-paying players. It's important to avoid neglecting your free players because even if they don't spend as much money as other players, a positive experience will still help your game spread from them to all of their potentially paying friends.Guns'n'Glory, one of the games we looked at earlier in this chapter, is a free-to-play game. The game features several consumables to purchase, but their sole function is to immediately pay out a certain amount of in-game currency to the player, which a free player could easily earn by playing and avoid having to pay.
Beware of an imbalance of power between non-paying players and paying players in your multiplayer games. You may want to remove paid power-ups in your multiplayer mode all together, or test them extensively to ensure players cannot gain the upper hand over their opponents using money alone. Nobody likes a pay-to-win game.
Have a go hero – tying it all together with more products
Use everything you've learned about in-app purchases in this chapter to create at least two more products that change your game. As we've been working with entitlements, try creating a consumable; they're processed the same way in code but their utility and philosophy differs greatly (make sure you brush up on the monetization models for a good guideline). The following are some ideas of functionality that you can add with in-app purchases in your cannonball game:
· A cannonball that splits off into several others
· Use the logic you used to instantiate an explosion and instead instantiate several new cannonballs
· Apply semi-random velocity to the child cannonballs to create a widespread yet inaccurate buckshot effect
Try adding a call to GameObject.Instantiate in an extension of the cannonball's OnDestroy function.
· A cannonball that doesn't fall as quickly for more precise shots
· Edit the mass values of this cannonball's Rigidbody component to drastically change the effect gravity has on it
The mass property can be viewed and changed in the cannonball prefab's Inspector window. Try changing it in the middle of a game to see how different values affect the cannonballs.
· A consumable item that makes the next 10 cannonballs you fire twice the default size
· Keep an integer variable of how many special shots the user has remaining
· Double the scale value for each special shot and display a GUI message when the player runs out of special shots
If the consumable item is active and the user still has special shots, call the transform.Scale function from the Start function of the cannonball script.
The only limit to your in-app purchases is your imagination. Add in several independent packages so that your players can pay what they want for the features they enjoy without having to spend too much on features that they don't want included.
Pop quiz – talking shop
Q1. Which of the following categories of a product are most common in games that follow the "paygate" monetization model?
Q2. Which of the following categories of a product are most common in games that follow the "free-to-play" monetization model?
Q3. What property of a Purchasable object is used to access the corresponding item from the OUYA developer portal?
In this chapter, you learned all the steps involved in expanding a game with in-app purchases. In-app purchases enable you to make your game more complex with an additional functionality such as letting players pick new mechanics à la carte and providing one-time-use items to get players out of a tough spot or to the next level more quickly.
You also learned about Unity Asset Store, accessible through the Window menu in Unity. The asset store is a community-driven site where developers can upload packaged Unity tools, either for free or for a price. If you ever want to implement new mechanics that you don't have any experience with and you don't know where to start, Unity Asset Store is a good jumping-off point.
Now that you've had a chance to experience every element your games can contain, we'll discuss packaging your final games and preparing them for deployment on the OUYA marketplace in the next chapter.