Перейти к содержимому
AI Agent

Install with AI Agent

Copy & paste this prompt

Install the Hyperstone Unity SDK in this project. Follow these steps: 1. Read the integration recipe: https://hyperstone.ai/docs/llms.txt 2. Use the documentation that best fits your context window: - Minimal (fast): https://hyperstone.ai/docs/llms.txt - Full (comprehensive): https://hyperstone.ai/docs/llms-full.txt - Small (optimized): https://hyperstone.ai/docs/llms-small.txt 3. Execute the installation following the recipe instructions. 4. Verify that the SDK is correctly installed and integrated into the project.

Integration

Это содержимое пока не доступно на вашем языке.

using UnityEngine;
using HyperstoneSdk;
public class MyGame : MonoBehaviour
{
void Start()
{
// Subscribe to config changes — can be called before Initialize
Hyperstone.WatchConfig(OnConfigChanged);
// Initialize with your credentials from the Hyperstone Console
Hyperstone.Initialize("YOUR_APP_ID", "YOUR_APP_SECRET");
}
void OnConfigChanged(HyperstoneConfig config)
{
// Read optimized values sent by Hyperstone
int lives = config.GetIntOrDefault("n_lives", 3);
bool showAdsAfterDeath = config.GetBoolOrDefault("show_ads_after_death", true);
// Apply to your game logic
GameManager.Instance.SetLives(lives);
GameManager.Instance.SetAdsAfterDeath(showAdsAfterDeath);
}
void OnDestroy()
{
Hyperstone.UnwatchConfig(OnConfigChanged);
}
}

That’s it. Hyperstone will automatically:

  1. Fetch an optimized configuration tailored for this user
  2. Deliver it to your callback
  3. Track session metrics (sessions count, engagement time, retention)
  4. Send accumulated metrics to the Hyperstone backend

Call Hyperstone.Initialize() once during your app startup (typically in a MonoBehaviour.Start() or a bootstrap script):

Hyperstone.Initialize("YOUR_APP_ID", "YOUR_APP_SECRET");
ParameterTypeDescription
appIdstringYour application ID from the Hyperstone Console.
appSecretstringYour application secret from the Hyperstone Console.
logLevelHyperstoneClient.LogLevel(Optional) Logging verbosity. Default: LogLevel.Info.

You can find your App ID and App Secret in the Hyperstone Console.

Initialize must only be called once. Subsequent calls are ignored with a warning.

Use Hyperstone.WatchConfig() to receive configuration updates. You can subscribe at any point in your project — even before calling Initialize. This is particularly useful for decoupled architectures where different systems register their interest in config independently.

// Subscribe early — even before Initialize
Hyperstone.WatchConfig(OnConfigChanged);
void OnConfigChanged(HyperstoneConfig config)
{
// This fires:
// 1. Immediately with the cached config (if one exists)
// 2. Again when a fresh config arrives from the server
}

When you subscribe:

  • If a config is already available (cached from a previous session or fetched from the server), your callback fires immediately with the current config.
  • When a fresh config is fetched from the server, all registered callbacks fire again with the new config.

To unsubscribe:

Hyperstone.UnwatchConfig(OnConfigChanged);

HyperstoneConfig provides typed accessors with default value fallbacks. The config keys and their value types are defined by you in the Hyperstone Console when configuring your optimization parameters.

void OnConfigChanged(HyperstoneConfig config)
{
// Primitives with safe defaults
int lives = config.GetIntOrDefault("n_lives", 3);
float speed = config.GetFloatOrDefault("player_speed", 5.0f);
double ratio = config.GetDoubleOrDefault("reward_ratio", 1.5);
long bigNum = config.GetLongOrDefault("score_cap", 1000000L);
bool showAds = config.GetBoolOrDefault("show_ads_after_death", true);
string theme = config.GetStringOrDefault("ui_theme", "dark");
// TryGet pattern (returns false if key is missing or type mismatch)
if (config.TryGetInt("bonus_level", out int bonus))
{
// Use bonus
}
}

