name: ugs-integration-patterns
description: Unity Gaming Services integration patterns, service abstraction, and UGS API usage. Use when integrating UGS services, implementing authentication, Cloud Save, or multiplayer features.
UGS Integration Patterns
Service Interface Pattern
Define Interface
// Systems/IAuthenticationService.cs
public interface IAuthenticationService
{
bool IsLoggedIn { get; }
string PlayerId { get; }
UniTask LoginAsync();
UniTask LogoutAsync();
}
Implement Service
// Systems/AuthenticationServices.cs
public class UnityAuthenticationService : IAuthenticationService
{
public bool IsLoggedIn => AuthenticationService.Instance.IsSignedIn;
public string PlayerId => AuthenticationService.Instance.PlayerId;
public async UniTask LoginAsync()
{
await AuthenticationService.Instance.SignInAnonymouslyAsync();
}
public async UniTask LogoutAsync()
{
await AuthenticationService.Instance.SignOutAsync();
}
}
Register Service
// Boot/GameInitializer.cs
ServiceLocator.Global.Register<IAuthenticationService>(
new UnityAuthenticationService()
);
Use Service
var authService = ServiceLocator.Global.Get<IAuthenticationService>();
if (!authService.IsLoggedIn)
{
await authService.LoginAsync();
}
Cloud Save Pattern
Save Data
public async UniTask SavePlayerDataAsync(PlayerData data)
{
try
{
var saveData = new Dictionary<string, object>
{
{ "PLAYER_DATA", data }
};
await CloudSaveService.Instance.Data.Player.SaveAsync(saveData);
Debug.Log("[DataManager] Player data saved");
}
catch (Exception e)
{
Debug.LogError($"[DataManager] Save failed: {e.Message}");
}
}
Load Data
public async UniTask<PlayerData> LoadPlayerDataAsync()
{
try
{
var keys = new HashSet<string> { "PLAYER_DATA" };
var data = await CloudSaveService.Instance.Data.Player.LoadAsync(keys);
if (data.TryGetValue("PLAYER_DATA", out var item))
{
return item.Value.GetAs<PlayerData>();
}
return new PlayerData(); // Default
}
catch (Exception e)
{
Debug.LogError($"[DataManager] Load failed: {e.Message}");
return new PlayerData();
}
}
Multiplayer Sessions Pattern
Create Session
public async UniTask<string> CreateSessionAsync(int maxPlayers)
{
try
{
var sessionRequest = new SessionRequest
{
MaxPlayers = maxPlayers
};
var session = await MultiplayerService.Instance.CreateSessionAsync(sessionRequest);
return session.SessionId;
}
catch (Exception e)
{
Debug.LogError($"[SessionManager] Create session failed: {e.Message}");
throw;
}
}
Join Session
public async UniTask JoinSessionAsync(string sessionId)
{
try
{
await MultiplayerService.Instance.JoinSessionAsync(sessionId);
Debug.Log($"[SessionManager] Joined session: {sessionId}");
}
catch (Exception e)
{
Debug.LogError($"[SessionManager] Join failed: {e.Message}");
throw;
}
}
Lobby Pattern
Create Lobby
public async UniTask<string> CreateLobbyAsync(int maxPlayers)
{
try
{
var lobbyRequest = new CreateLobbyRequest
{
MaxPlayers = maxPlayers,
IsPrivate = false
};
var lobby = await LobbyService.Instance.CreateLobbyAsync(lobbyRequest);
return lobby.LobbyCode;
}
catch (Exception e)
{
Debug.LogError($"[LobbyManager] Create lobby failed: {e.Message}");
throw;
}
}
Join Lobby by Code
public async UniTask JoinLobbyByCodeAsync(string code)
{
try
{
var joinRequest = new JoinLobbyByCodeRequest { LobbyCode = code };
var lobby = await LobbyService.Instance.JoinLobbyByCodeAsync(joinRequest);
Debug.Log($"[LobbyManager] Joined lobby: {lobby.LobbyId}");
}
catch (Exception e)
{
Debug.LogError($"[LobbyManager] Join failed: {e.Message}");
throw;
}
}
Friends Service Pattern
Get Friends List
public async UniTask<List<Friend>> GetFriendsAsync()
{
try
{
var friends = await FriendsService.Instance.GetFriendsAsync();
return friends.ToList();
}
catch (Exception e)
{
Debug.LogError($"[FriendsManager] Get friends failed: {e.Message}");
return new List<Friend>();
}
}
Send Friend Request
public async UniTask SendFriendRequestAsync(string playerId)
{
try
{
var request = new SendFriendRequestRequest { PlayerId = playerId };
await FriendsService.Instance.SendFriendRequestAsync(request);
Debug.Log($"[FriendsManager] Friend request sent to {playerId}");
}
catch (Exception e)
{
Debug.LogError($"[FriendsManager] Send request failed: {e.Message}");
}
}
Error Handling Pattern
Standard Error Handling
public async UniTask<T> ExecuteUGSCallAsync<T>(Func<UniTask<T>> operation, T defaultValue)
{
try
{
return await operation();
}
catch (RequestFailedException e)
{
Debug.LogError($"[ServiceName] UGS request failed: {e.Message}");
Debug.LogError($"Error Code: {e.ErrorCode}, Status: {e.HttpStatusCode}");
return defaultValue;
}
catch (Exception e)
{
Debug.LogError($"[ServiceName] Unexpected error: {e.Message}");
return defaultValue;
}
}
Initialization Pattern
Service Initialization
public async UniTask InitializeAsync()
{
try
{
if (UnityServices.State == ServicesInitializationState.Uninitialized)
{
await UnityServices.InitializeAsync();
}
// Initialize services
await InitializeAuthenticationAsync();
await InitializeCloudSaveAsync();
// ...
Debug.Log("[GamingServices] All services initialized");
}
catch (Exception e)
{
Debug.LogError($"[GamingServices] Initialization failed: {e.Message}");
throw;
}
}
Platform-Specific Patterns
Android - Google Play Games
#if UNITY_ANDROID && !UNITY_EDITOR
public class GPGSAuthenticationService : IAuthenticationService
{
public async UniTask LoginAsync()
{
await AuthenticationService.Instance.SignInWithGooglePlayGamesAsync();
}
}
#endif
Default - Anonymous
public class UnityAuthenticationService : IAuthenticationService
{
public async UniTask LoginAsync()
{
await AuthenticationService.Instance.SignInAnonymouslyAsync();
}
}
Service Availability Pattern
Check Before Use
public async UniTask SaveDataAsync()
{
if (_gamingServices?.CloudSave == null)
{
Debug.LogWarning("[DataManager] CloudSave not available");
return;
}
try
{
await _gamingServices.CloudSave.Data.Player.SaveAsync(data);
}
catch (Exception e)
{
Debug.LogError($"[DataManager] Save failed: {e.Message}");
}
}