Unity
Quickstart
This quickstart shows how to enable and use Reactional's In-Game Personalization features in your Unity project.
For an in project preview, you can download the Music Store Demo
.
This demo shows an implementation of a music store, with both a Unity Project and an external Game Server.
Before Getting Started
Make sure you have a mechanism to get Client credentials from your server-side, which you would have received as part of the Register new clients step.
Step 1: Install the Reactional Plugin for Unity
Follow the instructions in the Getting Started with the Reactional Plugin for Unity guide to install the Plugin into your Unity project.
Step 4 in the Getting Started page is not relevant with the workflow described in this page. Therefore, follow steps 1 through 5, skipping step 4.
Step 2: Initialize the Remote Service
The Remote service is the core component that handles all communication with Reactional's servers. Initialization should be performed early in your application lifecycle, typically when your game starts or when the player enters the main menu.
- Call Remote.Initialize to set up the service with your application credentials
- This function authenticates your application with Reactional's servers and establishes a secure connection
- Registers a new client if no id or secret has been passed to the function (but returns the used id and secret either way).
- After creation, clientId and clientSecret should be stored and retrieved from your own backend server to maintain security
- Initialization only needs to be performed once per application session
using Reactional.Services;
public class MusicStoreInitializerExample : MonoBehaviour
{
void Start()
{
// Replace with your actual client ID and secret
string clientId = "YOUR_CLIENT_ID";
string clientSecret = "YOUR_CLIENT_SECRET";
// Initialize the Remote service
Remote.Initialize(clientId, clientSecret);
}
}
Step 3: Retrieve available tracks to display in your in-game store
To fetch available music content to populate your in-game store interface, you would have to first retrieve playlists and iterate through the given tracks, using the info contained to display name or album artwork.
- Call Remote.GetPlaylists to fetch all available playlists and their associated tracks, passing your project id. The method returns paginated results, so you'll need to iterate through both playlist pages and track pages
- For each track, extract metadata such as title, artist information, and cover art URLs (for which you can call Preview.DownloadAlbumArtwork to asynchronously download the album artwork).
using Reactional.Services;
public class MusicStoreUIExample : MonoBehaviour
{
void Start()
{
var playlists = await Reactional.Services.Remote.GetPlaylists(projectId); // When not providing a users countryCode only tracks with worldwide access will be recieved
foreach (var page in playlists.Items)
{
foreach (var track in page.tracksPage.Items)
{
string songName = track.title;
string[] artistNames = track.artists.Select(a => a.name).ToArray();
var cover = await Reactional.Services.Preview.DownloadAlbumArtwork(track.image);
// Apply info to ui element
}
}
}
}
Step 4: Retrieve, load, and play purchased tracks
Here we simulate a purchase flow by creating a cart of selected tracks with proper pricing information. You will need to Handle the purchase transaction through your server-side payment processing (see demo for mock implementation). After a successful purchase, tracks are added to the user's purchased tracks collection
- Call Remote.GetTrack to retrieve the specified track data.
- Call Setup.LoadTrack to prepare the audio track for playback, loading it into the engine.
- Finally, call Playback.Playlist.Play to start audio playback.
using Reactional.Services;
public class MusicStorePurchaseExample : MonoBehaviour
{
List<TrackPayload> purchasedTracks = new List<TrackPayload>();
void Start()
{
List<TrackPayload> cart = GetTracksToPurchase(); // placeholder method
var items = new List<Dictionary<string, object>>();
foreach (var t in cart)
{
items.Add(new Dictionary<string, object> {
{ "id", t.id },
{ "price", t.priceInfo.b2c_price },
{ "type", "track" }
});
}
try
{
await MockPaymentMethod.PaymentHandler(items); // handle purchase on your server (see demo example)
}
catch(Exception e)
{
Debug.Log($"Failed to purchase tracks due to {e.Message}");
}
foreach (var t in cart)
{
purchasedTracks.Add(t);
}
// Load and play a random track
var selectedTrack = purchasedTracks[Random.Range(0, tracks.Count)];
var trackData = await Reactional.Services.Remote.GetTrack(selectedTrack); // When not providing a users countryCode only tracks with worldwide access will be recieved
await Reactional.Setup.LoadTrack(trackData);
Reactional.Playback.Playlist.Play();
}
}
Extra: Get clients' previously purchased tracks
This additional functionality allows you to sync a user's purchase history across devices and sessions, ensuring they have access to all previously acquired content.
- Call Remote.GetClientEntitlements to retrieve the user's complete purchase history from Reactional's servers.
- Filter the results to include only active, non-revoked track entitlements.
- Call Remote.GetTracksMetadata to fetch detailed track information in batches, this approach (20 tracks per request) ensures reliable performance even with large music libraries.
- This would be an easy way for implementing features like "My Library" or "Purchased Tracks" sections in your application.
- The resulting track payloads can be used for playback, display, or synchronization purposes.
using Reactional.Services;
public class MusicStoreEntitlementsExample : MonoBehaviour
{
void Start()
{
List<TrackPayloads> tracks = new List<TrackPayloads>();
// Get client purchases
var entitlements = await Reactional.Services.Remote.GetClientEntitlements();
var trackIds = entitlements.Where(e => !e.revoked && string.Equals(e.itemType, "track"))
.Select(e => e.itemId)
.Where(id => !string.IsNullOrWhiteSpace(id))
.Distinct()
.ToArray();
// Fetch TrackPayloads in batches to avoid long query strings
const int batchSize = 20;
for (int i = 0; i < trackIds.Length; i += batchSize)
{
var batch = trackIds.Skip(i).Take(batchSize).ToArray();
var payloads = await Reactional.Services.Remote.GetTracksMetadata(batch); // When not providing a users countryCode only tracks with worldwide access will be recieved
foreach (var t in payloads) { tracks.Add(t); }
}
// Use track payloads
}
}