For a full list of access methods, refer to the API Reference.

If your config maps cleanly to a C# class, you can deserialize it in one call using Unity’s JsonUtility:

[Serializable]
public class GameConfig
{
public int n_lives;
public bool show_ads_after_death;
public float player_speed;
}
void OnConfigChanged(HyperstoneConfig config)
{
GameConfig gameConfig = config.AsObject<GameConfig>();
// or overwrite an existing instance:
// config.OverwriteObject(existingGameConfig);
}

Hyperstone needs to know what happens in your app to optimize the configuration. The SDK provides methods for tracking standard events (ads, in-app purchases) and custom events/metrics.

Some events and properties are tracked automatically by the SDK and don’t require any code.

User Device Properties

  • SDK Version, Unity Version & Platform
  • App bundle ID and numeric Version
  • Operating system, Device model, and Device type (Phone/Tablet)
  • Language code and Time zone
  • Developer mode flag

System Metrics

  • Session & Time — Total engagement time (in minutes) and total session counts. New sessions start on app launch or resuming from a timeout pause.
  • Retention & Streaks — Total different days playing, continuous streaks, and calendar day tracking.
  • Aggregated Revenue — Total overall revenue, total ad revenue/requests/impressions/errors, and IAP aggregate totals.
  • Conversions — Purchaser conversion events (the first time a player makes a purchase).
// User saw an ad — include the revenue for ILRD
Hyperstone.LogAdImpression(
adPlatform: "admob", // Mediation platform (e.g., "admob", "ironsource", "max")
adNetwork: "meta", // The actual ad network that served the ad
adFormat: "rewarded", // Ad format ("banner", "interstitial", "rewarded", "native")
revenueUsd: 0.0032 // Estimated revenue in USD
);
// Ad was requested
Hyperstone.LogAdRequest(
adPlatform: "admob",
adFormat: "interstitial"
);
// Ad failed to load/show
Hyperstone.LogAdError(
adPlatform: "admob",
adNetwork: "meta",
adFormat: "interstitial",
failReason: "no_fill" // Optional, defaults to "unknown"
);

You can measure in-app purchase revenue using the LogIapTransactionSuccess method. You must manually pass the localized price point to properly measure the revenue generated:

// Successful purchase
Hyperstone.LogIapTransactionSuccess(
productId: "gems_100",
currency: "USD",
price: 4.99 // The price will be tracked as IAP revenue for LTV calculation
);
// Failed purchase
Hyperstone.LogIapTransactionError(
productId: "gems_100",
failReason: "cancelled"
);

The SDK automatically detects the first successful purchase and reports a purchaser conversion event. Subsequent ad revenue for purchaser users is additionally tracked as a separate measurement.

For app-specific tracking, use custom events and metrics:

// Simple event (counted with value = 1)
Hyperstone.LogCustomEvent("level_completed");
// Event with labels for segmentation
Hyperstone.LogCustomEvent("level_completed",
new Label("difficulty", "hard"),
new Label("world", "forest")
);
// Numeric metric (accumulates the value)
Hyperstone.IncrementCustomMetric("coins_spent", 50);
// Numeric metric with labels
Hyperstone.IncrementCustomMetric("damage_dealt", 127.5f,
new Label("weapon", "sword"),
new Label("enemy_type", "boss")
);

Naming rules for custom metrics:

  • Alphanumeric characters, hyphens, and underscores only ([a-zA-Z0-9-_])
  • Maximum 100 characters

Labels attach low-cardinality metadata to measurements. The Hyperstone service uses labels to segment and aggregate data. Good label candidates are things like ad networks, difficulty levels, or item categories — not unique user IDs or timestamps.

Impression-Level Revenue Data (ILRD) is critical for optimizing ad revenue. Here’s how to integrate with popular ad mediation platforms.

