In your Unity game

Unity SDK

C# bindings for Unity WebGL games. Submit scores, show ads, trigger haptics, and spend platform coins — all through the static YesSDK class.

Getting Started

Install via UPM

The Unity SDK ships as a Unity package. Add it once via the Package Manager and import Yes from any script.

Requirements

  • Unity 2021.3 LTS or newer
  • WebGL build target (the SDK is no-op on other platforms outside the Editor)
  • .NET Standard 2.1 or .NET Framework 4.x

Install (Package Manager)

  1. Open Window → Package Manager
  2. Click the + button and choose Add package from git URL…
  3. Paste the URL below and click Add
https://github.com/playonyes/yes-sdk-unity.git

Install (manifest.json)

Alternatively, add the dependency directly to Packages/manifest.json:

Packages/manifest.json
{
"dependencies": {
"com.yes.sdk": "https://github.com/playonyes/yes-sdk-unity.git"
}
}

Pinning a version

Append #v1.0.0 (or any tag/commit) to the URL to pin a specific release:

https://github.com/playonyes/yes-sdk-unity.git#v1.0.0

Quick Start

A minimal MonoBehaviour that fetches the player and submits a score:

GameController.cs
using UnityEngine;
using Yes;
public class GameController : MonoBehaviour
{
private void Start()
{
YesSDK.OnReady(async () =>
{
Player player = await YesSDK.GetPlayerAsync();
Debug.Log($"Playing as {player.username}");
});
}
public async void OnGameOver(int finalScore)
{
SubmitScoreResult result = await YesSDK.SubmitScoreAsync(finalScore);
if (result.isNewBest)
{
YesSDK.Haptic(HapticStyle.Success);
}
}
}

Configuration

Call YesSDK.Configure() once before the first SDK method if you want to override defaults. The Editor and standalone builds run a mock provider that returns realistic stub responses — you can develop your game without ever touching the platform.

YesBootstrap.cs
using UnityEngine;
using Yes;
public static class YesBootstrap
{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Configure()
{
YesSDK.Configure(new YesSDKConfig
{
Debug = true, // log every bridge message
TimeoutMs = 10000, // per-request timeout (default 10s)
UseMockProviderOutsideWebGL = true, // mock responses in Editor (default)
});
}
}

API Reference

Lifecycle

YesSDK.OnReady()#
public static void OnReady(Action callback)

Register a callback that fires once the SDK has finished bootstrapping. Invoked immediately if the SDK is already ready.

Parameters
NameTypeDescription
callbackActionInvoked when the SDK is ready. Null callbacks are ignored.
Example
YesSDK.OnReady(() =>
{
Debug.Log("SDK ready — safe to call any YesSDK method.");
});
YesSDK.Configure()#
public static void Configure(YesSDKConfig config)

Apply a custom configuration. Call before the first SDK method for the timeout to take effect; the Debug flag is honoured at any time.

Parameters
NameTypeDescription
configYesSDKConfigConfiguration object. Pass null to reset to defaults.
Example
YesSDK.Configure(new YesSDKConfig { Debug = true, TimeoutMs = 15000 });

Scores

Boost player retention

Leaderboards drive competition and keep players coming back. Games with score systems see significantly higher retention rates as players compete to climb the ranks.
YesSDK.SubmitScoreAsync()#
public static Task<SubmitScoreResult> SubmitScoreAsync(int score, SubmitScoreOptions options = null)

Submit a score to the leaderboard. Throws ArgumentOutOfRangeException if score is negative.

Parameters
NameTypeDescription
scoreintThe score to submit. Must be non-negative.
options?SubmitScoreOptionsOptional metadata (MetadataJson string).
Returns

Task<SubmitScoreResult>{ isNewBest, rank, score } — isNewBest is true when this beats the player's previous high score.

Example
SubmitScoreResult result = await YesSDK.SubmitScoreAsync(score);
if (result.isNewBest)
{
ShowMessage($"New best! Rank #{result.rank}");
YesSDK.Haptic(HapticStyle.Success);
}

Player

YesSDK.GetPlayerAsync()#
public static Task<Player> GetPlayerAsync()

Fetch the current player's profile. Cache the result — it doesn't change during a session.

Returns

Task<Player>{ id, username, avatarUrl } — use to personalise your game UI.

