A lightweight Unity client for the ZScore game services platform. This SDK lets your game talk to ZScore’s REST APIs from Unity using simple, coroutine-friendly handlers. Out of the box you can:
- Create and authenticate players
- Fetch and update achievements
- List currencies and offers
- Submit and query leaderboard scores
- Inspect the player wallet and perform wallet operations (increase/decrease balances)
- List and execute triggers
The SDK wraps UnityWebRequest and returns results via callbacks, so it works well with StartCoroutine in MonoBehaviours.
- Unity 2021.3 LTS or newer (tested with 6000.2.7f2)
- Scripting Runtime: .NET 4.x Equivalent
- An active ZScore project with an API Key
This repo contains a drop-in package under Assets/zscore-unity-sdk.
- Option A: Copy the
Assets/zscore-unity-sdkfolder into your project’sAssetsfolder. - Option B: Add this repository as a submodule and ensure the folder ends up at
Assets/zscore-unity-sdk.
Namespaces are under zscore_unity_sdk.
The central entry point is ZScoreClient. You construct it with your ZScore API key. Use the client to access domain-specific handlers (Players, AuthTokens, Achievements, Currencies, CurrencyOffers, Leaderboards, Triggers, Wallet, WalletOperations).
using UnityEngine;
using System.Collections;
using zscore_unity_sdk.Client;
using zscore_unity_sdk.Dto.Request.Player;
public class ZScoreExample : MonoBehaviour
{
[SerializeField] private string apiKey;
private ZScoreClient client;
private void Awake()
{
client = new ZScoreClient(apiKey);
// Optional: point to a different environment (defaults to https://api.zscore.eu/api/integration)
// client.baseApiUrl = "https://api.your-env.example/api/integration";
}
private void Start()
{
StartCoroutine(BootstrapPlayerFlow());
}
private IEnumerator BootstrapPlayerFlow()
{
// 1) Create a player
var playerRequest = new PlayerRequest { name = "Player_001" };
yield return StartCoroutine(client.Players().CreatePlayer(
playerRequest,
player =>
{
Debug.Log($"Player created: {player.id}");
// 2) Exchange player id for access tokens
var tokenRequest = new zscore_unity_sdk.Dto.Request.TokenForPlayerRequest { id = player.id };
StartCoroutine(client.AuthTokens().GetPlayerTokens(
tokenRequest,
tokens =>
{
client.playerAccessToken = tokens.accessToken;
client.playerRefreshToken = tokens.refreshToken;
Debug.Log("Player authenticated");
// Now you can call JWT-protected endpoints (achievements, wallet, etc.)
},
err => Debug.LogError($"Token error: {err.errorKey} - {err.detail}")));
},
err => Debug.LogError($"Create player error: {err.errorKey} - {err.detail}")));
}
}Notes
- Endpoints that require an API Key only (e.g., listing triggers) are handled internally by the SDK.
- Endpoints that require a Player JWT will throw if
playerAccessTokenis not set. Always authenticate first.
Below are concise examples for common operations. All methods are coroutines; call them via StartCoroutine and pass success/error callbacks.
// Get achievements (paged)
yield return StartCoroutine(client.Achievements().getAchievements(
page: 1,
onSuccess: page =>
{
Debug.Log($"Achievements received: {page.items.Length}");
// Complete a single-type achievement
foreach (var a in page.items)
{
if (a.type == zscore_unity_sdk.Dto.Response.Achievement.AchievementType.SINGLE)
{
StartCoroutine(client.Achievements().completeAchievement(
a.id,
res => Debug.Log("Achievement completed"),
err => Debug.LogError($"Complete error: {err.errorKey} - {err.detail}")));
}
}
},
onError: err => Debug.LogError($"List error: {err.errorKey} - {err.detail}")));
// Increase progress on a progressive achievement
yield return StartCoroutine(client.Achievements().increaseAchievementProgress(
achievementId: "your-achievement-id",
amount: 1,
onSuccess: res => Debug.Log($"Progress: {res.currentCount}/{res.neededCount}"),
onError: err => Debug.LogError($"Progress error: {err.errorKey} - {err.detail}")));// List triggers (API-Key secured)
yield return StartCoroutine(client.Triggers().GetTriggers(
page: 1,
onSuccess: page => Debug.Log($"Triggers: {page.items.Length}"),
onError: err => Debug.LogError($"List triggers error: {err.errorKey} - {err.detail}")));
// Execute a trigger (Player JWT secured)
yield return StartCoroutine(client.Triggers().ExecuteTrigger(
triggerId: "your-trigger-id",
onSuccess: () => Debug.Log("Trigger executed"),
onError: err => Debug.LogError($"Execute trigger error: {err.errorKey} - {err.detail}")));using zscore_unity_sdk.Runtime.Dto.Request.Wallet;
// Get wallet
yield return StartCoroutine(client.Wallet().GetWallet(
onSuccess: wallet => Debug.Log($"Wallet {wallet.id}"),
onError: err => Debug.LogError($"Wallet error: {err.errorKey} - {err.detail}")));
// Create wallet operations (increase / decrease)
yield return StartCoroutine(client.WalletOperations().CreateWalletOperation(
new WalletOperationRequest { currencyId = "currency-id", amount = 100, type = WalletOperationType.INCREASE },
onSuccess: op => Debug.Log("Wallet increased"),
onError: err => Debug.LogError($"Op error: {err.errorKey} - {err.detail}")));
yield return StartCoroutine(client.WalletOperations().CreateWalletOperation(
new WalletOperationRequest { currencyId = "currency-id", amount = 5, type = WalletOperationType.DECREASE },
onSuccess: op => Debug.Log("Wallet decreased"),
onError: err => Debug.LogError($"Op error: {err.errorKey} - {err.detail}")));
// List wallet operations (paged)
yield return StartCoroutine(client.WalletOperations().GetWalletOperations(
page: 1,
onSuccess: p => Debug.Log($"Ops: {p.items.Length}"),
onError: err => Debug.LogError($"List ops error: {err.errorKey} - {err.detail}")));// Currencies
yield return StartCoroutine(client.Currencies().GetCurrencies(
page: 1,
onSuccess: p => Debug.Log($"Currencies: {p.items.Length}"),
onError: err => Debug.LogError($"Currencies error: {err.errorKey} - {err.detail}")));
// Currency offers
yield return StartCoroutine(client.CurrencyOffers().GetCurrencyOffers(
page: 1,
onSuccess: p => Debug.Log($"Offers: {p.items.Length}"),
onError: err => Debug.LogError($"Offers error: {err.errorKey} - {err.detail}")));// List leaderboards
yield return StartCoroutine(client.Leaderboards().GetLeaderboards(
page: 1,
onSuccess: p => Debug.Log($"Leaderboards: {p.items.Length}"),
onError: err => Debug.LogError($"Leaderboards error: {err.errorKey} - {err.detail}")));
// Submit a score
yield return StartCoroutine(client.Leaderboards().CreateLeaderboardScore(
leaderboardId: "your-leaderboard-id",
score: 123,
onSuccess: _ => Debug.Log("Score submitted"),
onError: err => Debug.LogError($"Submit score error: {err.errorKey} - {err.detail}")));
// Get scores
yield return StartCoroutine(client.Leaderboards().GetLeaderboardScores(
leaderboardId: "your-leaderboard-id",
page: 1,
onSuccess: p => Debug.Log($"Scores: {p.items.Length}"),
onError: err => Debug.LogError($"Scores error: {err.errorKey} - {err.detail}")));The SDK manages HTTP headers for you but needs the right credentials provided via ZScoreClient:
- API Key: Pass to
new ZScoreClient(apiKey). Some endpoints (e.g., listing triggers) use only the API key. - Player JWT: After creating a player, exchange the player id for tokens using
client.AuthTokens().GetPlayerTokens(...)and setclient.playerAccessToken(and optionallyplayerRefreshToken). Most player-facing endpoints require this token and will throw if it is missing.
Default base URL: https://api.zscore.eu/api/integration. You can override it via client.baseApiUrl if you target a different environment.
All handlers accept an onError callback receiving ZScoreErrorResponse with fields like:
status(HTTP status)errorKeydetail
Always provide error callbacks and log or surface messages appropriately.
- These are coroutines; wrap calls with
StartCoroutine(...). - Pagination: list endpoints accept a
pageparam and use a default server page size ofZScoreClient.DEFAULT_PAGE_SIZE(25). - Network timeouts default to 20 seconds per request.
This SDK is provided as-is as part of the ZScore sample/integration materials. See repository license for details.