Use the AGS Game SDK to log in - Login with device ID - (Unity module)
Unwrap the Wrapper
In this tutorial, you will learn how to implement AccelByte Gaming Services (AGS) using the AGS Software Development Kit (SDK) to log in with a device ID.
In Byte Wars, there is a game instance wrapper defined in the AuthEssentialsWrapper
class. This wrapper is used to send login requests to AGS. For this tutorial, you will use the AuthEssentialsWrapper_Starter
wrapper, which is a starter version of the AuthEssentialsWrapper
class, to implement the feature from scratch.
What's in the Starter Pack
To follow this tutorial, you will use the starter wrapper class called AuthEssentialsWrapper_Starter
. This wrapper is defined in the following file:
- C# file:
Assets/Resources/Modules/AuthEssentials/Scripts/AuthEssentialsWrapper_Starter.cs
The AuthEssentialsWrapper_Starter
class includes several pre-defined components:
Helper variables to reference the AGS SDK interfaces. These variables are assigned when the wrapper is initialized:
private User user;
private UserProfiles userProfiles;
private Lobby lobby;
private void Start()
{
user = AccelByteSDK.GetClientRegistry().GetApi().GetUser();
userProfiles = AccelByteSDK.GetClientRegistry().GetApi().GetUserProfiles();
lobby = AccelByteSDK.GetClientRegistry().GetApi().GetLobby();
}A variable to hold an optional parameter that will be used when calling the login function. This is useful if you plan to integrate a login queue later on, but it can still be used even if you're not. Simply leave the parameter unset:
// Optional Parameters
public LoginV4OptionalParameters OptionalParameters = new();
Implement Login Using the AGS Game SDK
Open the
AuthEssentialsWrapper_Starter
class and create a new function to send a login request using the device ID. When the request is complete, it will invoke the callback function:public void LoginWithDeviceId(ResultCallback<TokenData, OAuthError> resultCallback)
{
LoginWithDeviceIdV4OptionalParameters optionalParams = new LoginWithDeviceIdV4OptionalParameters
{
OnQueueUpdatedEvent = OptionalParameters.OnQueueUpdatedEvent,
OnCancelledEvent = OptionalParameters.OnCancelledEvent,
CancellationToken = OptionalParameters.CancellationToken
};
user.LoginWithDeviceIdV4(
optionalParams,
result => OnLoginCompleted(result, resultCallback));
}Create a new function to create or get the user profile if the account is new. This profile is required to complete the account setup:
private void CreateOrGetUserProfile(ResultCallback<UserProfile> resultCallback)
{
userProfiles.GetUserProfile((Result<UserProfile> getUserProfileResult) =>
{
// If not found because it is not yet created, then try to create one.
if (getUserProfileResult.IsError &&
getUserProfileResult.Error.Code == ErrorCode.UserProfileNotFoundException)
{
CreateUserProfileRequest request = new CreateUserProfileRequest()
{
language = System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
timeZone = TutorialModuleUtil.GetLocalTimeOffsetFromUTC(),
};
userProfiles.CreateUserProfile(request, resultCallback);
return;
}
resultCallback.Invoke(getUserProfileResult);
});
}Create a new function to retrieve public user data, such as user ID, display name, and avatar URL:
private void GetUserPublicData(string userId, ResultCallback<AccountUserPlatformInfosResponse> resultCallback)
{
user.GetUserOtherPlatformBasicPublicInfo("ACCELBYTE", new string[] { userId }, resultCallback);
}Next, create the callback function to handle the login result. If the login is successful, it performs several actions: connects to the AGS lobby, retrieves or creates the user profile, and fetches the public user data to be cached locally:
private void OnLoginCompleted(
Result<TokenData, OAuthError> loginResult,
ResultCallback<TokenData, OAuthError> resultCallback = null)
{
// Abort if login failed.
if (loginResult.IsError)
{
BytewarsLogger.Log($"Failed to login. Error: {loginResult.Error.error}");
resultCallback?.Invoke(loginResult);
return;
}
// Connect to the lobby if not already connected.
if (!lobby.IsConnected)
{
lobby.Connect();
}
// Get user profile.
TokenData tokenData = loginResult.Value;
BytewarsLogger.Log("Login successful. Retrieving user profile and info.");
CreateOrGetUserProfile((Result<UserProfile> userProfileResult) =>
{
// Abort if failed to retrieve or create user profile.
if (userProfileResult.IsError)
{
BytewarsLogger.LogWarning($"Failed to retrieve or create user profile. Error: {userProfileResult.Error.Message}");
resultCallback?.Invoke(Result<TokenData, OAuthError>.CreateError(new OAuthError() { error = userProfileResult.Error.Message }));
return;
}
// Get public user info.
GetUserPublicData(tokenData.user_id, (Result<AccountUserPlatformInfosResponse> userInfoResult) =>
{
// Abort if failed to get user info.
if (userInfoResult.IsError || userInfoResult.Value.Data.Length <= 0)
{
BytewarsLogger.LogWarning($"Failed to retrieve user info. Error: {userInfoResult.Error.Message}");
resultCallback?.Invoke(Result<TokenData, OAuthError>.CreateError(new OAuthError() { error = userInfoResult.Error.Message }));
return;
}
// Cache the public user info in the game.
AccountUserPlatformData publicUserData = userInfoResult.Value.Data[0];
GameData.CachedPlayerState.PlayerId = publicUserData.UserId;
GameData.CachedPlayerState.AvatarUrl = publicUserData.AvatarUrl;
GameData.CachedPlayerState.PlayerName =
string.IsNullOrEmpty(publicUserData.DisplayName) ?
$"Player-{publicUserData.UserId[..5]}" :
publicUserData.DisplayName;
GameData.CachedPlayerState.PlatformId =
string.IsNullOrEmpty(GameData.CachedPlayerState.PlatformId) ?
tokenData.platform_id : GameData.CachedPlayerState.PlatformId;
resultCallback.Invoke(loginResult);
});
});
}Now, create a function to send a logout request:
public void Logout(Action action)
{
user.Logout(result => OnLogoutComplete(result, action));
}Finally, create the callback function to handle the logout result:
private void OnLogoutComplete(Result result, Action callback)
{
if (!result.IsError)
{
BytewarsLogger.Log("Logout successful");
callback?.Invoke();
}
else
{
BytewarsLogger.Log($"Logout failed. Error message: {result.Error.Message}");
}
}
Resources
The files used in this tutorial are available in the Unity Byte Wars GitHub repository.