Example
Player player = await YesSDK.GetPlayerAsync();
playerNameLabel.text = player.username;
if (!string.IsNullOrEmpty(player.avatarUrl))
{
StartCoroutine(LoadAvatar(player.avatarUrl));
}

Ads

Two ad formats

Rewarded ads are opt-in — the player chooses to watch in exchange for a reward. Interstitial ads play between natural moments (e.g., between levels) and are rate-limited by the platform so players aren't overwhelmed.
YesSDK.ShowRewardedAdAsync()#
public static Task<RewardedAdResult> ShowRewardedAdAsync()

Display a rewarded video ad. The player can earn rewards by watching the full ad.

Returns

Task<RewardedAdResult>{ rewarded, errorCode, errorMessage } — only grant rewards when rewarded is true.

Example
RewardedAdResult ad = await YesSDK.ShowRewardedAdAsync();
if (ad.rewarded)
{
player.coins += 100;
ShowMessage("You earned 100 coins!");
}
else if (ad.errorCode == "USER_DISMISSED")
{
ShowMessage("Watch the full ad to earn rewards");
}
else if (ad.errorCode == "NOT_LOADED")
{
ShowMessage("No ad available right now");
}
YesSDK.IsRewardedAdReadyAsync()#
public static Task<AdReadyStatus> IsRewardedAdReadyAsync()

Check if a rewarded ad is loaded and available. Use to conditionally enable a 'Watch Ad' button.

Returns

Task<AdReadyStatus>{ ready } — true when an ad is ready to show.

Example
AdReadyStatus status = await YesSDK.IsRewardedAdReadyAsync();
watchAdButton.interactable = status.ready;
YesSDK.ShowInterstitialAdAsync()#
public static Task<InterstitialAdResult> ShowInterstitialAdAsync()

Show an interstitial ad between natural game moments. Rate-limited — if called too frequently, it resolves immediately without showing.

Returns

Task<InterstitialAdResult>{ shown, errorCode, errorMessage } — shown is true if the ad was actually displayed.

Example
public async void OnLevelComplete()
{
await YesSDK.ShowInterstitialAdAsync();
LoadNextLevel();
}
YesSDK.IsInterstitialAdReadyAsync()#
public static Task<AdReadyStatus> IsInterstitialAdReadyAsync()

Check if an interstitial is available and not rate-limited. Returns false during the cooldown period after a previous interstitial.

Returns

Task<AdReadyStatus>{ ready } — true when an interstitial can be shown right now.

Example
AdReadyStatus status = await YesSDK.IsInterstitialAdReadyAsync();
if (status.ready)
{
await YesSDK.ShowInterstitialAdAsync();
}

Haptics

YesSDK.Haptic()#
public static void Haptic(HapticStyle style = HapticStyle.Medium)

Trigger haptic feedback on the player's device. Fire-and-forget — falls back silently on devices without haptic support.

Parameters
NameTypeDescription
style?HapticStyleThe haptic style. Defaults to HapticStyle.Medium.
Example
YesSDK.Haptic(); // default Medium tap
YesSDK.Haptic(HapticStyle.Success); // positive feedback
YesSDK.Haptic(HapticStyle.Error); // negative feedback
HapticStyle values
EnumWhen to use
HapticStyle.LightSubtle UI taps
HapticStyle.MediumDefault — general feedback
HapticStyle.HeavyImpacts, collisions
HapticStyle.SuccessScore submitted, level cleared
HapticStyle.WarningLow health, almost out of time
HapticStyle.ErrorFailed action, game over
HapticStyle.SelectionMenu navigation, picker changes

Coins

Platform-controlled pricing

Coin costs are defined by the platform using fixed tiers — your game never sets prices directly. This keeps the economy consistent across all games and ensures players always know what to expect.
YesSDK.PurchaseAsync()#
public static Task<PurchaseResult> PurchaseAsync(PurchaseTier tier, PurchaseOptions options = null)

Prompt the player to spend coins from their wallet. The platform shows a native confirmation modal. Always check result.success before granting in-game content.

Parameters
NameTypeDescription
tierPurchaseTierThe coin tier to charge (Tier1–Tier4).
options.Label?stringLabel shown in the confirmation modal (e.g. 'Unlock Level Pack').
Returns

Task<PurchaseResult>{ success, tierId, coinsSpent, reason } — reason is "cancelled", "insufficient_funds", or "error" on failure.

