Brick Breaker Example Project
Aboutβ
The brick breaker Example project is included with the Skillz Unity package. The following document explains how to run the example project as well as how the example project Implements the Skillz SDK and features including match parameters, progression, fairness, anti-cheat measures, and other best practices.
NOTE: All the pertinent files are under Assets/Skillz/Examples/Brick Break
.
Running the Example Projectβ
Running in the Unity Editorβ
The brick breaker example project can be run in the Unity editor using the Skillz SIDEkick. It is recommended to run the example project in this way as the setup process is much simpler.
Go to
File > Build Settings
.Add the following scenes into the 'Scenes in Build' in the build settings:
(The following can be found in theAssets/Skillz/Examples/Brick Break/Scenes
folder)
BB_StartMenu
BB_Game
BB_ProgressionRoom
2a. Make sure the BB_StartMenu
scene is at index 0
Open the
BB_StartMenu
scene. You will be prompted to import TMP Essentials. ClickImport TMP Essentials
.Go to
Skillz > Settings
from the menu bar.Under the SIDEkick section add the following SIDEkick templates:
(The following can be found in theAssets/Skillz/Examples/Brick Break/SIDEkick
folder)
BB Match Types
BB Match Parameters
BB Players
BB Progression Responses
BB Seasons
Click the
Launch Game
button.
Running on a Mobile Deviceβ
It is recommended to run the example project in the Unity editor using SIDEkick as it is quicker to set up. To run the brick breaker example on a mobile device, more setup is required. Instructions on how to run on a mobile device can be found at the end of this document in the Running the Example Project on a Mobile Device section.
Launching Skillz From the Start Menuβ
The BB_Start menu scene in the Skillz/Examples/Brick Break/Scenes
folder makes use of the Skillz Manager
prefab to launch Skillz. When the start button is clicked the Skillz UI is launched. When a user in the Skillz UI starts a match, returns to the start menu, or enters the progression room, the corresponding scene is launched.
NOTE: The chosen scenes needs to be in the Build Settings
under the Scenes in Build
section.
The Skillz Manager
in the example project also includes references to a Skillz Example Manager Logic
script. This script currently only has log statements, but this script can be used to add additional logic to these scene transitions.
Submitting the Scoreβ
The brick breaker example project handles score submission in the BB_SkillzMatchManager
script (Assets/Skillz/Examples/Brick Break/Scripts/BB_SkillzMatchManager
). The score is submitted with SkillzCrossPlatform.SubmitScore()
method. If the score is submitted successfully then the SkillzCrossPlatform.ReturnToSkillz()
method is called on the next update. This will return the user to the Skillz UI. If the Score submission is unsuccessful then the SkillzCrossPlatfrom.DisplayTournamentResultsWithScore()
fallback method is called. This will ensure the userβs score is not lost. More information on score submission can be found here.
// ...
private void Update()
{
if (hasSubmittedScore)
{
MatchComplete();
}
}
public void SubmitScore()
{
SkillzCrossPlatform.SubmitScore(GetScore(), OnScoreSubmitSuccess, OnScoreSubmitFailure);
}
private void OnScoreSubmitSuccess()
{
Debug.Log("Score Submit - Success");
hasSubmittedScore = true;
}
//If the submit score fails then call fallback score submission
private void OnScoreSubmitFailure(string reason)
{
Debug.Log("Score Submit - Failure: " + reason);
SkillzCrossPlatform.DisplayTournamentResultsWithScore(GetScore());
}
public void MatchComplete()
{
Debug.Log("Returning to Skillz UI");
SkillzCrossPlatform.ReturnToSkillz();
}
private int GetScore()
{
return BB_Managers.matchManager.GetTotalScore();
}
// ...
Using Match Parameters to Support Multiple Game Modesβ
The Skillz brick breaker example uses match parameters to alter the rules of the match based on the type of match the user selects. These parameters are:
game_mode
Sets the mode as either a delux match (mulitpliers added to bricks) or practice match.time
The time given for the player to complete the match.multi_ball
Whether the game spawns extra balls at set time intervals.
Setting up Match Parameters in SIDEkickβ
When running your game within the Unity editor, the match parameters are set up in the Sidekick settings. Select Skillz > settings
, go to the SIDEkick
section, then double click on the selected Match Parameter Templates
. The templates will then appear in the inspector where they can be edited as needed.
When after launching the game the templates will be available under the match parameters dropdown in the simulated Skillz UI. Select the desired template and enter the match.
Setting up Match Parameters on the Developer Consoleβ
When you run the game on a mobile device, the match parameters need to be set up along with the tournament types in the developer console (https://developers.skillz.com). To modify the match parameters click on your game then click the Optimize
tab. Under the Customize Gameplay
section, select Tournament
. The instructions to run this project on a mobile device can be found here.
Querying Match Parameters in the Game Sceneβ
Match parameters can be accessed in the game code by calling the SkillzCrossPlatform.GetMatchRules()
method. This will return a Hashtable with key-value pairs corresponding to the match parameters set up in the developer console or SIDEkick settings. The values of these parameters are then used to drive changes in the rules of the match. This is done in the BB_MatchManager
script (Assets/Skillz/Examples/Brick Break/Scripts/BB_MatchManager
).
// ...
private Hashtable matchParameters;
private float matchTime = 60;
private bool isMultiBall = false;
private void SetMatchParameters()
{
matchParameters = SkillzCrossPlatform.GetMatchRules();
if (matchParameters.ContainsKey("game_mode"))
{
gameMode = (string)matchParameters["game_mode"];
}
if (matchParameters.ContainsKey("time"))
{
timeRemaining = int.Parse(((string)matchParameters["time"]));
matchTime = timeRemaining;
}
if (matchParameters.ContainsKey("multi_ball"))
{
if ((string)matchParameters["multi_ball"] == "true")
{
isMultiBall = true;
}
}
}
// ...
Ensuring Fairnessβ
On the Skillz platform it is critical that the games be fair. Both players must be presented with the same opportunity to achieve a score. Care must be taken to ensure one player does not have an advantage over the other.
This means that any kind of randomness in the game that affects gameplay must be calculated the same for each player. The Skillz SDK provides a set of SkillzCrossPlatform.Random
methods to achieve this. If these calls are made in the same order for each player, they will return the exact same result.
In the Skillz Brick Breaker example, a fairness Script (Skillz/Examples/Brick Breaker/Scripts/BB_Fairness
) is used to ensure the game is set up in the same way for each player. The fairness script has a GenerateFairGame()
function as seen below:
// ...
public static BB_GameBoard GenerateFairGame(List<BB_GameBoard> possibleGameBoards, bool isDeluxMatch, Transform gameBoardParent)
{
//Choose Game Board
int gameBoardIndex = SkillzCrossPlatform.Random.Range(0,possibleGameBoards.Count);
BB_GameBoard chosenGameBoard = possibleGameBoards[gameBoardIndex];
//Create the game board
BB_GameBoard gameBoard = GameObject.Instantiate(chosenGameBoard, gameBoardParent);
//Choose Brick Multiplier Locations
if (isDeluxMatch)
{
for (int i = 0; i < 6; i++)
{
int brickChoice = SkillzCrossPlatform.Random.Range(0, gameBoard.NumberOfBricks());
gameBoard.GetBrick(brickChoice).SetMultiplier(2);
}
}
//Generate List of ball perturbations
randomBallPerturbations = new List<Vector2>();
for (int i = 0; i < 50; i++)
{
Vector2 randomPerturbation = SkillzCrossPlatform.Random.InsideUnitCircle() * .1f;
randomBallPerturbations.Add(randomPerturbation);
}
return gameBoard;
}
// ...
A random integer is generated using SkillzCrossPlatform.Random.Range()
and this is used to pick one of the possible game boards. This will ensure the amount, positions, and type of bricks are the same for both players.
If the game is a delux match, SkillzCrossPlatform.Random.Range()
is used to pick which bricks will have a score multiplier (eg. X2). This ensures the locations of the multipliers are the same for each player in the match.
And lastly a list of ball perturbations is generated using SkillzCrossPlatform.Random.InsideUnitCircle() these. These are used to set the initial velocity for balls that spawn during the match.
It is important to note how the fairness setup has been consolidated into one script. There are no other calls to SkillzCrossPlatform.Random anywhere else in the game code. This ensures that the SkillzCrossPlatform.Random calls happen deterministically (in the same order and therefore with some result) for each player in the match.
Anti-Cheat Measuresβ
When integrating with Skillz it becomes extremely important to take precautions against potential cheating in a game. To maintain a fair and competitive gameplay experience, we recommend that developers take anti-cheating measures before going live with Skillz. More Information on anti-cheat measures can be found here.
The Brick Breaker example app duplicates and obfuscates important game data to prevent cheaters from modifying the data through memory modification. This is accomplished by using the BB_AntiCheatVault
class (Assets/Skillz/Examples/Brick Break/Scripts/BB_AntiCheatVault
).
// ...
public class BB_AntiCheatVault
{
private int xorCode1;
private int xorCode2;
private int value;
private int valueCheck;
public BB_AntiCheatVault()
{
xorCode1 = Random.Range(0, int.MaxValue);
xorCode2 = Random.Range(0, int.MaxValue);
value = 0 ^ xorCode1;
valueCheck = 0 ^ xorCode2;
}
public void Set(int newValue)
{
value = newValue ^ xorCode1;
valueCheck = newValue ^ xorCode2;
}
public int Get()
{
return value ^ xorCode1;
}
public bool IsValid()
{
return (value ^ xorCode1) == (valueCheck ^ xorCode2);
}
}
// ...
Instead of storing an important variable like score in a regular variable it is stored in a BB_AntiCheatVault
. This can be seen in the BB_MatchManager
script (Assets/Skillz/Examples/Brick Break/Scripts/BB_MatchManager
).
// ...
private BB_AntiCheatVault score;
public void AddScore(int deltaScore)
{
score.Set(score.Get() + deltaScore);
BB_Managers.matchUIManager.SetScore(GetScore());
}
// ...
When the score is queried it is then checked for validity to make sure it has not been altered during the game.
// ...
public int GetScore()
{
if (!score.IsValid())
{
return 0;
}
return score.Get();
}
// ...
Pausing the Gameβ
When Pausing the game it is important to not display the game board in the background. The Player could then cheat by continually pausing and planning their next move. For this reason, the brick breaker pause menu displays on top of the game board and completely obscures the current state of the game.
Creating a Progression Systemβ
Progression adds a critical component to help drive the success of your game. The Progression methods allow you to store, recall, and update player data at any time within the game, unlocking personalized player experiences.
Progression Roomβ
The Skillz brick breaker example includes an example of a simple progression system. Various user statistics are tracked over many matches. Earned achievements are displayed in a dedicated progression room (Assets/Skillz/Examples/Brick Break/Scenes/BB_ProgressionRoom
).
First we will take a look at the progression room and how the progression data is queried. The BB_ProgressionManager
script (Assets/Skillz/Examples/Brick Break/Scripts/BB_ProgressionManager.cs
) is used to interact with the Skillz progression API.
// ...
private void Start()
{
defualtDataKeys = new List<string>();
defualtDataKeys.Add("games_played");
defualtDataKeys.Add("cash_games_played");
defualtDataKeys.Add("games_won");
defualtDataKeys.Add("cash_games_won");
defualtDataKeys.Add("best_score_lifetime");
defualtDataKeys.Add("average_score");
defualtDataKeys.Add("player_level");
defualtDataKeys.Add("skillz_level");
defualtDataKeys.Add("install_date");
customDataKeys = new List<string>();
customDataKeys.Add("bricks_broken");
customDataKeys.Add("bricks_cleared");
customDataKeys.Add("only_bronze_remaining");
customDataKeys.Add("15_time_remaining");
customDataKeys.Add("no_ball_lost");
//Retrieve the progression data from Skillz
GetProgressionData();
}
private void GetProgressionData()
{
SkillzCrossPlatform.GetProgressionUserData(ProgressionNamespace.DEFAULT_PLAYER_DATA,
defualtDataKeys,
OnSuccessDefault,
OnFailure);
SkillzCrossPlatform.GetProgressionUserData(ProgressionNamespace.PLAYER_DATA,
customDataKeys,
OnSuccessCustom,
OnFailure);
}
// ...
On Start()
, the data keys lists are created and SkillzCrossPlatfrom.GetProgressionUserData()
is called twice. Once to get the default progression data and Once to get the custom progression data. Notice that the data keys in the defaultDataKeys
list and customDataKeys
list match the data keys in the progression responses section of the SIDEkick settings and the data keys setup in the developer console. When the call returns successfully, the OnSuccessDefault
and OnSuccessCustom
methods are called and the defaultProgressionData
and customProgressionData
are updated respectively.
// ...
private Dictionary<string, SkillzSDK.ProgressionValue> defaultProgressionData;
private Dictionary<string, SkillzSDK.ProgressionValue> customProgressionData;
// ...
//Store the default progression data locally
private void OnSuccessDefault(Dictionary<string, ProgressionValue> data)
{
foreach (string key in data.Keys)
{
defaultProgressionData.Add(key, data[key]);
}
hasRevievedDefaultData = true;
}
//Store the custom progression data locally
private void OnSuccessCustom(Dictionary<string, ProgressionValue> data)
{
foreach (string key in data.Keys)
{
customProgressionData.Add(key, data[key]);
}
hasRecievedCustomData = true;
}
// ...
Now that the progression values are stored locally, they can be utilized by the progression room controller (Assets/Skillz/Examples/Brick Break/Scripts/BB_ProgressionRoomController
) to display data in the progression room.
Updating Progression Dataβ
When a player completes a match in the Brick Breaker example, the progression data is updated to reflect the player's performance. This is accomplished using the same Progression Manager (Assets/Skillz/Examples/Brick Break/Scripts/BB_ProgressionManager.cs
) as is in the progression room scene. The progression data is queried on Start()
and stored locally as seen above. Retrieving the progression data is necessary because the new progression data values is based upon the old values added to the new values (eg. bricks_broken
goes from 100 to 120 if 20 bricks are broken).
A list of progression data updates is then tracked locally. Updates are added to the list using the SetData()
method. The updates are stored locally to reduce the amount of calls to SkillzCrossPlatform.UpdateProgressionData()
, as only one call is needed at the end of the match to update the data.
// ...
private Dictionary<string, object> customProgressionUpdates;
// ...
public void SetData(string dataKey, object value)
{
if (customProgressionUpdates.ContainsKey(dataKey))
{
customProgressionUpdates[dataKey] = value;
}
else
{
customProgressionUpdates.Add(dataKey, value);
}
}
// ...
When the match is completed the updates are pushed to Skillz using the SkillzCrossPlatfrom.UpdateProgressionData()
method.
// ...
//Save the progression data to Skillz
public void UpdateProgressionData()
{
SkillzCrossPlatform.UpdateProgressionUserData(ProgressionNamespace.PLAYER_DATA,
customProgressionUpdates,
OnSuccessUpdate,
OnFailure);
}
// ...
NOTE: Only the custom progression data is updated. The default progression data is automatically updated by Skillz and cannot be updated manually using Skillz API calls.
Running the Example Project on a Mobile Deviceβ
Select βAdd new gameβ
Fill in name and description, select
cross-platform > unity
. Then selectStart Integration
.
- Choose the game options as seen below then click
Next
.
When on the
Now let's set up the SDKβ screen, follow the instructions then click
Next`.When on the
Letβs integrate the SDK into your game
screen. Instead of following the instructions in the documentations, the Brick Breaker example will need to be setup.Open Unity go to
File > Build Settings
.Add the following scenes into the 'Scenes in Build' in the build settings:
(The following can be found in theAssets/Skillz/Examples/Brick Break/Scenes
folder)
BB_StartMenu
BB_Game
BB_ProgressionRoom
Make sure the
BB_StartMenu
scene is at index 0.Go to
Skill > Settings
.Set the
Skillz Orientation
toPortrait
, Set theGame ID
to the id generated in the developer console.Follow the build instructions for your SDK version and desired platform at: https://docs.skillz.com/docs/installing-skillz-unity
Follow the steps below to finish the setup process in the developer console.
Configuring Developer Console for the Example Projectβ
Setting Up Tournaments with Game Parametersβ
In the developer console, select your game then go to
Optimize > Tournament
.Select
Edit
on the sandbox tournament templates.Fill out the tournament templates with desired values. The brick breaker example supports the game parameters below:
Setting Up Progressionβ
In the developer console, select your game then go to
Progression > Entry Points > Edit
Click
New Entry Point
and create an entry point.In the developer console go to
Progression > Player Data > Edit
.Turn on the
Sandbox
flag, then clickAdd Custom Data
.Add the custom data keys seen below: