Integrate with other Unity services
Integrate Cloud Code with various Unity Gaming Services using C# Software Development Kits or REST APIs.
Read time 6 minutesLast updated 5 days ago
To unlock the full potential of Cloud Code, you can seamlessly integrate it with various Unity Gaming Services using either the C# Service SDKs or REST APIs.
The C# SDKs offer a simpler and more consistent experience, providing convenient access to Unity Gaming Services. If the Unity Gaming Service you wish to utilize already has a Cloud Code C# SDK, you can take advantage of it for a smoother integration. However, in cases where a specific UGS service lacks a Cloud Code C# SDK, you have the flexibility to connect with it directly through its REST API.
For some services where the state doesn't change frequently, such as Remote Config, it can be beneficial to introduce an in-memory cache to reduce the number of HTTP requests. For more information, refer to In-memory cache.
Connect to UGS through the UGS SDKs
To access the Cloud Code C# services SDK from NuGet, search for Com.Unity.Services.CloudCode.Apis. Once you install the package, you can use it within your C# modules to simplify the way you connect with other Unity services.
For a full list of Cloud Code C# SDKs, refer to the Available Libraries page.
API Clients
The and classes are both wrappers around the Cloud Code C# SDKs, providing simplified interfaces for calling Unity Gaming Services (UGS) from Cloud Code modules. However, they serve different purposes and are designed for distinct use cases.
GameApiClientAdminApiClientUse the GameApiClient
class
GameApiClientThe class is specifically tailored for interacting with standard gaming services provided by UGS. It simplifies the process of calling UGS services from Cloud Code modules, such as reading and writing data in Cloud Save. You can use the class to access either Player Data, which is associated with an individual player, or Game Data, which is associated with the game as a whole and isn't tied to any one player. The examples below demonstrate both cases.
GameApiClientTo use the interface, register it as a singleton in your configurator:
IGameApiClientICloudCodeSetupusing Unity.Services.CloudCode.Apis.Extensions;using Unity.Services.CloudCode.Core;public class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.AddGameApiClient(); }}
Save and retrieve Player Data
You can use the interface in any function that you attribute with .
To use the interface, pass it as a parameter to the function.
IGameApiClientCloudCodeFunctionIGameApiClientThe following example demonstrates how to save and read Player Data from Cloud Save. Player Data is tied to and authenticated with :
context.PlayerIdcontext.AccessTokenusing System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Apis;using Unity.Services.CloudCode.Apis.Extensions;using Unity.Services.CloudCode.Core;using Unity.Services.CloudCode.Shared;using Unity.Services.CloudSave.Model;namespace ExampleModule;public class CloudSaveSdkSample{ private readonly ILogger<CloudSaveSdkSample> _logger; public CloudSaveSdkSample(ILogger<CloudSaveSdkSample> logger) { _logger = logger; } [CloudCodeFunction("SavePlayerData")] public async Task SavePlayerData(IExecutionContext context, IGameApiClient gameApiClient, string key, string value) { try { await gameApiClient.CloudSaveData.SetItemAsync( context, context.AccessToken!, context.ProjectId!, context.PlayerId!, new SetItemBody(key, value)); _logger.LogInformation("Successfully saved data for key: {Key}", key); } catch (ApiException ex) { _logger.LogError("Failed to save data for key {Key}. Error: {Error}", key, ex.Message); throw new Exception($"Unable to save player data: {ex.Message}"); } } [CloudCodeFunction("GetPlayerData")] public async Task<string> GetPlayerData(IExecutionContext context, IGameApiClient gameApiClient, string key) { try { var result = await gameApiClient.CloudSaveData.GetItemsAsync( context, context.AccessToken!, context.ProjectId!, context.PlayerId!, new List<string> { key }); var data = result.Data.Results.FirstOrDefault()?.Value?.ToString() ?? string.Empty; _logger.LogInformation("Successfully retrieved data for key: {Key}", key); return data; } catch (ApiException ex) { _logger.LogError("Failed to retrieve data for key {Key}. Error: {Error}", key, ex.Message); throw new Exception($"Unable to retrieve player data: {ex.Message}"); } }}public class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.AddGameApiClient(); }}
Save and retrieve Game Data
The following example demonstrates how to save and read Game Data from Cloud Save. Unlike Player Data, Game Data isn't tied to . Instead, you provide your own identifier () for the non-player entity you want to associate the data with, such as a guild or a piece of global game state, and authenticate with instead of . For more information on Game Data, refer to Cloud Save Game Data. For more information on when to use the , refer to Service and access token support.
context.PlayerIdcustomIdcontext.ServiceTokencontext.AccessTokenServiceTokenusing System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Apis;using Unity.Services.CloudCode.Apis.Extensions;using Unity.Services.CloudCode.Core;using Unity.Services.CloudCode.Shared;using Unity.Services.CloudSave.Model;namespace ExampleModule;public class CloudSaveGameDataSample{ private readonly ILogger<CloudSaveGameDataSample> _logger; public CloudSaveGameDataSample(ILogger<CloudSaveGameDataSample> logger) { _logger = logger; } [CloudCodeFunction("SaveGameData")] public async Task SaveGameData(IExecutionContext context, IGameApiClient gameApiClient, string customId, string key, string value) { try { await gameApiClient.CloudSaveData.SetCustomItemAsync( context, context.ServiceToken, context.ProjectId!, customId, new SetItemBody(key, value)); _logger.LogInformation("Successfully saved game data for key: {Key}", key); } catch (ApiException ex) { _logger.LogError("Failed to save game data for key {Key}. Error: {Error}", key, ex.Message); throw new Exception($"Unable to save game data: {ex.Message}"); } } [CloudCodeFunction("GetGameData")] public async Task<string> GetGameData(IExecutionContext context, IGameApiClient gameApiClient, string customId, string key) { try { var result = await gameApiClient.CloudSaveData.GetCustomItemsAsync( context, context.ServiceToken, context.ProjectId!, customId, new List<string> { key }); var data = result.Data.Results.FirstOrDefault()?.Value?.ToString() ?? string.Empty; _logger.LogInformation("Successfully retrieved game data for key: {Key}", key); return data; } catch (ApiException ex) { _logger.LogError("Failed to retrieve game data for key {Key}. Error: {Error}", key, ex.Message); throw new Exception($"Unable to retrieve game data: {ex.Message}"); } }}public class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.AddGameApiClient(); }}
For an example of these functions called from a Unity client, including saving and then loading the data, refer to Save and load data.
Use the AdminApiClient
class
AdminApiClientThe class is intended for accessing administrative functionalities of UGS services. It provides a simplified interface for calling UGS admin-related services from Cloud Code modules. The example illustrates how to create a leaderboard using the AdminApiClient, showcasing its utility for administrative tasks.
AdminApiClientTo use the interface, register it as a singleton in your configurator:
IAdminApiClientICloudCodeSetupusing Unity.Services.CloudCode.Apis.Extensions;using Unity.Services.CloudCode.Core;public class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.AddAdminApiClient(); }}
Usage Example
Similar to the , the interface can be employed in any function attributed with . When using the interface, pass it as a parameter to the function.
IGameApiClientIAdminApiClientCloudCodeFunctionIAdminApiClientThe following example demonstrates how to create a Leaderboard:
using System;using System.Threading.Tasks;using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Apis;using Unity.Services.CloudCode.Apis.Admin;using Unity.Services.CloudCode.Apis.Extensions;using Unity.Services.CloudCode.Core;using Unity.Services.CloudCode.Shared;using Unity.Services.Leaderboards.Admin.Model;namespace ExampleModule;public class ModuleMain{ private static ILogger<ModuleMain> _logger; public ModuleMain(ILogger<ModuleMain> logger) { _logger = logger; } [CloudCodeFunction("CreateLeaderboard")] public async Task CreateLeaderboard(IExecutionContext context, IAdminApiClient adminApiClient) { try { await adminApiClient.Leaderboards.CreateLeaderboardAsync( executionContext: context, serviceAccountKey: "YOUR_SERVICE_ACCOUNT_KEY", serviceAccountSecret: "YOUR_SERVICE_ACCOUNT_SECRET", projectId: Guid.Parse(context.ProjectId), environmentId: Guid.Parse(context.EnvironmentId), leaderboardIdConfig: new LeaderboardIdConfig( id: "new-leaderboard", name: "new-leaderboard", sortOrder: SortOrder.Asc, updateType: UpdateType.KeepBest ) ); } catch (ApiException ex) { _logger.LogError("Failed to create a Leaderboard. Error: {Error}", ex.Message); throw new Exception($"Failed to create a Leaderboard. Error: {ex.Message}"); } } public class ModuleConfig : ICloudCodeSetup { public void Setup(ICloudCodeConfig config) { config.AddAdminApiClient(); } }}
Connect to UGS through REST APIs
If you want to use a service that doesn't have a C# SDK yet, you can also connect with the services directly through their REST API.
Authentication
Depending on your use case, you can use either the or the to authenticate the API call.
If you use the to authenticate UGS Client APIs, ensure the service you want to call supports service tokens. For a list of services and use cases that support service tokens, refer to the Service and access token support documentation.
AccessTokenServiceTokenServiceTokenCalling the API
Dependency Injection allows you to create API interfaces as singletons and inject them into your modules.