Example
PurchaseResult result = await YesSDK.PurchaseAsync(
PurchaseTier.Tier2,
new PurchaseOptions("Extra Lives")
);
if (result.success)
{
GrantExtraLives();
YesSDK.Haptic(HapticStyle.Success);
}
else if (result.reason == "insufficient_funds")
{
ShowMessage("Not enough coins!");
}
else if (result.reason == "cancelled")
{
// Player tapped cancel — do nothing
}
Coin Tiers
EnumCoins
PurchaseTier.Tier150
PurchaseTier.Tier2150
PurchaseTier.Tier3500
PurchaseTier.Tier41000

Language

Match the app's language

Players set their language in the Yes app. Use GetLanguage() to read it and localize your game's UI so everything feels native to them.
YesSDK.GetLanguage()#
public static string GetLanguage()

Returns the app's current language code. Synchronous — no await needed. Call at game init to set your UI language.

Returns

stringLanguage code: "en" (English) or "tr" (Turkish). Defaults to "en".

Example
string lang = YesSDK.GetLanguage();
if (lang == "tr")
{
SetUILanguage(Language.Turkish);
}
else
{
SetUILanguage(Language.English);
}

Full Example

A complete MonoBehaviour that wires up every SDK feature:

GameController.cs
using UnityEngine;
using UnityEngine.UI;
using Yes;
public class GameController : MonoBehaviour
{
[SerializeField] private Text playerNameLabel;
[SerializeField] private Button watchAdButton;
[SerializeField] private Button buyExtraLivesButton;
private Player _player;
private int _score;
private void Start()
{
YesSDK.OnReady(async () =>
{
// Personalise the UI
_player = await YesSDK.GetPlayerAsync();
playerNameLabel.text = _player.username;
// Localise to match the app's language
ApplyLanguage(YesSDK.GetLanguage());
// Only show "Watch Ad" if an ad is ready
var status = await YesSDK.IsRewardedAdReadyAsync();
watchAdButton.interactable = status.ready;
});
}
public async void OnLevelComplete(int levelScore)
{
_score += levelScore;
// Submit score (fire and forget the await)
var result = await YesSDK.SubmitScoreAsync(_score);
if (result.isNewBest)
{
YesSDK.Haptic(HapticStyle.Success);
}
// Interstitial between levels
await YesSDK.ShowInterstitialAdAsync();
LoadNextLevel();
}
public async void OnWatchAdForLife()
{
var ad = await YesSDK.ShowRewardedAdAsync();
if (ad.rewarded)
{
GrantExtraLife();
YesSDK.Haptic(HapticStyle.Success);
}
}
public async void OnBuyExtraLives()
{
var result = await YesSDK.PurchaseAsync(
PurchaseTier.Tier2,
new PurchaseOptions("Extra Lives")
);
if (result.success)
{
GrantExtraLives(count: 3);
YesSDK.Haptic(HapticStyle.Success);
}
else if (result.reason == "insufficient_funds")
{
ShowMessage("Not enough coins!");
}
}
private void ApplyLanguage(string code) { /* ... */ }
private void LoadNextLevel() { /* ... */ }
private void GrantExtraLife() { /* ... */ }
private void GrantExtraLives(int count) { /* ... */ }
private void ShowMessage(string text) { /* ... */ }
}

Best Practices

Wait for OnReady

Calls before the SDK has bootstrapped will queue and resolve once ready, but for calls that block UI (player profile, ad readiness) wrap them in OnReady or check YesSDK.IsReady first.

YesSDK.OnReady(async () =>
{
Player player = await YesSDK.GetPlayerAsync();
nameLabel.text = player.username;
});

Always check ad results

Never grant a reward without first checking result.rewarded. Players can dismiss or skip ads, and granting rewards anyway breaks the economy.

Test in the Editor with mock mode

By default, the SDK returns realistic mock responses in the Unity Editor and any non-WebGL build. You can iterate on score submission, ad flows, and purchases without ever building to WebGL. Disable via UseMockProviderOutsideWebGL = false if you need to debug the bridge layer.

Score submission timing

Submit scores at natural game moments — end of level, game over, or achievement completion. Avoid spamming submissions during gameplay.

Reference sample

A complete IMGUI demo exercising every API is included with the package at Samples~/BasicIntegration/YesSDKDemo.cs. Import it via the Package Manager → Samples tab.