Payment
Implement player payments and credit management in your game
Payment
PlayKit SDK supports a player payment model where players purchase credits (Sparks) to use AI features. This page explains how to implement credit queries and payment flows in your game.
Developer Costs vs Player Payment
PlayKit provides two billing modes:
Developer Billing Mode (Development Phase)
- Uses Developer Token
- All AI call costs charged to developer account
- Suitable for: Development, testing, prototyping
Player Billing Mode (Production)
- Players purchase credits
- Each AI call deducts from player credits
- Suitable for: Released games
Query Player Credits
Use PlayKit_PlayerClient to query player's current credit balance:
using Cysharp.Threading.Tasks;
using PlayKit_SDK;
using UnityEngine;
public class PlayerCreditDisplay : MonoBehaviour
{
async void Start()
{
// Ensure SDK is initialized
if (!PlayKitSDK.IsReady())
{
await PlayKitSDK.InitializeAsync();
}
// Get player client
var playerClient = PlayKitSDK.GetPlayerClient();
// Query player info
var playerInfo = await playerClient.GetPlayerInfoAsync(
this.GetCancellationTokenOnDestroy()
);
if (playerInfo.Success)
{
Debug.Log($"Player ID: {playerInfo.Response.UserId}");
Debug.Log($"Current credits: {playerInfo.Response.Credits}");
// Update UI display
UpdateCreditDisplay(playerInfo.Response.Credits);
}
else
{
Debug.LogError($"Failed to get player info: {playerInfo.ErrorMessage}");
}
}
void UpdateCreditDisplay(int credits)
{
// Update credit display UI
}
}Handle Insufficient Credits
When player credits are insufficient, AI calls will fail. You need to detect this and guide players to recharge:
using Cysharp.Threading.Tasks;
using PlayKit_SDK;
using PlayKit_SDK.Public;
using System.Collections.Generic;
using UnityEngine;
public class CreditCheck : MonoBehaviour
{
public async UniTask<bool> TryGenerateText(string message)
{
var chatClient = PlayKitSDK.Factory.CreateChatClient();
var messages = new List<PlayKit_ChatMessage>
{
new PlayKit_ChatMessage { Role = "user", Content = message }
};
var config = new PlayKit_ChatConfig(messages);
var result = await chatClient.TextGenerationAsync(
config,
this.GetCancellationTokenOnDestroy()
);
if (!result.Success)
{
// Check if insufficient credits error
if (result.ErrorMessage.Contains("insufficient credits") ||
result.ErrorMessage.Contains("Insufficient"))
{
Debug.LogWarning("Player has insufficient credits");
// Show recharge prompt
ShowRechargePrompt();
return false;
}
else
{
Debug.LogError($"Request failed: {result.ErrorMessage}");
return false;
}
}
return true;
}
void ShowRechargePrompt()
{
// Show recharge UI or prompt
Debug.Log("Please visit recharge page to purchase credits");
}
}Real-time Credit Monitoring
Monitor player credits in real-time and alert when balance falls below threshold:
using Cysharp.Threading.Tasks;
using PlayKit_SDK;
using UnityEngine;
public class CreditMonitor : MonoBehaviour
{
[SerializeField] private int lowCreditThreshold = 100;
[SerializeField] private float checkInterval = 60f; // Check every minute
private int currentCredits;
private bool isMonitoring = false;
async void Start()
{
await StartMonitoring();
}
public async UniTask StartMonitoring()
{
if (isMonitoring) return;
isMonitoring = true;
while (isMonitoring)
{
await UpdateCredits();
await UniTask.Delay((int)(checkInterval * 1000));
}
}
public async UniTask UpdateCredits()
{
var playerClient = PlayKitSDK.GetPlayerClient();
var result = await playerClient.GetPlayerInfoAsync(
this.GetCancellationTokenOnDestroy()
);
if (result.Success)
{
int previousCredits = currentCredits;
currentCredits = result.Response.Credits;
// Credit change notification
if (previousCredits != currentCredits)
{
OnCreditsChanged(previousCredits, currentCredits);
}
// Low credit warning
if (currentCredits < lowCreditThreshold)
{
OnLowCredits(currentCredits);
}
}
}
void OnCreditsChanged(int oldValue, int newValue)
{
Debug.Log($"Credits changed: {oldValue} -> {newValue}");
// Update UI
// Trigger events
}
void OnLowCredits(int credits)
{
Debug.LogWarning($"Low credit warning: {credits} credits remaining");
// Show low credit prompt
}
void OnDestroy()
{
isMonitoring = false;
}
}Recharge Flow Integration
Recharge functionality is implemented through the PlayKit platform's payment interface. See PlayKit Platform documentation for specific integration methods.
Basic Recharge Flow
- Player clicks recharge button
- Open PlayKit recharge page or use SDK's recharge interface
- Player completes payment
- Credits automatically added to player account
- Game detects credit change and updates display
Example: Open Recharge Page
using UnityEngine;
public class RechargeButton : MonoBehaviour
{
[SerializeField] private string rechargeURL = "https://playkit.ai/recharge";
public void OnRechargeClicked()
{
// Open recharge page in browser
Application.OpenURL(rechargeURL);
// Check credits when app resumes after recharge
StartCoroutine(WaitForRecharge());
}
System.Collections.IEnumerator WaitForRecharge()
{
yield return new WaitForSeconds(2f);
// Check if credits updated
var monitor = FindObjectOfType<CreditMonitor>();
if (monitor != null)
{
monitor.UpdateCredits().Forget();
}
}
}Estimate Feature Costs
Different AI features consume different credits. You can show estimated costs to players before calling:
Text Generation Cost Estimation
public class CostEstimator
{
// Rough estimation (actual costs depend on model and token count)
public int EstimateTextGenerationCost(string prompt)
{
// Estimate input tokens (~4 chars/token for English, ~1 char/token for Chinese)
int estimatedInputTokens = prompt.Length / 2;
// Estimate output tokens (assume similar to input length)
int estimatedOutputTokens = estimatedInputTokens;
// GPT-4o-mini price example (check platform for actual prices)
// Input: $0.150 / 1M tokens
// Output: $0.600 / 1M tokens
double inputCost = estimatedInputTokens * 0.00000015;
double outputCost = estimatedOutputTokens * 0.00000060;
// Convert to credits (assume 1 credit = $0.01)
int credits = Mathf.CeilToInt((float)((inputCost + outputCost) * 100));
return Mathf.Max(credits, 1); // Minimum 1 credit
}
public int EstimateImageGenerationCost(string size)
{
// DALL-E 3 price example
switch (size)
{
case "1024x1024": return 4; // $0.040
case "1024x1792": return 8; // $0.080
case "1792x1024": return 8; // $0.080
default: return 2;
}
}
}Show Cost Before Call
using UnityEngine;
using UnityEngine.UI;
public class AIFeatureButton : MonoBehaviour
{
[SerializeField] private Text costText;
[SerializeField] private Button executeButton;
private CostEstimator estimator = new CostEstimator();
private int estimatedCost;
public void SetPrompt(string prompt)
{
estimatedCost = estimator.EstimateTextGenerationCost(prompt);
costText.text = $"Estimated cost: {estimatedCost} credits";
// Check if player can afford
CheckCanAfford();
}
async void CheckCanAfford()
{
var playerClient = PlayKitSDK.GetPlayerClient();
var result = await playerClient.GetPlayerInfoAsync(
this.GetCancellationTokenOnDestroy()
);
if (result.Success)
{
bool canAfford = result.Response.Credits >= estimatedCost;
executeButton.interactable = canAfford;
if (!canAfford)
{
costText.text = $"Insufficient credits (need {estimatedCost}, have {result.Response.Credits})";
}
}
}
}Best Practices
- Display credits in real-time: Always show player's current credits in game UI
- Warn early: Alert players to recharge when credits fall below threshold
- Show estimated costs: Tell players approximately how many credits each AI feature costs
- Handle failures gracefully: When credits are insufficient, provide clear recharge guidance
- Cache player info: Avoid frequent queries, use event-driven updates
- Provide trial credits: Consider giving new players some free credits to experience features
Cost Optimization
Ways to help players save credits:
- Use cheaper models: Use gpt-4o-mini instead of gpt-4 for simple tasks
- Limit output length: Use
maxTokensparameter to limit response length - Reuse results: Cache answers to common questions
- Compress prompts: Simplify system prompts and user inputs
- Reasonable temperature settings: Lower temperature values may produce shorter responses
var config = new PlayKit_ChatConfig(messages) { Temperature = 0.5f, MaxTokens = 150 };Next Steps
- Learn Publishing Guide to prepare your game for production
- Check PlayKit Platform for detailed pricing information
- Read API Reference for complete PlayerClient API