Introduction
In this post, we’re going to put the finishing touches to our item shop!
In the previous post, we created a new scene for our Item Store
and added the basic UI for the scene.
With the UI in place, we’re going to create the appropriate scripts today to:
- define a data model of what our power-up looks like and their costs
- save and load the player’s power-up level
- purchase our power-ups
Today’s going to be pretty script heavy, so let’s get to it.
Step 1: Creating Data Models for the Power-Ups
Step 1.1: Define What We Are Creating
We want to be able to buy upgrades for our power-ups, however, to do that, we need to represent something in the code that we can use.
Our goal is to be able to create a database of the sort to be able to define our power-up at each level.
We’re not going to do anything fancy to store this information like storing it in a database or a text file. Instead, we’re just going to store it in a class that we can access. We’ll see what I mean later.
What sort of representation do we need to use for our data? Here’s a couple that fits all our power-ups.
Level
– what is the level of this upgrade Effect
– how effective is our power-up at the specific level, specifically, for magnet
we’re going to increase our range, for multiplier
the multiplier we use, and for invincible
the speed we travel at Cost
– how many coins does it cost to buy the upgrade
Those three criteria will be used to define what our power-ups will look like.
Step 1.2: Creating the Script
Now that we have defined the 3 criteria that we are looking for, let’s translate this into code.
- Create a new script called
PowerUpsDatabase
, just like our DataManager
, this will be a static
class that we can reference whenever we want to get information.
Here’s what it looks like:
public class PowerUpModel
{
public int Level;
public float Effect;
public int Cost;
public PowerUpModel(int level, float effect, int cost)
{
this.Level = level;
this.Effect = effect;
this.Cost = cost;
}
}
public static class PowerUpsDatabase {
public static PowerUpModel[] MagnetPowerUps = {
new PowerUpModel(0, 15, 50),
new PowerUpModel(1, 20, 100),
new PowerUpModel(2, 25, 200),
new PowerUpModel(3, 30, 400),
new PowerUpModel(4, 35, -1)
};
public static PowerUpModel[] MultiplierPowerUps =
{
new PowerUpModel(0, 2, 50),
new PowerUpModel(1, 3, 100),
new PowerUpModel(2, 4, 200),
new PowerUpModel(3, 5, 400),
new PowerUpModel(4, 6, -1)
};
public static PowerUpModel[] InvinciblePowerUps =
{
new PowerUpModel(0, 2, 50),
new PowerUpModel(1, 2.25f, 100),
new PowerUpModel(2, 2.5f, 200),
new PowerUpModel(3, 2.75f, 400),
new PowerUpModel(4, 3, -1)
};
}
Looking at the Code
There are two classes in this script:
The first one is PowerUpModel
in which we are using to store the important values that we will use for each of our power-up upgrades: the level, the effect, and the cost to purchase. I added a constructor that we can use to pass in the level, effect, and cost variables when we create an instance of this class. All we do in the constructor is use the values we passed in and store it inside our class.
Next, we have PowerUpsDatabase
which is a static
class that any script can access that we create 3 arrays of PowerUpModel
, we create 3 arrays, one for each of our upgrades. For each of our arrays, I created the initial PowerUpModels
that we will use for our item store.
Now you might be wondering what the effect value will be used for. We won’t use them in today’s post, but essentially:
Magnet
– the effect will be used to determine the radius of our Magnet Collider
. As we improve our magnet, our collection radius will get bigger and bigger Multiplier –
the effect will be used to determine the multiplier value that we will multiply our score and coin with Invincible –
the effect of the invincible will be used to determine the speed that the player will fly. At level 0, we will go 2x faster up to 3x faster at level 4.
None of the code here has any specific functionalities, they’re more like references that we can refer to later to figure out what effects we should use for the player.
Step 2: Save the Player’s Power-Up Level
Step 1.1: Store the Player’s Power-Up
After we have created the different upgrade levels for each of our three power-ups, we now need to know what level the player is at. This is the purpose of the Level
field inside PowerUpModel
.
Like how we store the player’s coin
and score
, we can store our power-up upgrade level in the exact same way.
Let’s make the changes to DataManager
. Here’s what it looks like:
using UnityEngine;
public class DataManager
{
private static string _coinKey = "Coin";
private static string _scoreKey = "Score";
private static string _magnetLevelKey = "Magnet";
private static string _multiplierLevelKey = "Multiplier";
private static string _invincibleLevelKey = "Invincible";
public static int LoadCoin()
{
return PlayerPrefs.GetInt(_coinKey, 0);
}
private static void SaveCoin(int coin)
{
PlayerPrefs.SetInt(_coinKey, coin);
}
public static int LoadScore()
{
return PlayerPrefs.GetInt(_scoreKey, 0);
}
private static void SaveScore(int score)
{
PlayerPrefs.SetInt(_scoreKey, score);
}
public static void AddCoin(int coin)
{
int totalCoin = LoadCoin() + coin;
SaveCoin(totalCoin);
}
public static void BuyUpgrade(int coin)
{
int currentCoin = LoadCoin();
if (currentCoin >= coin)
{
SaveCoin(currentCoin - coin);
}
}
public static void AddNewScore(int score)
{
if (LoadScore() < score)
{
SaveScore(score);
}
}
public static int LoadMagnetLevel()
{
return PlayerPrefs.GetInt(_magnetLevelKey, 0);
}
public static int LoadMultiplierLevel()
{
return PlayerPrefs.GetInt(_multiplierLevelKey, 0);
}
public static int LoadInvincibleLevel()
{
return PlayerPrefs.GetInt(_invincibleLevelKey, 0);
}
public static void IncreaseMagnetLevel()
{
IncreaseLevel(_magnetLevelKey, PowerUpsDatabase.MagnetPowerUps.Length - 1);
}
public static void IncreaseMultiplierLevel()
{
IncreaseLevel(_multiplierLevelKey, PowerUpsDatabase.MultiplierPowerUps.Length - 1);
}
public static void IncreaseInvincibleLevel()
{
IncreaseLevel(_invincibleLevelKey, PowerUpsDatabase.InvinciblePowerUps.Length - 1);
}
private static void IncreaseLevel(string upgradeKey, int upgradeMaxLevel)
{
int currentLevel = PlayerPrefs.GetInt(upgradeKey, 0);
if (currentLevel < upgradeMaxLevel)
{
PlayerPrefs.SetInt(upgradeKey, currentLevel + 1);
}
}
}
Looking at the Fields
The fields are straightforward, our data manager is going to keep track of our upgrade level for our three power-ups: magnet
, multiplier
, and invincible
. The fields are the keys to access our database entry.
Walking Through the Code
LoadMagnetLevel, LoadMultiplierLevel, LoadInvincibleLevel()
are all public static
functions that return to us the current level of the upgrades for the user. IncreaseMagnetLevel, increaseMultiplierLevel, IncreaseInvincibleLevel()
are all public static
functions that call IncreaseLevel
with the specific power-up we’re going to increase and the max level from our PowerUpDatabase
, for which we just use the length – 1
. Yes, we could have just put in 4 since our power-ups are always size 5
, however, if we ever decide to make changes, we’ll have to refactor our code. This makes our code future proof. - Finally, we have
IncreaseLevel()
which is a private
general function that will increase our power-up upgrade level that is called by the three functions mentioned above. The code is written this way to prevent us from carelessly increasing our level. For further checks, we make sure that the current level of the upgrade is lower than the max level. If it is, we change our key to be 1
higher than its current value - We also added
BuyUpgrade()
we’ll be using this shortly, but we take in the cost of the upgrade, make sure that we can afford the upgrade and if we can, we save our new coin
total to our PlayerPrefs
.
Step 3: Add the Power-Up UI Script
Step 3.1: Create the Script
We have a model in code that we can use for our power-ups, we have a way for us to keep track of our current levels, now it’s time for us to create the script that we will use when interacting with our UI.
Create a new ItemStoreCanvasController
script on our Item Store Canvas
game
object.
This script will define public
functions that we will bind to Pointer Click events for clicking our button. Alongside that, we’ll also be writing some logic to display the text in our UI.
Here’s what the ItemStoreCanvasController
looks like:
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ItemStoreCanvasController : MonoBehaviour {
public Text CoinText;
public Button MagnetButton;
public Button MultiplierButton;
public Button InvincibleButton;
private Text _magnetBuyText;
private Text _multiplierBuyText;
private Text _invincibleBuyText;
void Start ()
{
_magnetBuyText = MagnetButton.GetComponentInChildren<Text>();
_multiplierBuyText = MultiplierButton.GetComponentInChildren<Text>();
_invincibleBuyText = InvincibleButton.GetComponentInChildren<Text>();
UpdateUI();
}
private void UpdateUI()
{
CoinText.text = "Coin: " + DataManager.LoadCoin();
UpdateUpgradeButton(DataManager.LoadMagnetLevel(),
MagnetButton, _magnetBuyText, PowerUpsDatabase.MagnetPowerUps);
UpdateUpgradeButton(DataManager.LoadMultiplierLevel(),
MultiplierButton, _multiplierBuyText, PowerUpsDatabase.MultiplierPowerUps);
UpdateUpgradeButton(DataManager.LoadInvincibleLevel(),
InvincibleButton, _invincibleBuyText, PowerUpsDatabase.InvinciblePowerUps);
}
private void UpdateUpgradeButton(int upgradeLevel, Button button,
Text text, PowerUpModel[] powerUpModels)
{
if (upgradeLevel >= powerUpModels.Length - 1)
{
button.interactable = false;
text.text = "Maxed";
return;
}
int coin = DataManager.LoadCoin();
int cost = powerUpModels[upgradeLevel].Cost;
text.text = cost.ToString();
if (coin < cost) { button.interactable = false; } }
public void BuyMagnet() { print("buy magnet");
int coin = DataManager.LoadCoin(); int level = DataManager.LoadMagnetLevel();
int cost = PowerUpsDatabase.MagnetPowerUps[level].Cost; if (coin >= cost)
{
DataManager.BuyUpgrade(cost);
DataManager.IncreaseMagnetLevel();
UpdateUI();
}
}
public void BuyMultiplier()
{
int coin = DataManager.LoadCoin();
int level = DataManager.LoadMultiplierLevel();
int cost = PowerUpsDatabase.MultiplierPowerUps[level].Cost;
if (coin >= cost)
{
DataManager.BuyUpgrade(cost);
DataManager.IncreaseMultiplierLevel();
UpdateUI();
}
}
public void BuyInvincible()
{
int coin = DataManager.LoadCoin();
int level = DataManager.LoadInvincibleLevel();
int cost = PowerUpsDatabase.InvinciblePowerUps[level].Cost;
if (coin >= cost)
{
DataManager.BuyUpgrade(cost);
DataManager.IncreaseInvincibleLevel();
UpdateUI();
}
}
public void StartGame()
{
SceneManager.LoadScene(0);
}
}
It’s been a while since we’ve seen a new long script! Let’s dig into it.
Looking at the Fields
public Text CoinText
– The Text
UI that we use for our string
public Button MagnetButton
– The Button
UI for the Magnet Button
public Button MultiplierButton
– The Button
UI for the Multiplier Button
public Button InvincibleButton
– The Button
UI for the Invincible Button
private Text _magnetBuyText
– The Text
UI for the text component in the Magnet Button
private Text _multiplierBuyText
– The Text
UI for the text component in the Multiplier Button
private Text _invincibleBuyText
– The Text
UI for the text component in the Invincible Button
Walking Through the Code
There’s quite a bit of code we have this time around. To help make sense of this code, we have to understand that the Controller
has two purposes:
- Show the correct values for our UI. This includes displaying the accurate coins and shop upgrade costs when we buy something. As an extra, I also made the button appear not interactable if we can’t buy the upgrade anymore.
- Separate
public
click functions that will get called when a user clicks on the buttons we have in our UI. This includes our 3 buy buttons and our start game button.
Now that we understand this, let’s walk through the code.
- In
Start()
, we set up our script by getting the Text
components from our Button
and then we call UpdateUI()
to set up the values of our UI. - In
UpdateUI()
, we set to display our coin
value and then call UpdateUpgradeButton()
with information specific to our upgrade so we can write re-usable code to display our Button
s correctly. - In
UpdateUpgradeButton()
, we are given the Button
and Text
of the button we want to change along with other information like which PowerUpModel
we’re using and its current level. We disable our button if we’re at the max level or if we can’t afford the upgrade. We display the cost of the upgrade on button text, otherwise, we say Max
if we already have the highest upgrade. BuyMagnet
, BuyMultiplier
, and BuyInvincible
are all very similar. These are all public
functions that will get bound to their corresponding buttons. When we click on them, we will check to see if we can afford the upgrade and if we can, we’ll call our DataManager
to decrease our coin count and increase our upgrade level. Once we do that, we update our UI to reflect our new state. StartGame()
is the function we bind to our Game Start
button.
In this function, we simply start to go back to our main
scene to play the game.
Setting Up the Script
Almost there! We have our script now, we just need to set it up.
- Drag our Coin Text to the Coin Text slot, Buy Magnet to the Magnet Button slot, Buy Multiplier to the Multiplier Button Slot, Buy Invincible to the Invincible Button slot in our Item Store Canvas Controller script.
Here’s what it looks like:
And then, we need to bind each of our Buttons to call our public
function from this script.
- In
Buy Magnet
, create a new component called Event Trigger
- Create a new
Pointer Down
Event - Add a new event to it and drag the
Item Store Canvas
game object to the slot - Next, select the function to be called when this event gets fired, look for
Item Store Canvas Controller
> BuyMagnet
Do this for the other buy button and the Game Start button.
Here’s an example of what one looks like:
End of Day 99
Once we have finished all of this, play the game, earn some money (or cheat like I did and put DataManager.AddCoin(10000)
in Start()
of any script) and then buy some upgrades.
Here’s what our result looks like:
Pretty neat, right? As you can see, I already maxed out 2 of my upgrades and will be working on the Invincible
one next.
The only problem is that these upgrades don’t really do anything in the game. In our final post in the 100 days challenge, we’re going to implement the upgrade level system to our game. It’s going to be glorious! I’ll see you all next time!
Day 98 | 100 Days of VR | Day 100
Home
CodeProject
The post Day 99 of 100 Days of VR: Endless Flyer – Creating A Database For Power-Up Upgrades appeared first on Coding Chronicles.