using GoogleMobileAds.Api;
// When setting up your rewarded ad:
rewardedAd.OnAdPaid += (AdValue adValue) =>
{
// AdMob reports value in micros (1,000,000 micros = 1 unit of currency)
double revenueUsd = adValue.Value / 1_000_000.0;
Hyperstone.LogAdImpression(
adPlatform: "admob",
adNetwork: "admob", // AdMob as network when not using mediation
adFormat: "rewarded",
revenueUsd: revenueUsd
);
};
// For mediated ads, extract the actual ad network from the adapter class name or response info:
rewardedAd.OnAdPaid += (AdValue adValue) =>
{
double revenueUsd = adValue.Value / 1_000_000.0;
var responseInfo = rewardedAd.GetResponseInfo();
var loadedAdapterName = responseInfo?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "unknown";
Hyperstone.LogAdImpression(
adPlatform: "admob",
adNetwork: loadedAdapterName,
adFormat: "rewarded",
revenueUsd: revenueUsd
);
};
using Unity.Services.LevelPlay;
// Subscribe to the impression data event
IronSourceEvents.onImpressionDataReadyEvent += OnImpressionDataReady;
void OnImpressionDataReady(IronSourceImpressionData impressionData)
{
if (impressionData.revenue.HasValue)
{
Hyperstone.LogAdImpression(
adPlatform: "ironsource",
adNetwork: impressionData.adNetwork ?? "unknown",
adFormat: impressionData.adUnit ?? "unknown",
revenueUsd: impressionData.revenue.Value
);
}
}

To reset all locally stored Hyperstone data (e.g., when a user logs out or you want a clean slate):

Hyperstone.ClearData();

This clears the stored user ID, cached config, accumulated metrics, session history, and purchaser status. The next Initialize call will treat this as a brand-new user.

Control the SDK’s log verbosity:

Hyperstone.LogLevel = HyperstoneClient.LogLevel.Debug; // Verbose — useful during development
Hyperstone.LogLevel = HyperstoneClient.LogLevel.Info; // Default — initialization and key events
Hyperstone.LogLevel = HyperstoneClient.LogLevel.Warning; // Only warnings and errors
Hyperstone.LogLevel = HyperstoneClient.LogLevel.Error; // Only errors

You can also pass the log level directly at initialization:

Hyperstone.Initialize("YOUR_APP_ID", "YOUR_APP_SECRET", HyperstoneClient.LogLevel.Debug);

All SDK logs are prefixed with [Hyperstone]: for easy filtering in the Unity Console.

Understanding the SDK internals helps you use it effectively and debug integration issues.

The Hyperstone static class is a facade over a singleton HyperstoneClient MonoBehaviour. On first access, the SDK creates a [Hyperstone] GameObject marked with DontDestroyOnLoad so it persists across scene loads.

sequenceDiagram
    participant App as Your App
    participant SDK as Hyperstone SDK
    participant Storage as PlayerPrefs
    participant Server as Hyperstone Server

    Note over App, Server: Initialization & Config Fetch
    App->>SDK: Hyperstone.WatchConfig(callback)
    App->>SDK: Hyperstone.Initialize(appId, appSecret)
    SDK->>Storage: Load cached UID, config, metrics
    Storage-->>SDK: Cached data (if any)
    SDK-->>App: callback(cached config)

    SDK->>Server: POST /v1/c {user properties}
    Note right of SDK: Headers: xp-app-id, xp-app-secret, xp-uid
    Server-->>SDK: Config JSON + UID
    SDK->>Storage: Persist UID + config
    SDK-->>App: callback(fresh config)

    Note over App, Server: Event Tracking
    App->>SDK: LogAdImpression / LogIap / IncrementCustomMetric
    SDK->>SDK: Accumulate in metrics buffer
    SDK->>Storage: Persist buffer (crash-safe)

    Note over SDK, Server: Metric Sending (debounced, with cooldown)
    SDK->>Server: POST /v1/i {batched metrics}
    Note right of SDK: Headers: xp-app-id, xp-app-secret, xp-uid
    alt Success
        Server-->>SDK: 200 OK
        SDK->>Storage: Clear sent metrics
    else Failure
        Server-->>SDK: Error
        SDK->>SDK: Restore metrics to buffer for retry
    end

    Note over SDK, Server: Automatic (no code required)
    loop Every 15s while app is active
        SDK->>SDK: Increment engagement time
    end
    SDK->>SDK: Track sessions, retention, streaks
  1. InitializationHyperstone.Initialize() creates/finds the singleton, stores your credentials, loads any cached config and metrics from PlayerPrefs, and begins a config fetch request.
  2. Config Fetch — The SDK sends a POST request to the Hyperstone API with device/user properties. The server responds with an optimized configuration and a unique user identifier (UID). Both are persisted locally.
  3. Config Delivery — Once the config arrives, all registered WatchConfig callbacks are invoked. If a cached config existed from a previous session, callbacks fire immediately on subscribe with the cached version, and again when the fresh config arrives.
  4. Metric Collection — Events (ad impressions, purchases, custom metrics, sessions, engagement time) are accumulated in an in-memory buffer and periodically persisted to PlayerPrefs. This ensures no data is lost on crashes.
  5. Metric Sending — The SDK batches metrics and sends them to the backend with a debounce window (0.5s) and a cooldown period (20s) to avoid overwhelming the server. If a send fails, metrics are restored to the buffer and retried on the next opportunity.
  6. Session Management — The SDK automatically tracks sessions, detecting new sessions on app launch and when the app resumes from a background pause longer than 30 seconds. Engagement time is measured in 15-second increments. Retention is tracked at both “soft day” granularity (16+ hours between sessions) and calendar-day granularity.

