Set Up Core Loop & Gameplay
Overviewβ
Below, we walk your through the elements of setting up your core loop and gameplay on Skillz. Beginning with starting a match, reporting a score and eventually getting back to the Skillz UI. By the end of this article, you will have a complete core loop allowing you to fully test a standard Skillz match.
Before continuing, make sure you have completed the previous steps - Launch the Skillz UI.
Launching Your Gameplayβ
When Skillz launches, it will take control of the user experience. The player will start a match and Skillz will notify the game. At this point, control is given back to your game to start the match gameplay. The examples below illustrate how to handle starting a match.
- Unity/C#
- Legacy Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
#import "AppDelegate.h"
#import <Skillz/SkillzInstance.h>
@implementation AppDelegate
- (void)tournamentWillBegin:(NSDictionary *)gameParameters withMatchInfo:(SKZMatchInfo *)matchInfo
{
}
This example has an AppDelegate
class that has implemented the SkillzDelegate
protocol. The tournamentWillBegin:withMatchInfo:
method is called when the player's match is about to begin. Implement this method to navigate to the View/ViewController that represents the gameplay portion of your game.
Additionally, the gameParameters
parameter holds key value parameters of the specific type of tournament being played. These parameters are created by you in the Skillz Developer Console when defining the types of tournaments your game will support.
import UIKit
import Skillz
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, SkillzDelegate {
func tournamentWillBegin(_ gameParameters: [AnyHashable : Any]!, with matchInfo: SKZMatchInfo!) {
}
}
This example has an AppDelegate
class that has implemented the SkillzDelegate
protocol. The tournamentWillBegin
method is called when the player's match is about to begin. Implement this method to navigate to the View/ViewController that represents the gameplay portion of your game.
Additionally, the _ gameParameters
parameter holds key value parameters of the specific type of tournament being played. These parameters are created by you in the Skillz Developer Console when defining the types of tournaments your game will support.
As described in the example for launching Skillz, Skillz will launch the activity that you set for the skillz_game_activity
meta-data tag in your game's AndroidManifest.xml
file.
<meta-data android:name="skillz_game_activity" android:value="com.skillz.your.GameActivity" />
When your activity launches, we recommend that you call relevant methods of the Skillz
static class to retrieve tournament parameters, and match info. Refer to the API Reference for a list of the methods available.
You should have previously implemented the SkillzMatchDelegate
interface but likely only included the stubbed in functions. To handle a match start, you need to expand your implementation of OnMatchWillBegin
.
From within OnMatchWillBegin
you should:
- Clear any previously stored match settings
- Retrieve the Match object and utilize it to set gameplay parameters
- Load your game scene
// ...
public void OnMatchWillBegin(Match matchInfo) {
SceneManager.LoadScene("GameplayScene");
}
// ...
You should have previously implemented the Skillz Manager
. The OnMatchWillBegin
extra logic function specified in the SkillzManager
can be used to:
- Clear any previously stored match settings
- Retrieve the Match object and utilize it to set gameplay parameters
- Load your game scene, if you have specified a
Game Scene
in theSkillz Manager
// ...
public void OnMatchWillBeginExtraLogic(Match matchInfo) {
//Extra Logic Here
}
// ...
Completing Gameplayβ
Submit Scoreβ
To ensure that both asynchronous and synchronous gameplay proceeds optimally, the score for the match should be submitted immediately using SubmitScore
when the match ends, regardless of any remaining player input necessary to reach the match results screen. The score submission should be handled in the background without any explicit action by the player necessary to proceed.
The SubmitScore
method is expecting three values - a score as well as Success and Failure Callbacks.
- Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
- (IBAction)submitScore:(id)sender
{
[[Skillz skillzInstance] submitScore:@(self.currentHeartbeat+(someHeartBeat))
withSuccess:^(void){
NSLog(@"Success!");
NSString *msg = @"Success!";
[[[UIAlertView alloc] initWithTitle:@"Score Submit"
message:msg
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
} withFailure:^(NSString *errorMessage){
NSString *msg = [NSString stringWithFormat:@"Failure: %@", errorMessage];
[[[UIAlertView alloc] initWithTitle:@"Score Submit"
message:msg
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil] show];
}];
}
@IBAction func submitScore(_ sender: Any) {
Skillz.skillzInstance().submitScore(
NSNumber(value: currentHeartbeat + someHeartBeat),
withSuccess: {
print("Success!")
let msg = "Success!"
UIAlertView(title: "Score Submit", message: msg, delegate: self, cancelButtonTitle: "OK", otherButtonTitles: "").show()
Skillz.submitScore(getActivity(), new BigDecimal(currentScore), matchId, new SkillzScoreCallback() {
@Override
public void failure(Exception error) {
isScoreSubmitted = false;
ContraUtils.log("Report Score", "e", error,"Error in report score!");
new AlertDialog.Builder(getActivity())
.setMessage("Error in submit score, NOT reported.")
.setNegativeButton("Ok", null)
.create()
.show();
}
@Override
public void success() {
isScoreSubmitted = true;
submitScoreButton.setEnabled(false);
score = currentScore;
ContraUtils.log("Report Score", "i", "Score reported successfully");
new AlertDialog.Builder(getActivity())
.setMessage("Score submitted successfully!")
.setNegativeButton("Ok", null)
.create()
.show();
}
});
You should report the final score from a script that controls your game scene logic.
using Skillz;
using UnityEngine;
public class GameManager : MonoBehaviour
{
void SubmitScore() {
SkillzCrossPlatform.SubmitScore(GetScore(), Success, Failure);
}
void Success() {
Debug.Log("Success");
//Return to the Skillz UI
}
void Failure(string reason) {
Debug.LogWarning("Fail: " + reason);
//Fallback score submission
}
}
Note on Progressionβ
After submitting a score, you have the opportunity to present the player with a granular score breakdown and an opportunity to allow the player to view their game progression. Setup for this is detailed further in the Progression Overview.
Return To The Skillz UIβ
The ReturnToSkillz
method exits your gameplay scene and presents the Skillz UI. This must be called after the score has been successfully submitted with the SubmitScore
method. After SubmitScore
has been called, you can present users with high scores or progression systems to enhance the game experience before ultimately calling the ReturnToSkillz
method and loading the Skillz UI.
In all cases, it will return true or false, depending on whether or not it is able to return the user to Skillz. For the case of a match in progress, unless a score has been submitted, this method will return false and the user will not be returned to Skillz. If a score has been submitted, it returns true and returns the user to Skillz.
- Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
BOOL canReturn = [[Skillz skillzInstance] returnToSkillzWithCompletion:^{
SZTViewController *vc = self.parentViewController;
// make sure to clean thing up if needed
NSLog(@"Returning to Skillz");
[self.view removeFromSuperview];
[self removeFromParentViewController];
}];
let canReturn = Skillz.skillzInstance().returnToSkillz() { [self] in
let vc = parent as? SZTViewController
// make sure to clean things up if needed
print("Returning to Skillz")
view.removeFromSuperview()
removeFromParent()
}
boolean Skillz.returnToSkillz(@NonNull final Activity activity, String matchId)
If returning from a recently played match, provide the
matchId
. If returning from a Progression Room with no match initiated, send anull
value in place ofmatchId
to return the user back to Skillz.
The ReturnToSkillz method provides flexibility on how to hand the end of the match behavior.
using Skillz;
using UnityEngine;
public class GameManager : MonoBehaviour
{
void SubmitScore() {
SkillzCrossPlatform.SubmitScore(GetScore(), Success, Failure);
}
void Success() {
Debug.Log("Success");
SkillzCrossPlatform.ReturnToSkillz();
}
void Failure(string reason) {
Debug.LogWarning("Fail: " + reason);
//Fallback score submission
}
}
Fallback Score Reportingβ
Please Note:β
ReportFinalScore has been deprecated and replaced by the DisplayTournamentResultsWithScore method.
The primary method for reporting a score to Skillz is through the methods defined above SubmitScore
and ReturnToSkillz
. However, DisplayTournamentResultsWithScore should always be implemented as a fallback in the event that the SubmitScore method fails. This best practice helps to ensure your userβs scores will not be lost. This method submits the player score, then immediately returns the user to the Skillz UI.
Be sure to ensure that calling this method as fallback will prevent any pending/in-progress SubmitScore calls from triggering a new retry after the user returns to Skillz. If you do not do this, the pending retry may execute in a new game and you could end up submitting a previous gameβs score.
- Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
[[Skillz skillzInstance] displayTournamentResultsWithScore:score
withCompletion:^{
NSLog(@"Wrap up any game code that needs to be cleaned up");
MyCoolViewController *vc = self.parentViewController;
[vc disableGameplay];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}];
Skillz.skillzInstance().displayTournamentResults(
withScore: score) { [self] in
print("Wrap up any game code that needs to be cleaned up")
let vc = parent as? MyCoolViewController
vc?.disableGameplay()
view.removeFromSuperview()
removeFromParent()
}
void Skillz.displayTournamentResultsWithScore(getActivity, score, matchId)
using Skillz;
using UnityEngine;
public class GameManager : MonoBehaviour
{
void SubmitScore() {
SkillzCrossPlatform.SubmitScore(GetScore(), Success, Failure);
}
void Success() {
Debug.Log("Success");
SkillzCrossPlatform.ReturnToSkillz();
}
void Failure(string reason) {
Debug.LogWarning("Fail: " + reason);
SkillzCrossPlatform.DisplayTournamentResultsWithScore(GetScore());
}
}
Incomplete Matchesβ
There are a couple of ways to end a match prematurely. First, you can allow the user to quit the game and submit their current score, which gives them an opportunity to win with the score they have. Second, you can abort them from a match, which will result in a loss.
Depending on your specific gameplay, you will need to determine which method works best for you.
Abortingβ
Aborting a match is an alternative to reporting the final score. When a player aborts a match, they have forfeited it to the opponent. In general, the best practice is to report a score for the user, making sure that the score reflects the player leaving the game incomplete. So for example, in a racing game the lowest score (race time) may be the best. If so, the computed score reported for a player quitting early would need to be recalculated to a much higher value, such as the maximum race time, to reflect their loss.
- Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
[[Skillz skillzInstance] notifyPlayerAbortWithCompletion:(^(void)
{
// Completion block
}];
Skillz.skillzInstance().notifyPlayerAbortWithCompletion() {
// Completion block
}
void Skillz.abortMatch(abortActivity());
SkillzCrossPlatform.AbortMatch();
Ending Replayβ
Many cash matches are recorded in order to allow players to view replays as well as allow Skillz to monitor fair play. The SDK provides an option that will allow you to end the replay after successfully submitting scores, but before progressing. This prevents unnecessarily long replays when the players interact with other gameplay elements like Progression. If you choose not to manually end the replay, the replay will end when the game returns to the Skillz UI.
You might want to consider supporting this feature in your game to allow users more control to conserve on resources (i.e. battery, network etc.).
If you invoke this method before calling SubmitScore a value of
false
will be returned. It is always recommended to submit the player score as soon as the match gameplay ends, if possible.
- Unity/C#
- iOS/Swift
- iOS/Objective-C
- Android
BOOL success = [[Skillz skillzInstance] endReplayRecording];
let success = Skillz.skillzInstance().endReplayRecording()
boolean Skillz.endReplayRecording(String matchId);
bool success = SkillzCrossPlatform.EndReplay();
Testβ
SIDEkickβ
If your game is made with Unity, you can simulate launching Skillz from the editor by using the Skillz SIDEkick before exporting and building for iOS or Android. If you are having issues, more insight can be gained by turning on debug logging in the Skillz settings.
Now it's time to test your game loop with Skillz. Please build and run your game on a mobile device.
When you test your game loop, be sure to go to the Developer Console to have it report the user's score back and receive your second checkmark.