Skip to main content

Use the AGS Game SDK to log in - Login with device ID - (Unity module)

Last updated on June 23, 2025

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

  1. 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));
    }
  2. 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);
    });
    }
  3. 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);
    }
  4. 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);
    });
    });
    }
  5. Now, create a function to send a logout request:

    public void Logout(Action action)
    {
    user.Logout(result => OnLogoutComplete(result, action));
    }
  6. 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