All data is stored in Unity’s PlayerPrefs under keys namespaced by your App ID (e.g., xp-uid-{appId}, xp-config-{appId}). This means:

  • Config and metrics survive app restarts
  • Metrics that fail to send are buffered and retried
  • Each app ID has isolated storage (relevant for multi-tenancy)

All calls to the Hyperstone static API are thread-safe. You can safely call Hyperstone.Initialize(), Hyperstone.WatchConfig(), Hyperstone.LogAdImpression(), and all other methods from any thread — including background threads, async tasks, or job system callbacks.

Under the hood, the Hyperstone facade captures Unity’s main-thread SynchronizationContext at startup (via [RuntimeInitializeOnLoadMethod]). If a call is made from a non-main thread, it is automatically marshalled to the main thread using SynchronizationContext.Post(). This ensures that the underlying HyperstoneClient MonoBehaviour (which uses coroutines and Unity APIs) always runs on the main thread, while your calling code doesn’t need to worry about thread affinity.

The Hyperstone static API manages a single shared client instance (singleton pattern). In most apps, this is all you need.

However, if your application needs to communicate with multiple Hyperstone apps simultaneously (e.g., a publishing platform hosting multiple titles, or a single app with separate optimization scopes), you can create and manage HyperstoneClient instances manually:

using UnityEngine;
using HyperstoneSdk;
public class MultiTenantExample : MonoBehaviour
{
private HyperstoneClient _gameplayClient;
private HyperstoneClient _monetizationClient;
void Start()
{
// Create separate client instances for different app scopes
_gameplayClient = CreateClient("GameplayOptimizer");
_gameplayClient.Initialize("GAMEPLAY_APP_ID", "GAMEPLAY_APP_SECRET");
_gameplayClient.WatchConfig(OnGameplayConfigChanged);
_monetizationClient = CreateClient("MonetizationOptimizer");
_monetizationClient.Initialize("MONETIZATION_APP_ID", "MONETIZATION_APP_SECRET");
_monetizationClient.WatchConfig(OnMonetizationConfigChanged);
}
private HyperstoneClient CreateClient(string name)
{
var go = new GameObject($"[Hyperstone - {name}]");
DontDestroyOnLoad(go);
return go.AddComponent<HyperstoneClient>();
}
void OnGameplayConfigChanged(HyperstoneConfig config)
{
int lives = config.GetIntOrDefault("n_lives", 3);
// ...
}
void OnMonetizationConfigChanged(HyperstoneConfig config)
{
int adCooldown = config.GetIntOrDefault("ad_cooldown_seconds", 60);
// ...
}
}