Unity Integration (C#)
This guide shows how to integrate Scrya ads into a Unity project using UnityWebRequest. The pattern works for any Unity version supporting .NET 4.x or later.
Setup
No package to install — Scrya is a REST API. You just need your API key and these helper methods.
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Text;
public class ScryaAds : MonoBehaviour
{
private const string API_BASE = "https://api.scrya.com/api/ads";
private string apiKey = "sk_live_your_key_here";
private string gameId = "your_game_id";
private IEnumerator PostJson(string endpoint, string json,
System.Action<string> onSuccess, System.Action<string> onError = null)
{
var request = new UnityWebRequest(API_BASE + endpoint, "POST");
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(json));
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Authorization", "Bearer " + apiKey);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
onSuccess?.Invoke(request.downloadHandler.text);
else
onError?.Invoke(request.error);
}
} Step 1: Match an Ad
Call this when generating a scene (dilemma, dialogue, cutscene):
[System.Serializable]
public class AdMatchRequest
{
public string game_id;
public string user_id;
public PlayerGeo player_geo;
public GameContext game_context;
public string session_id;
}
[System.Serializable]
public class PlayerGeo { public string country_code; public string state_code; }
[System.Serializable]
public class GameContext
{
public string theme_id;
public string category;
public string narrative;
public string[] mood_tags;
}
[System.Serializable]
public class AdMatchResponse
{
public string campaign_id;
public string creative_id;
public string narrative_hook;
public string creative_type;
public string brand_name;
public int cpm_bid_cents;
}
public IEnumerator MatchAd(string playerId, string narrative, string[] moods,
System.Action<AdMatchResponse> callback)
{
var request = new AdMatchRequest
{
game_id = gameId,
user_id = playerId,
player_geo = new PlayerGeo { country_code = "US" },
game_context = new GameContext
{
theme_id = "3",
category = "simulation",
narrative = narrative,
mood_tags = moods
},
session_id = System.Guid.NewGuid().ToString()
};
yield return PostJson("/match", JsonUtility.ToJson(request), (json) =>
{
var match = JsonUtility.FromJson<AdMatchResponse>(json);
callback?.Invoke(match);
}, (error) =>
{
Debug.Log("No ad matched (normal): " + error);
callback?.Invoke(null);
});
} Step 2: Apply Visual Bias
If the match includes a biased_pipeline, apply it to your scene:
// After getting a match:
if (match != null)
{
// Inject narrative hook into dialogue
dialogueSystem.AddLine(match.narrative_hook);
// Optionally simulate to get visual bias
StartCoroutine(SimulateBias(match.campaign_id, "crisis", "tense, kinetic",
(sim) =>
{
// Apply biased lighting
if (!string.IsNullOrEmpty(sim.biased_lighting))
sceneLighting.SetPreset(sim.biased_lighting);
// Apply biased effects
if (!string.IsNullOrEmpty(sim.biased_effects))
postProcessing.SetPreset(sim.biased_effects);
}));
} Step 3: Record the Impression
[System.Serializable]
public class ImpressionRequest
{
public string campaign_id;
public string creative_id;
public string game_id;
}
public IEnumerator RecordImpression(AdMatchResponse match)
{
if (match == null) yield break;
var request = new ImpressionRequest
{
campaign_id = match.campaign_id,
creative_id = match.creative_id,
game_id = gameId
};
yield return PostJson("/impressions", JsonUtility.ToJson(request),
(json) => Debug.Log("Impression recorded"),
(error) => Debug.LogWarning("Impression failed: " + error));
} Full Example: Scene Generation
public IEnumerator GenerateSceneWithAds(string playerId, string narrative)
{
AdMatchResponse match = null;
// 1. Match
yield return MatchAd(playerId, narrative,
new[] { "tense", "urgent" },
(m) => match = m);
// 2. Inject
if (match != null)
{
dialogueSystem.AddLine(match.narrative_hook);
Debug.Log($"Ad from {match.brand_name}: {match.narrative_hook}");
}
// ... render the scene ...
// 3. Record (after player sees it)
yield return RecordImpression(match);
} Async/Await Alternative
If using Unity 2023+ with async/await support or UniTask:
public async Task<AdMatchResponse> MatchAdAsync(string playerId, string narrative)
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + apiKey);
var json = JsonUtility.ToJson(new AdMatchRequest { /* ... */ });
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(API_BASE + "/match", content);
if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
return null; // No matching ads
var responseJson = await response.Content.ReadAsStringAsync();
return JsonUtility.FromJson<AdMatchResponse>(responseJson);
}