### Implement start() lifecycle method Source: https://en.docsv2.balancy.dev/ui-builder/events Use start() to access other components or initiate animations after all components have finished their awake phase. ```javascript class MyScript extends balancy.ElementBehaviour { start() { // Safe to get references to other components this.healthBar = this.getComponent(HealthBar); // Start animations this.startAnimation(); } } ``` -------------------------------- ### start() Source: https://en.docsv2.balancy.dev/ui-builder/events Called once before the first update(), after all components have called awake(). ```APIDOC ## start() ### Description Called once before the first update(), after all components have called awake(). This method is safe to use for getting references to other components. ``` -------------------------------- ### Implement lifecycle methods Source: https://en.docsv2.balancy.dev/cms/extensions Demonstrates overriding onInit and onDispose for setup and cleanup tasks. ```javascript class SetupExtension extends Balancy.Editor.BaseExtension { async onInit() { Balancy.Editor.Log.info("Extension initialized"); // Pre-load data, set up state, etc. } async onDispose() { Balancy.Editor.Log.info("Extension disposed"); // Clean up resources } } ``` -------------------------------- ### Instantiate Balancy_UI_LiveOps_Shop Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of instantiating a shop view prefab and initializing it within a script. ```javascript // In your shop view script async function main() { const shopData = window.balancyViewOwner; const shopObject = await balancy.instantiatePrefabById('shop-view'); const script = shopObject.getComponent(Balancy_UI_LiveOps_Shop); script.init(shopData); document.getElementById('shop-container').appendChild(shopObject.element); } ``` -------------------------------- ### Start Lifecycle Method Source: https://en.docsv2.balancy.dev/ui-builder/prefabs Invoked once before the first update, suitable for cross-component dependencies. ```javascript start() { // Get references to other components this.movement = this.getComponent(Movement); // Start animations this.startAnimation(); } ``` -------------------------------- ### Install @balancy/utils Package Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Command to install the official utility package for browser-based file management. ```bash npm install @balancy/utils ``` -------------------------------- ### Initialize IndexedDBFileHelperAdapter Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Setup and initialization of the IndexedDB-based file helper for browser environments. ```typescript import { IndexedDBFileHelperAdapter } from '@balancy/utils'; import { Balancy } from '@balancy/core'; // Create and initialize the file helper const fileHelperAdapter = await IndexedDBFileHelperAdapter.create({ cachePath: '.balancy' }); // Get cache statistics const stats = fileHelperAdapter.getCacheStats(); console.log(`πŸ“ Files: ${stats.fileCount}, πŸ’Ύ Memory: ${stats.memoryUsage}`); // Initialize Balancy (DataObjectsManager integration is automatic) await Balancy.Main.initializeFileHelper(fileHelperAdapter); ``` -------------------------------- ### Global Settings Response Example Source: https://en.docsv2.balancy.dev/cms/extra/data_scheme Example JSON structure returned by the global settings endpoint. ```json { "branches": {"version": 209}, "products": {"version": 9}, "settings": { "useLocalTime": true, "gameTimeOffset": 0 } } ``` -------------------------------- ### Initialize Balancy SDK Source: https://en.docsv2.balancy.dev/advanced/init Use these snippets to initialize the Balancy SDK in your project. The C# example includes a progress callback, while the TypeScript example uses an async initialization pattern. ```C# var config = new AppConfig { ApiGameId = "", PublicKey = "", Environment = Constants.Environment.Development, OnProgressUpdateCallback = (fileName, progress) => { Debug.Log($"Launch progress {(int)(progress * 100)}% - {fileName}"); } }; Balancy.Main.Init(config); ``` ```TypeScript const config = AppConfig.create({ apiGameId: "", publicKey: "", environment: Environment.Development, }); await Balancy.Main.init(config); ``` -------------------------------- ### Guest Start with Optional Login Source: https://en.docsv2.balancy.dev/advanced/authentication Demonstrates initializing a guest session and providing a manual login path for users. ```C# public class AuthenticationManager : MonoBehaviour { private void Start() { AuthenticateAsGuest(); } private void AuthenticateAsGuest() { API.Auth.AsGuest((AuthResponseData response) => { if (response.Success) { Debug.Log("Playing as guest"); LoadMainMenu(); } else { Debug.LogError($"Guest auth failed: {response.ErrorMessage}"); } }); } // Called when player clicks "Login" in settings public void OnLoginSubmit(string email, string password) { API.Auth.WithNameAndPassword(email, password, (AuthResponseData response) => { if (response.Success) { Debug.Log("Logged in successfully!"); LoadMainMenu(); } else { ShowLoginError(response.ErrorMessage); } }); } } ``` ```TypeScript // With autoLogin: true (default), the SDK authenticates as guest automatically. // No explicit guest auth call needed. // Login when player clicks "Login" in settings: function onLoginSubmit(email: string, password: string) { Balancy.API.Auth.withNameAndPassword(email, password, (response) => { if (response.success) { console.log('Logged in successfully!'); loadMainMenu(); } else { showLoginError(response.errorMessage); } }); } ``` -------------------------------- ### Available Branches Response Example Source: https://en.docsv2.balancy.dev/cms/extra/data_scheme Example JSON structure containing branch definitions. ```json { "branches": [ { "name": "dev", "condition": {"minVersion": "1.0.0", "maxVersion": "0.0.0", "environments": 1}, "id": 0 }, { "name": "stage", "condition": {"minVersion": "0.0.0", "maxVersion": "0.0.0", "environments": 2}, "id": 1 }, { "name": "production", "condition": {"minVersion": "0.0.0", "maxVersion": "0.0.0", "environments": 4}, "id": 2 } // other branches... ] } ``` -------------------------------- ### Open View with Parameters Source: https://en.docsv2.balancy.dev/ui-builder/views Examples of opening offer and event views while passing specific game objects as owners. ```C# // Open offer view with offer as owner var offerInfo = Balancy.LiveOps.GetActiveOffer("special_pack"); offerInfo.GameOffer.UnnyView.OpenView( onShown: () => { Debug.Log("Offer view is now visible"); }, ownerObject: offerInfo ); // Open event view with event owner var eventInfo = Balancy.LiveOps.GetGameEventInfo(myGameEvent); eventInfo.GameEvent.UnnyView.OpenView(null, eventInfo); ``` ```TypeScript // Open offer view with offer as owner const offerInfo = Balancy.LiveOps.getActiveOffer("special_pack"); offerInfo.gameOffer.unnyView.openView( () => { console.log("Offer view is now visible"); }, offerInfo ); // Open event view with event owner const eventInfo = Balancy.LiveOps.getGameEventInfo(myGameEvent); eventInfo.gameEvent.unnyView.openView(null, eventInfo); ``` -------------------------------- ### Initiate Purchases Source: https://en.docsv2.balancy.dev/advanced/api Methods to start a purchase process for store items or offers. ```C# Balancy.API.InitPurchase(storeItem, (success, error) => Debug.Log("Purchase complete: " + success + " error = " + error)); Balancy.API.InitPurchaseOffer(offerInfo, (success, error) => Debug.Log("Purchase complete: " + success + " error = " + error)); Balancy.API.InitPurchaseOffer(offerGroupInfo, storeItem, (success, error) => Debug.Log("Purchase complete: " + success + " error = " + error)); ``` ```TypeScript Balancy.API.initPurchase(storeItem, (success, error) => console.log("Purchase complete: " + success + " error = " + error)); Balancy.API.initPurchaseOffer(offerInfo, (success, error) => console.log("Purchase complete: " + success + " error = " + error)); Balancy.API.initPurchaseOfferGroup(offerGroupInfo, storeItem, (success, error) => console.log("Purchase complete: " + success + " error = " + error)); ``` -------------------------------- ### Install Balancy CLI Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Install the required CLI package via npm. ```bash npm install @balancy/cli ``` -------------------------------- ### Handle Animation Events in Timeline Source: https://en.docsv2.balancy.dev/ui-builder/animation_api Example of setting up a timeline and subscribing to multiple animation events. ```javascript const tl = balancy.createTimeline(); tl.add(this.animation); tl.on('showParticles', () => { /* ... */ }); tl.on('playSound', () => { /* ... */ }); tl.play(); ``` -------------------------------- ### Icon Display Example Source: https://en.docsv2.balancy.dev/cms/advanced/display_format Example usage of the icon function to render a circle shape with specific text and color. ```text {icon(circle, &&, #666666)} ``` -------------------------------- ### Basic File Helper Initialization Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Minimal configuration examples for initializing the file helper with browser or IndexedDB adapters. ```typescript // For basic browser implementation await Balancy.Main.initializeFileHelper(new FileHelperClassBrowser({ cachePath: '.balancy' })); // For IndexedDB implementation (recommended) const adapter = await IndexedDBFileHelperAdapter.create({ cachePath: '.balancy', codePath: 'src/auto-generated-code', // Optional resourcesPath: 'src/resources' // Optional }); await Balancy.Main.initializeFileHelper(adapter); ``` -------------------------------- ### Implement awake() lifecycle method Source: https://en.docsv2.balancy.dev/ui-builder/events Use awake() for initial setup after serialized parameters are applied. ```javascript class MyScript extends balancy.ElementBehaviour { // @serialize {number} maxHealth = 100; awake() { // Parameters already applied console.log('Max health:', this.maxHealth); // Set up event listeners this.element.addEventListener('click', () => this.onClick()); // Initialize state this.currentHealth = this.maxHealth; } } ``` -------------------------------- ### Install Balancy SDK packages Source: https://en.docsv2.balancy.dev/quick_start/engines/typescript Use npm to add the core and utility packages to your project dependencies. ```bash npm install --save @balancy/core@latest npm install --save @balancy/utils@latest ``` -------------------------------- ### Example: Accessing a Specific Item by ID Source: https://en.docsv2.balancy.dev/advanced/data_profiles Demonstrates fetching an item by ID and accessing its properties. ```C# var item26 = Balancy.CMS.GetModelByUnnyId("26"); Debug.Log($"item26.unnyId = {item26.UnnyId}"); Debug.Log($"item26.Name = {item26.Name}"); Debug.Log($"item26.MaxStack = {item26.MaxStack}"); ``` ```TypeScript const item26 = Balancy.CMS.getModelByUnnyId("26"); console.log(`item26.unnyId = ${item26.unnyId}`); console.log(`item26.Name = ${item26.name.getValue()}`); console.log(`item26.MaxStack = ${item26.maxStack}`); ``` -------------------------------- ### Display Game Offer Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of fetching and displaying an active game offer. ```javascript // In your main view script async function main() { const offers = await balancy.getActiveOffers(); const offerInfo = offers[0]; const viewObject = await balancy.instantiatePrefabById('offer-view'); const script = viewObject.getComponent(Balancy_UI_LiveOps_GameOffer); script.init(offerInfo); document.body.appendChild(viewObject.element); } ``` -------------------------------- ### Versions File Structure Source: https://en.docsv2.balancy.dev/cms/extra/data_scheme Example of the versions file containing a list of dictionaries with version, name, and ID information. ```json { "dictionaries": [ { "version": "3", "name": "EnemyInfo", "id": "10587" }, { "version": "5", "name": "DamageInfo", "id": "12" } ] } ``` -------------------------------- ### Accessing Balancy Namespace Methods Source: https://en.docsv2.balancy.dev/ui-builder/api General usage examples for global balancy methods. ```javascript balancy.getSystemProfileValue('GeneralInfo.Level') balancy.closeView('Purchase completed') balancy.ElementsManager.instantiate(element) ``` -------------------------------- ### Best Practices for Condition Handling Source: https://en.docsv2.balancy.dev/liveops/conditions Examples demonstrating defensive null checks and proper subscription cleanup to prevent crashes and memory leaks. ```csharp // βœ… GOOD - defensive null checks var premiumOffer = Balancy.CMS.GetModelByUnnyId("3456"); var condition = premiumOffer?.Condition; if (condition != null && condition.CanPass()) { ShowPremiumFeature(); } // ❌ BAD - crash if null var premiumOffer = Balancy.CMS.GetModelByUnnyId("3456"); if (premiumOffer.Condition.CanPass()) // NullReferenceException! { ShowPremiumFeature(); } // βœ… GOOD - always unsubscribe void OnDestroy() { if (_condition != null) { _condition.UnsubscribeFromStatusChange(); } } // ❌ BAD - memory leak void OnDestroy() { // Forgot to unsubscribe! } ``` -------------------------------- ### Handle profile initialization events Source: https://en.docsv2.balancy.dev/faq This callback is triggered at game start, when the profile is ready, and after a reset. ```csharp //It's called at the game start, when the profile is ready, and after the Restart. ISmartObjectsEvents.OnSmartObjectsInitialized(); ``` -------------------------------- ### Implement Shop Slot Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of a shop slot implementation using the StoreItem component. ```javascript class ShopSlot extends balancy.ElementBehaviour { // @serialize {element} storeItemComponent = null; async init(slotData) { const script = this.storeItemComponent.getComponent(Balancy_UI_LiveOps_StoreItem); await script.init(slotData.storeItem, { onBuy: (item) => this.purchase(item) }); } async purchase(item) { const result = await balancy.buyShopSlot(item.unnyId); console.log('Purchase result:', result); } } ``` -------------------------------- ### Display Rewards List Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example implementation of a rewards list using the ItemWithAmount component. ```javascript class RewardsList extends balancy.ElementBehaviour { // @serialize {element} itemPrefab = null; // @serialize {element} container = null; displayRewards(rewards) { this.container.element.innerHTML = ''; for (const item of rewards.items) { const itemObject = this.itemPrefab.instantiate(); const script = itemObject.getComponent(Balancy_UI_LiveOps_ItemWithAmount); script.init(item); this.container.element.appendChild(itemObject.element); } } } ``` -------------------------------- ### Implement Complete Purchase Flow Source: https://en.docsv2.balancy.dev/ui-builder/events A comprehensive example demonstrating how to handle both response and error events for a purchase button. ```javascript const buyButton = document.getElementById('buy-gems-button'); // Handle successful/failed purchases buyButton.addEventListener('balancyButtonResponse', (event) => { if (event.detail.success) { // Purchase succeeded const gems = event.detail.result.gemsAwarded; // Show success showSuccessMessage(`You got ${gems} gems!`); // Update UI updateGemsDisplay(); // Play sound playSound('purchase_success'); } else { // Purchase failed showErrorDialog(event.detail.error); } }); // Handle errors buyButton.addEventListener('balancyButtonError', (event) => { console.error('Purchase error:', event.detail.error); showErrorDialog('Purchase failed. Please try again.'); }); ``` -------------------------------- ### Return Output Ports in C# Source: https://en.docsv2.balancy.dev/liveops/visual_scripting/all_nodes Example of returning a dictionary of values to match Output port names. ```csharp return new NodeRunFunctionReturnType( new Dictionary { {"new_speed", 10}, {"new_accel", 9.81} } ); ``` -------------------------------- ### Initialize Components in Lifecycle Methods Source: https://en.docsv2.balancy.dev/ui-builder/scripts Perform component initialization in awake() or start() to avoid redundant operations in update(). ```javascript class MyView extends balancy.ElementBehaviour { // @serialize {element} buyButton = null; // βœ“ Good: Initialize in start() or awake() async awake() { const script = this.buyButton.getComponent(Balancy_UI_Common_BuyButton); await script.init({ /* ... */ }); } // βœ— Avoid: Initializing in update() update(deltaTime) { // This would re-initialize every frame! } } ``` -------------------------------- ### Full C# Custom Method Implementation Source: https://en.docsv2.balancy.dev/liveops/visual_scripting/all_nodes A complete example showing the namespace, class structure, and static methods required for custom nodes. ```csharp namespace Experiments { public class SpeedManager { public static NodeRunFunctionReturnType IncreaseSpeed(int speed) { return new NodeRunFunctionReturnType( new Dictionary { {"new_speed", speed * 2} } ); } public static NodeRunFunctionReturnType ResetSpeed() { return new NodeRunFunctionReturnType( new Dictionary { {"new_speed", 10}, {"new_accel", 9.81} }, "AfterReset" ); } } } ``` -------------------------------- ### Example: Accessing and Iterating a List of Items Source: https://en.docsv2.balancy.dev/advanced/data_profiles Retrieves all items of a specific type and iterates through them to log their properties. ```C# var allItems = Balancy.CMS.GetModels(true); Debug.Log("AllItems count = " + allItems.Length); foreach (var item in allItems) { Debug.Log("=== New Item ==="); Debug.Log($"unnyId = {item.UnnyId}"); Debug.Log($"Name = {item.Name}"); Debug.Log($"MaxStack = {item.MaxStack}"); } ``` ```TypeScript const allItems = Balancy.CMS.getModels(true); console.log(`AllItems count = ${allItems.length}`); allItems.forEach(item => { console.log("=== New Item ==="); console.log(`unnyId = ${item.unnyId}`); console.log(`Name = ${item.name.getValue()}`); console.log(`MaxStack = ${item.maxStack}`); }); ``` -------------------------------- ### Setup Reward Claiming Source: https://en.docsv2.balancy.dev/ui_builder Configures claim buttons based on reward status and handles the asynchronous reward claiming process. ```javascript function setupClaimButton(lineId, levelIndex, reward, status) { const button = document.getElementById(`claim-${lineId}-${levelIndex}`); if (status === 1) { // Available button.style.display = 'block'; button.onclick = async () => { const success = await balancy.claimBattlePassReward(lineId, levelIndex); if (success) { // Show reward animation showRewardAnimation(button, reward); // Update button state setupClaimButton(lineId, levelIndex, reward, 2); // Claimed } }; } else { button.style.display = 'none'; } } ``` -------------------------------- ### Data Link Example Source: https://en.docsv2.balancy.dev/cms/extra/data_scheme Example URL structure for accessing specific template data. ```text https://cdn.unnychat.com/entities/11111111-1111-1111-111111111111/dev/EnemyInfo_v3.json ``` -------------------------------- ### Manage event state and progress Source: https://en.docsv2.balancy.dev/ui_builder Use these functions to initialize events, start new ones based on configuration, and claim rewards upon task completion. ```javascript // Example: Managing event state and progress async function initializeEvent() { // Load event configuration and custom data const eventConfig = await balancy.getDocumentValue(window.balancyViewOwner.unnyIdGameEvent, 3); const customEventInfo = await balancy.getCustomEventInfo(); const tasks = await balancy.getTasks(); // Initialize based on current state if (!customEventInfo.started) { await startNewEvent(eventConfig); } else { continueEvent(customEventInfo, tasks); } } async function startNewEvent(eventConfig) { // Save custom event data const customData = { started: true, startTime: Math.floor(Date.now() / 1000), progress: {} }; await balancy.setCustomEventInfo(customData); // Activate event tasks const activeTasks = await balancy.activateTasks([eventConfig.task.unnyId]); console.log('Event started with tasks:', activeTasks); } async function completeEventTask(taskId) { const success = await balancy.claimTaskReward(taskId); if (success) { // Award inventory items await balancy.addInventoryItems('reward_coins', 100); console.log('Task completed and reward claimed'); } } ``` -------------------------------- ### Balancy.Main.Init(config) Source: https://en.docsv2.balancy.dev/advanced/init Initializes the Balancy SDK with the provided configuration object. ```APIDOC ## Balancy.Main.Init(config) ### Description Initializes the Balancy SDK. This process downloads necessary data from the server, caches it locally, and sets up periodic update checks. ### Parameters - **config** (AppConfig) - Required - Configuration object containing game credentials and initialization settings. ### AppConfig Properties #### Mandatory Parameters - **ApiGameId** (string) - Required - A unique GUID associated with your game. - **PublicKey** (string) - Required - Essential public key for game operations. - **Environment** (Enum) - Required - Specifies the connection environment (e.g., Development). #### Additional Parameters - **AutoLogin** (bool) - Optional - Automatically authenticates user by device ID (Default: true). - **DevicePlatform** (string) - Optional - Identifies the device platform (Default: autodetect). - **BalancyPlatform** (string) - Optional - Identifies the payment platform (Default: autodetect). - **LaunchType** (Enum) - Optional - Defines data usage: Local and/or Cloud (Default: All). - **UpdateType** (Enum) - Optional - Dictates content update extent (Default: FullUpdate). - **UpdatePeriod** (int) - Optional - Time in seconds between update attempts (Default: 600). - **OnProgressUpdateCallback** (Action) - Optional - Callback for loading progress. - **CustomId** (string) - Optional - Third-party system user ID. #### Optional Parameters - **DeviceId** (string) - Optional - Unique device ID for authentication (Default: autodetect). - **AppVersion** (string) - Optional - Application version (Default: autodetect). - **EngineVersion** (string) - Optional - Engine version (Default: autodetect). - **BranchName** (string) - Optional - Balancy branch name (Default: autodetect). ``` -------------------------------- ### Initialize Battle Pass Source: https://en.docsv2.balancy.dev/ui_builder Sets up the Battle Pass by delaying the ready signal, fetching configuration and progress, and initializing UI components. ```javascript async function initializeBattlePass() { // Delay automatic ready signal balancy.delayIsReady(); try { // Load configuration and progress const config = await balancy.getBattlePassConfig(); const progress = await balancy.getBattlePassProgress(); // Setup UI setupHeader(progress, config.scores); setupRewardTrack(config.rewards, progress); setupClaimButtons(config.rewards, progress); // Notify ready balancy.sendIsReady(); } catch (error) { console.error('Failed to initialize battle pass:', error); } } window.addEventListener('balancy-ready', initializeBattlePass, { once: true }); ``` -------------------------------- ### Balancy_UI_LiveOps_GameOffer.init Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the game offer component with offer information. ```APIDOC ## Balancy_UI_LiveOps_GameOffer.init ### Description Initializes the game offer component using an OfferInfo runtime wrapper. ### Parameters - **offerInfo** (object) - Required - The OfferInfo object containing offer details. ``` -------------------------------- ### balancy.getProductInfo(product) Source: https://en.docsv2.balancy.dev/ui-builder/api Gets IAP product information from the platform store. ```APIDOC ## balancy.getProductInfo(product) ### Description Gets IAP product information from the platform store. ### Parameters - **product** (object) - Required - Product document ### Returns - Promise ### Example const productInfo = await balancy.getProductInfo(price.product); ``` -------------------------------- ### Owner Data Configuration Source: https://en.docsv2.balancy.dev/ui-builder/attributes Example of the window.balancyViewOwner object used for data resolution. ```javascript window.balancyViewOwner = { instanceId: "f09ab140-3752-4593-98e3-48a31046", gameOffer: null, // Will be auto-resolved unnyIdGameOffer: "1188", // Used for resolution discount: 25, priceUSD: 4.99 }; ``` -------------------------------- ### Balancy_UI_LiveOps_ShopPage.init(shopPage) Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the shop page component with a ShopPage runtime object. ```APIDOC ## init(shopPage) ### Description Initializes the shop page component with a ShopPage runtime object to display shop slots. ### Parameters - **shopPage** (object) - Required - The ShopPage runtime object. ``` -------------------------------- ### IndexedDBFileHelperAdapter.create Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Initializes the IndexedDB-based file system adapter for browser environments. ```APIDOC ## IndexedDBFileHelperAdapter.create ### Description Creates and initializes an IndexedDB file helper adapter for persistent storage in browser environments. ### Parameters - **cachePath** (string) - Required - Path where the files will be saved. - **codePath** (string) - Optional - Path for generated code files. - **resourcesPath** (string) - Optional - Path for downloaded resources. ### Example ```typescript const fileHelperAdapter = await IndexedDBFileHelperAdapter.create({ cachePath: '.balancy', codePath: 'src/auto-generated-code', resourcesPath: 'src/resources' }); ``` ``` -------------------------------- ### Download configurations via CLI Source: https://en.docsv2.balancy.dev/advanced/engines/typescript Use this command to fetch configurations and assets from the selected branch and save them to a specified local directory. ```bash npm run balancy -- config-download -c .balancy -p src/resources ``` -------------------------------- ### Get Profile Value Source: https://en.docsv2.balancy.dev/ui_builder Retrieves a value from a specific profile by name and path. ```javascript const value = await balancy.getProfileValue('PlayerData', 'Achievements.Completed'); ``` -------------------------------- ### Get product information Source: https://en.docsv2.balancy.dev/ui-builder/api Retrieves IAP product details from the platform store. ```javascript const productInfo = await balancy.getProductInfo(price.product); console.log(productInfo.LocalizedPriceString); // "$4.99" ``` -------------------------------- ### Instantiate Offer View Prefab Source: https://en.docsv2.balancy.dev/ui-builder/templates Listens for the balancy-ready event to instantiate and initialize an offer view prefab. ```javascript // Offer view script async function main() { const offerInfo = window.balancyViewOwner; const viewObject = await balancy.instantiatePrefabById('offer-view'); const script = viewObject.getComponent(Balancy_UI_LiveOps_GameOffer); script.init(offerInfo); document.body.appendChild(viewObject.element); } window.addEventListener('balancy-ready', main, { once: true }); ``` -------------------------------- ### Initialize Balancy SDK in Unity Source: https://en.docsv2.balancy.dev/quick_start/engines/unity Manual initialization of the Balancy SDK using AppConfig and event callbacks. Ensure callbacks are subscribed before calling Init. ```csharp using Balancy; using Balancy.Data; public class BalancyInit : MonoBehaviour { void Start() { var config = new AppConfig { ApiGameId = "", PublicKey = "", Environment = Constants.Environment.Development, OnProgressUpdateCallback = (fileName, progress) => { Debug.Log($"Loading {(int)(progress * 100)}% - {fileName}"); } }; // Subscribe to callbacks BEFORE calling Init SubscribeToCallbacks(); Balancy.Main.Init(config); } void SubscribeToCallbacks() { // Mandatory: fires multiple times during initialization. // Start the game on the FIRST callback (local cached data). // Refresh when cloud sync completes with the latest data. Balancy.Callbacks.OnDataUpdated += status => { Debug.Log($"Data updated β€” Cloud: {status.IsCloudSynced}, CMS: {status.IsCMSUpdated}"); // Always refresh game data on every callback ListActiveEvents(); if (status.IsCloudSynced) { // Second callback - cloud sync complete if (status.IsCMSUpdated || status.IsProfileUpdated) { Debug.Log("[Balancy] Cloud data synchronized!"); //OnBalancyRefreshed(); } } else { // First callback - local data ready Debug.Log("[Balancy] Local data ready - Game can start!"); //OnBalancyReady(); } }; // LiveOps: event activated Balancy.Callbacks.OnNewEventActivated += eventInfo => Debug.Log($"Event started: {eventInfo?.GameEvent?.Name}"); // LiveOps: event deactivated Balancy.Callbacks.OnEventDeactivated += eventInfo => Debug.Log($"Event ended: {eventInfo?.GameEvent?.Name}"); // LiveOps: offer activated Balancy.Callbacks.OnNewOfferActivated += offerInfo => Debug.Log($"Offer started: {offerInfo?.GameOffer?.Name}"); // LiveOps: offer deactivated Balancy.Callbacks.OnOfferDeactivated += (offerInfo, wasPurchased) => Debug.Log($"Offer ended: {offerInfo?.GameOffer?.Name}, purchased: {wasPurchased}"); // Error handling Balancy.Callbacks.OnAuthFailed += status => Debug.LogError($"Auth failed: {status.Message}"); } void ListActiveEvents() { var smartInfo = Balancy.Profiles.System.SmartInfo; // Active Game Events foreach (var eventInfo in smartInfo.GameEvents) { var secondsLeft = eventInfo.GetSecondsLeftBeforeDeactivation(); Debug.Log($"Active event: {eventInfo.GameEvent?.Name} β€” {secondsLeft}s remaining"); } // Active Offers foreach (var offerInfo in smartInfo.GameOffers) { Debug.Log($"Active offer: {offerInfo.GameOffer?.Name}"); } } } ``` -------------------------------- ### Shop, ShopPage, and ShopSlot Hierarchy Source: https://en.docsv2.balancy.dev/ui-builder/scripts Demonstrates the instantiation and initialization flow from Shop to ShopPage and finally to individual ShopSlot components. ```javascript // Shop creates pages class Shop { async _createPages() { for (const shopPage of this._shop.pages) { // Use page's custom view or default page prefab const viewId = shopPage.page?.unnyView?.id; const pageObject = viewId ? await balancy.instantiatePrefabById(viewId) : this.defaultPagePrefab.instantiate(); const pageScript = pageObject.getComponent(Balancy_UI_LiveOps_ShopPage); pageScript.init(shopPage); } } } // ShopPage creates slots class ShopPage { async _createSlots() { for (const shopSlot of this._shopPage.slots) { // Use slot's custom view or default slot prefab const viewId = shopSlot.unnyView?.id; const slotObject = viewId ? await balancy.instantiatePrefabById(viewId) : this.defaultSlotPrefab.instantiate(); const slotScript = slotObject.getComponent(Balancy_UI_LiveOps_ShopSlot); slotScript.init(shopSlot); } } } // ShopSlot is self-contained (similar to StoreItem but for shops) class ShopSlot { async init(shopSlot) { const storeItem = shopSlot.slot.storeItem; // Apply name, icon, rewards this._applyName(storeItem); this._applyIcon(storeItem); // Initialize buy button const buyButtonScript = this.buyButton.getComponent(Balancy_UI_Common_BuyButton); buyButtonScript.init({ price: storeItem.price, storeItem: storeItem, onBuy: () => this._handleBuy() }); } } ``` -------------------------------- ### Define Owner Data Structures Source: https://en.docsv2.balancy.dev/ui-builder/views Example structures for GameOffer and GameEvent objects assigned to window.balancyViewOwner. ```javascript window.balancyViewOwner = { instanceId: "f09ab140-3752-4593-98e3-48a31046", gameOffer: null, // Will be resolved automatically unnyIdGameOffer: "1188", // Used for document resolution productId: "coin_pack_small", status: 1, // ... other offer fields }; ``` ```javascript window.balancyViewOwner = { unnyIdGameEvent: "663", eventName: "Summer Festival", startTime: 1751328000, endTime: 1751414400, // ... other event fields }; ``` -------------------------------- ### Implement Balancy_UI_LiveOps_Reward in ElementBehaviour Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of using the reward component within a custom ElementBehaviour class. ```javascript class MyOffer extends balancy.ElementBehaviour { // @serialize {element} rewardComponent = null; init(offer) { const rewardScript = this.rewardComponent.getComponent(Balancy_UI_LiveOps_Reward); rewardScript.init(offer.storeItem.reward); // Automatically displays all items in the reward } } ``` -------------------------------- ### Initialize Balancy with Environment Selection Source: https://en.docsv2.balancy.dev/cms/advanced/environment Use this configuration to initialize the Balancy SDK and dynamically select the environment based on preprocessor directives. ```csharp Balancy.Main.Init(new AppConfig { ApiGameId = , PublicKey = , OnReadyCallback = response => { if (!response.Success) Debug.LogError("Couldn't initialize Balancy"); }, Environment = GetEnvironment() }); public static Balancy.Constants.Environment GetEnvironment() { #if SERVER_PROD return Balancy.Constants.Environment.Production; #elif SERVER_STAGE return Balancy.Constants.Environment.Stage; #else return Balancy.Constants.Environment.Development; #endif } ``` -------------------------------- ### Implement Progressive Authentication Source: https://en.docsv2.balancy.dev/advanced/authentication Demonstrates transitioning from guest authentication to account linking to preserve player progress. ```C# void Start() { API.Auth.AsGuest(OnGuestAuthComplete); } void OnPlayerReachesLevel5() { ShowNotification("Link your account to save progress across devices!"); ShowLinkAccountButton(); } ``` ```TypeScript // autoLogin: true handles guest auth automatically function onPlayerReachesLevel5() { showNotification('Link your account to save progress across devices!'); showLinkAccountButton(); } ``` -------------------------------- ### Get and display remaining time Source: https://en.docsv2.balancy.dev/ui-builder/api Retrieves the remaining time from settings and updates a DOM element. ```javascript const timeLeft = balancy.getTimeLeft(); document.getElementById('timer').textContent = balancy.formatTime(timeLeft); ``` -------------------------------- ### Preload assets and wait for completion Source: https://en.docsv2.balancy.dev/advanced/preloading Demonstrates the pattern of preloading multiple assets and executing a callback once all downloads are finished. ```C# // 1. Preload all offer icons foreach (var offer in activeOffers) { offer.GameOffer.Icon?.Preload(); } // 2. Wait for everything to finish Balancy.Dictionaries.DataObjectsManager.WaitForPreloading(() => { // 3. All icons are now cached β€” show the offers UI ShowOffersScreen(activeOffers); }); ``` ```TypeScript // 1. Preload all offer icons for (const offer of activeOffers) { const iconId = offer.gameOffer?.icon?.id; if (iconId) { DataObjectsManager.loadSprite(iconId, () => {}); } } // 2. Wait for everything to finish DataObjectsManager.waitForPreloading(() => { // 3. All icons are now cached β€” show the offers UI showOffersScreen(activeOffers); }); ``` -------------------------------- ### Get image URL Source: https://en.docsv2.balancy.dev/ui-builder/api Retrieves the remote URL for an image asset using its unique identifier. ```javascript const imageUrl = await balancy.getImageUrl('123'); document.getElementById('icon').src = imageUrl; ``` -------------------------------- ### Implement Account Linking and Conflict Resolution Source: https://en.docsv2.balancy.dev/advanced/authentication Demonstrates how to link an account using email and password, with a fallback to handle 409 conflict errors by offering to force the link or switch accounts. ```C# public class AccountLinkingManager : MonoBehaviour { private void OnLinkEmailSubmit(string email, string password) { ShowLoadingIndicator(); // First attempt without forceLink to detect conflicts API.Link.WithNameAndPassword(email, password, false, (LinkResponseData response) => { HideLoadingIndicator(); if (response.Success) { ShowNotification("Email linked to your account!"); } else if (response.ErrorCode == 409) { ShowBindingConflictDialog(email, password); } else { ShowError($"Linking failed: {response.ErrorMessage}"); } }); } private void ShowBindingConflictDialog(string email, string password) { ConflictDialog.Show( message: "This email is already linked to another account.", option1: "Unlink & Link to Current Account", option2: "Switch to Other Account", onOption1: () => { API.Link.WithNameAndPassword(email, password, true, response => { if (response.Success) ShowNotification("Email linked!"); }); }, onOption2: () => { API.Auth.WithNameAndPassword(email, password, response => { if (response.Success) OnAccountSwitched(); }); } ); } } ``` ```TypeScript function onLinkEmailSubmit(email: string, password: string) { showLoadingIndicator(); // First attempt without forceLink to detect conflicts Balancy.API.Link.withEmailAndPassword(email, password, false, (response) => { hideLoadingIndicator(); if (response.success) { showNotification('Email linked to your account!'); } else if (response.errorCode === 409) { showBindingConflictDialog(email, password); } else { showError(`Linking failed: ${response.errorMessage}`); } }); } function onForceLinkClicked(email: string, password: string) { Balancy.API.Link.withEmailAndPassword(email, password, true, (response) => { if (response.success) showNotification('Email linked!'); }); } function onSwitchAccountClicked(email: string, password: string) { Balancy.API.Auth.withEmailAndPassword(email, password, (response) => { if (response.success) onAccountSwitched(); }); } ``` -------------------------------- ### Get localized text Source: https://en.docsv2.balancy.dev/ui-builder/api Fetches the localized string associated with a specific key for UI display. ```javascript const welcomeText = await balancy.getLocalizedText('welcome_message'); document.getElementById('title').textContent = welcomeText; ``` -------------------------------- ### GET /entities/{game_id}/{branch_name}/versions.json Source: https://en.docsv2.balancy.dev/cms/extra/data_scheme Retrieves version information for a specific branch of a game. ```APIDOC ## GET https://cdn.unnychat.com/entities/{game_id}/{branch_name}/versions.json ### Description Retrieves version information for a specific branch of a game. ### Method GET ### Endpoint https://cdn.unnychat.com/entities/{game_id}/{branch_name}/versions.json ### Parameters #### Path Parameters - **game_id** (string) - Required - The GUID of your game. - **branch_name** (string) - Required - The name of the branch to access. ``` -------------------------------- ### Balancy_UI_LiveOps_GameOfferGroup.init Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the game offer group component. ```APIDOC ## Balancy_UI_LiveOps_GameOfferGroup.init ### Description Initializes the group offer component with multiple purchase options. ### Parameters - **offerGroupInfo** (object) - Required - The OfferGroupInfo runtime wrapper. ``` -------------------------------- ### Balancy_UI_LiveOps_ShopSlot.init Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the shop slot component with slot data and purchase options. ```APIDOC ## Balancy_UI_LiveOps_ShopSlot.init ### Description Initializes the shop slot component to handle purchase functionality. ### Parameters - **shopSlot** (object) - Required - The shop slot data. - **options** (object) - Required - Configuration object including the onBuy callback. ``` -------------------------------- ### Retrieve All Products Source: https://en.docsv2.balancy.dev/advanced/api Asynchronously fetch all configured products and iterate through the results. ```C# Balancy.API.GetProducts(response => { if (response.Success) { foreach (var product in response.Products) { Debug.Log($"Product: {product.Name} => {product.ProductId}"); Debug.Log($" Platform Product ID: {product.PlatformProductId}"); Debug.Log($" Price: {product.Price}"); Debug.Log($" Type: {product.Type}"); } } else { Debug.LogError($"Failed to get products: {response.ErrorMessage} (Code: {response.ErrorCode})"); } }); ``` ```TypeScript Balancy.API.getProducts(response => { if (response.success) { response.products.forEach(product => { console.log(`Product: ${product.name} => ${product.productId}`); console.log(` Platform Product ID: ${product.platformProductId}`); console.log(` Price: ${product.price}`); console.log(` Type: ${product.type}`); }); } else { console.error(`Failed to get products: ${response.errorMessage} (Code: ${response.errorCode})`); } }); ``` -------------------------------- ### Button Action Attributes Source: https://en.docsv2.balancy.dev/ui_builder HTML examples of using data-button-action and related attributes to trigger Balancy actions. ```html ``` -------------------------------- ### Implement Balancy_UI_Common_BuyButton in ElementBehaviour Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of integrating the buy button within a custom Balancy ElementBehaviour class. ```javascript class MyOffer extends balancy.ElementBehaviour { // @serialize {element} buyButton = null; async start() { const script = this.buyButton.getComponent(Balancy_UI_Common_BuyButton); await script.init({ price: this.offer.price, storeItem: this.offer.storeItem, onBuy: () => this.purchase() }); } async purchase() { const result = await balancy.buyOffer(); if (result) { this.buyButton.getComponent(Balancy_UI_Common_BuyButton) .setState(balancy.BuyButtonState.Cooldown, { cooldownSeconds: 3600 }); } } } ``` -------------------------------- ### Balancy_UI_LiveOps_StoreItem.init Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the store item component with store item data and configuration options. ```APIDOC ## Balancy_UI_LiveOps_StoreItem.init ### Description Initializes the store item display with the provided store item document and configuration options. ### Parameters - **storeItem** (object) - Required - The store item document. - **options** (object) - Required - Configuration object including state, cooldownSeconds, and onBuy callback. ``` -------------------------------- ### balancy-components-complete Source: https://en.docsv2.balancy.dev/ui-builder/events Fired when all script components have been initialized, ensuring that components are ready for interaction. ```APIDOC ## Event: balancy-components-complete ### Description Fired when all script components have been initialized (after `awake()` and `onEnable()` called). ### Usage ```javascript document.addEventListener('balancy-components-complete', () => { console.log('All components initialized'); }); ``` ``` -------------------------------- ### LiveOps Strategy Examples Source: https://en.docsv2.balancy.dev/liveops/overview A list of common operational activities used to maintain and evolve game services. ```text βœ… Adding a skimming pricing(*) strategy to your shop βœ… Adjusting the frequency of ads to various segments of players βœ… Decorating a game for St. Valentine’s Day and adding new festive skins βœ… Promoting your in-game tournament on social media, where your community gathers βœ… Bug fixes and app productivity optimization (*) Skimming pricing initially sets a relatively high price for an offer and subsequently lowers it over time. ``` -------------------------------- ### Get inventory item count Source: https://en.docsv2.balancy.dev/ui-builder/api Retrieves the current quantity of a specific item in the player's inventory. ```javascript const coinCount = await balancy.getInventoryItemsCount('coins'); console.log(`Player has ${coinCount} coins`); ``` -------------------------------- ### Get Next Reward Source: https://en.docsv2.balancy.dev/advanced/data_profiles Determine if the next reward is a special bonus or a regular reward and retrieve its details. ```C# var nextReward = dailyBonusInfo.GetNextReward(); bool isNextRewardBonus = dailyBonusInfo.IsNextRewardBonus(); if (isNextRewardBonus) { Debug.Log("Next reward is the bonus reward!"); var bonusReward = dailyBonusInfo.DailyBonus?.BonusReward; // Display bonus reward... } else if (nextReward != null) { Debug.Log("Next regular reward:"); foreach (var item in nextReward.Items) { Debug.Log($" - {item?.Item?.Name} x{item?.Count}"); } } ``` ```TypeScript const nextReward = dailyBonusInfo.getNextReward(); const isNextRewardBonus = dailyBonusInfo.isNextRewardBonus(); if (isNextRewardBonus) { console.log("Next reward is the bonus reward!"); const bonusReward = dailyBonusInfo.dailyBonus?.bonusReward; // Display bonus reward... } else if (nextReward) { console.log("Next regular reward:"); nextReward.items?.forEach(item => { console.log(` - ${item?.item?.name?.value} x${item?.count}`); }); } ``` -------------------------------- ### Balancy_UI_LiveOps_Reward.init(reward) Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the reward component to display a collection of items. ```APIDOC ## init(reward) ### Description Initializes the reward component with a reward document containing multiple items. It automatically instantiates the item prefab for each item in the reward. ### Parameters - **reward** (object) - Required - The reward document containing ItemWithAmount objects. ``` -------------------------------- ### Listen to balancy-ready event Source: https://en.docsv2.balancy.dev/ui-builder/events Use this event to trigger logic once the UI is fully initialized. The 'once' flag is recommended for initialization tasks. ```javascript document.addEventListener('balancy-ready', () => { console.log('Balancy UI is fully initialized'); // Start animations, timers, etc. }); // Or with once flag window.addEventListener('balancy-ready', main, { once: true }); async function main() { // Your initialization code const offers = await balancy.getActiveOffers(); displayOffers(offers); } ``` -------------------------------- ### Initialize Balancy_UI_Common_BuyButton Source: https://en.docsv2.balancy.dev/ui-builder/scripts Initializes the buy button with price, store item, callback, and state configuration. ```javascript await buyButton.init({ price: priceDocument, // Required: Price document storeItem: storeItemDocument, // Required for Ads price onBuy: () => handlePurchase(), // Callback when clicked state: balancy.BuyButtonState.Available, // Initial state cooldownSeconds: 0 // For cooldown state }); ``` -------------------------------- ### Implement Balancy_UI_Common_BuyPrice in ElementBehaviour Source: https://en.docsv2.balancy.dev/ui-builder/scripts Example of integrating the price display component within a custom Balancy ElementBehaviour class. ```javascript class PriceDisplay extends balancy.ElementBehaviour { // @serialize {element} priceComponent = null; async start() { const script = this.priceComponent.getComponent(Balancy_UI_Common_BuyPrice); await script.init( this.storeItem.price, this.storeItem ); } } ``` -------------------------------- ### Implement a loading screen Source: https://en.docsv2.balancy.dev/advanced/preloading Uses the wait callback to toggle UI visibility during asset initialization. ```C# // Show loading screen loadingScreen.SetActive(true); Balancy.Dictionaries.DataObjectsManager.WaitForPreloading(() => { loadingScreen.SetActive(false); ShowMainMenu(); }); ```