To help you get started learning about our services and their implementation, you can download Light Fantastic. Light Fantastic is our sample game which shows off a wide range of AccelByte services. By looking at our sample game and this guide, you’ll be able to see how our services can be implemented in your own game.
Modify GAME_VERSION (and DS_TARGET_VERSION) in Assets\Scripts\AccelByte\LightFantasticConfig.cs. If there are no changes in the gameplay and server version, DS_TARGET VERSION doesn't have to be updated.
In the Unity Editor, open the File menu and select BuildSettings. Select PC, Mac & Linux Standalone as the platform, then select your architecture from the dropdown list. Ensure that Server Build is cleared and that Development Build is selected.
Ensure the Assets/Resources/AccelByteServerSDKConfig.json fields are all correct, especially the ClientId and ClientSecret.
In the Unity Editor, open the File menu and select BuildSettings. Select PC, Mac & Linux Standalone as the platform, then choose Linux from the Target Platform dropdown list. Ensure that Server Build is selected.
In the Unity Editor, open the File menu and select BuildSettings. Select PC, Mac & Linux Standalone as the platform, then choose Windows from the Target Platform dropdown list. Ensure that Server Build is selected.
To run the server, add the parameter localds when running the executable.
In Light Fantastic, you can create a player account to play the game. As a developer you can work with accounts in several ways, including assigning different accounts different roles and permissions.
Our User Account Management service includes many ways of authenticating a user, such as headless auth via unique identifiers, or login with third parties such asSteam, Epic, Xbox, or Playstation.
In this guide, we’ll focus on the conventional email registration, verification, and authentication method.
One helpful feature of the AccelByte SDK is that it manages its own Unity GameObject instance. As such, you don’t need to create an empty GameObject to manage AccelByte services. When you call an AccelByte value or function, the SDK will create and manage itself in the active scene:
Here’s what happens when a player opens our game:
public class AccelByteAuthenticationLogic : MonoBehaviour
The first thing we do is initialize our plugin in the scene, using the GetUser function. This will retrieve an empty user object, which we can then log into to input the necessary data. However, before we log a user in we must first register that user.
Registration requires just two functions. First is the registration code:
public void Register()
System.DateTime dob = new System.DateTime(int.Parse(UIHandlerAuthComponent.registerDobYear.text),
This code is hooked up to a few input fields and dropdown menus. First, we convert the date of birth text fields to System.DateTime format. Then, we call the User.Register function, which sends the player’s information to the server. By default, to register a player we need:
A valid email address
The player’s desired password
The player’s desired display name
Their current region in ISO 3166–1 alpha-2 format
Their date of birth in DateTime format
Callback to receive the data
The user registration form in Light Fantastic looks like this:
Our Register() function is tied to the Register button’s OnClick EventListener. When the event is fired, it sends the registration data to the server and the server sends back a response. We need a callback to interpret the data sent back from the server, as seen below:
Our registration callback takes one generic class of Result which we populate with various other member classes depending on the task at hand. In this case, the result will be populated with UserData. If there are any errors in the user data, information about the error is displayed for the player. Several errors are possible, such as their email address already being registered or one of the fields containing invalid characters. If the request was successful, the registration flow continues. By default, all new players must verify their email address to complete registration. Newly registered players will receive the email seen below:
Before we can call our Verify() function we must log our player in so they are authorized to make more calls against the service. You can see in our Register code that if a login is successful, we take the username and password from the registration UI fields and make a LoginWithUsername call.
We use the abUserData object to store and reference the relevant UserData that the server sends back. In this case, we display a UserId and SessionId and then check that the player has verified their email. If they have, we send them to the Main Menu of the game; if not we send them to the Verification panel:
To verify we simply copy the verification code from the email we received into the box and click Verify, which is hooked to our Verify() function via the button’s OnClick EventListener. There are two verification functions: the event that sends the code to the server, and an event that requests a new code be emailed to a player:
We check for errors, and if there are none, progress the player to our main menu where we have finished the registration process. Next time the player logs in, we’ll take their entered email and password from the UI fields, call the Login function, and send the email and password to the server.
public void Login()
ShowErrorMessage(true, "Please fill your email address and password");
ShowErrorMessage(true, "Please fill your email address");
else if (string.IsNullOrEmpty(UIHandlerAuthComponent.loginPassword.text))
ShowErrorMessage(true, "Please fill your password");
AccelByte offers a full suite of Social features to help you build community between players of your game, including Friends, Groups, Chat, Notifications, and more. You can see how our Friends service works in Light Fantastic.
We use Websocket to run our social services, which allows us to send and receive messages along an established connection with a lot less overhead than a standard REST request. Websocket also allows for asynchronous communication, which is what allows features like chat and notifications to work.
// TODO: use coroutine to day the call to avoid spam
Debug.LogWarning("Not Connected To Lobby. Attempting to Connect...");
First thing we do is initialize our Lobby with the AccelBytePlugin.GetLobby function. This is the object we’ll use to manage our lobby connection, which we need for friends to work.
Next is our ConnectToLobby function, which handles the initial websocket connection. If this connection fails Social services will be unavailable, so upon failure we’ll try to reconnect until a connection is established. In production, it would be best to put the retry on a timer so that the service isn’t hit with too many requests.
Once we’re connected,the friends list inside AccelByteFriendsLogic.cs will load.
for (int i = 0; i < result.Value.friendsId.Length; i++)
friendList.Add(result.Value.friendsId[i], new FriendData(result.Value.friendsId[i], "Loading...", new DateTime(2000, 12, 30), "0"));
lastFriendUserId = result.Value.friendsId[i];
isLoadFriendDisplayName = true;
LoadFriendsList returns an array of Friend IDs, which is all the game’s code needs, but it’s helpful for players to show their friends’ usernames as well. For each friendId we receive, we can get their info using GetUserByUserId.
public void GetFriendInfo(string friendId, ResultCallback<UserData> callback)
For every friend we have in our FriendStatus array we do the following:
Calculate the days since they were last seen
Instantiate a prefab friend tile gameobject (see above)
Set the parent of that friend tile to scroll view
If the days since the friend was last seen is 0, then the hours and minutes will also be checked. If all values are 0, the friend is shown as Online. If the days, hours, or minutes since they were last seen is greater than 0, the amount of time since they’ve been online will be displayed.
For this we instantiate a prefab of our friend tile, to which the FriendPrefab script is assigned.
We store the userId for later use with Chat, Party, or Matchmaking services. We also store the username, isonline and last seen values to display to the player.
Lastly, the SetupFriendUI function assigns the string values passed in from the ListFriendsStatus response to the actual Unity UI components.
With this our friends list is displayed! Now that we can display our friends list, we need to be able to invite other players to be our friend.
First, we need to clean up the previous instance of our friends list. This involves deleting all Child UI objects in our ScrollContent.
Then we check for errors, if none are found we instantiate a prefab search result UI tile as a child of the Search UI’s ScrollContent object. Similar to our friend UI tile, the search result is populated with a Display Name and UserId.
The script on the search result is a little different however, as the search result object is responsible for sending the friend request:
Here’s what the script looks like:
public class SearchFriendPrefab : MonoBehaviour
private Text usernameText;
private Button addFriendButton;
private string userId;
public void SetupFriendPrefab(string username, string id)
As you can see, it’s quite similar to the FriendPrefab in that it holds a player’s info and is responsible for updating its own UI text objects. This prefab, however, also contains a button for sending a friend request.
The AddFriend function is hooked to the button’s EventTrigger in the Unity Editor. When clicked, it triggers SendFriendRequest, which takes a userId and the callback to send the response.
The script manages its own response in the SendFriendRequestCallback function. We check for errors, and if there are none we change the button’s UI Text to say the request was sent and mark it as unclickable.
We need to clean up any existing UI Prefabs in our UI, then check for errors. For every friend in our outgoing friend requests, we instantiate an Invitation prefab, which consists of a Username and a Sent indicator.
Similar to before, each of these prefabs has its own script to manage the UI tile’s instance, since they each have some level of interaction.
Next we have Incoming Invites, where we can choose to either accept or decline a friend:
Debug.Log("AcceptFriendRequest sent successfully.");
Similar to previous Prefab scripts, we want to set up our Invitation tile, but the only identifying information we have for the players is their User ID. We need easily identifiable names to show our end users. To get these we’ll use the GetFriendInfo function, which is just GetUserByUserId by a different name.
In OnGetFriendInfoRequest we check for errors, and if there are none we update the UI text element with the player’s Display Name.
Next we have AcceptInvite and DeclineInvite and their callbacks. These are hooked up to the Unity UI button’s event trigger:
When fired, these will add the player to the friends list, or remove the invite from the pending invites list.
With that completed, our new friend afif7 is now added to our overall friends list:
For player afif7, the invited player afif1 also shows up in their friends list.
Now that we’ve enabled friends, let’s set up parties. Parties allow players to play Light Fantastic together. The main actions players can take here are Creating a Party, Inviting Players to a Party, Kicking Players from a Party, and Leaving a Party.
Debug.Log("OnPartyCreated Party successfully created with party ID: " + result.Value.partyID);
abPartyInfo = result.Value;
isReadyToInviteToParty = true;
The CreateParty function can also be implemented right after the player presses the Invite To Party button in their friend list and before calling InviteToParty function. It will check if the inviter already has a party, and if not a new party will be created.
The party leader is the only one that can invite other players to the party via their friend list. Only friends that are online can be invited to join a party. In Light Fantastic, the party slots are shown in the bottom-right corner of the main menu of the game. Empty party slots have plus signs in them, and when clicked the player can add a friend to their party.
public void InviteToParty(string id, ResultCallback callback)
The invitation arrives to the invited player through the InvitedToParty event. The PartyInvitation should be cached to a variable so it can be used with the JoinParty function in the next step. The abPartyInfo variable will be used to store information about the party that will be useful to update our UI later on.
The From value in PartyInvitation is a user ID, so we need to call GetUserData in order to get the displayname to show who the invitation is from. After the popup is shown to the player they’ll be given two options, to either Accept or Decline the invitation.
Declining the invitation closes the popup invitation by calling SetActive to false on the popup’s gameobject. Accepting the invitation will call the JoinParty function and the callback will update the player’s current party with the latest info. The UI party slot will also be updated once the partyInfo is retrieved successfully. Below you can see how to assign the AcceptPartyButton OnClick event to OnAcceptPartyClicked.
And here is what it looks like when the button is clicked.
// On joined should change the party slot with newer players info
Debug.Log("OnJoinedParty Joined party with ID: " + result.Value.partyID + result.Value.leaderID);
abPartyInfo = result.Value;
PopupManager.Instance.ShowPopupWarning("Join a Party", "You are just joined a party!", "OK");
The party slot displays all of the party members from abPartyInfo.members visually. It also records the player’s userId, display name, and email. Below are the player slots as they appear in Light Fantastic (in the bottom-right corner of the screen) and in Unity:
Of the four slots, there is one PlayerButton and three AddFriendButtons. To use the AddFriendButtons, first we must reference them with a transform array.
public class UILobbyLogicComponent : MonoBehaviour
public Transform partyMemberButtons;
Next, create a partyMemberList using the PartyData.
PopupManager.Instance.ShowPopupWarning("Kick a Party Member", "You are just kicked one of the party member!", "OK");
The kicked player will receive the KickedFromParty notification right after being kicked by the party leader. The callback of this event will be used to clear the party slot.
Register KickedFromParty as the listener:
public void SetupPartyCallbacks()
lobbyLogic.abLobby.InvitedToParty += result => OnInvitedToParty(result);
lobbyLogic.abLobby.JoinedParty += result => OnMemberJoinedParty(result);
lobbyLogic.abLobby.KickedFromParty += result => OnKickedFromParty(result);
PopupManager.Instance.ShowPopupWarning("Leave The Party", "You are just left the party!", "OK");
After the event, the remaining party members will have their PartyInfo updated just as if a member had been kicked. If the member that left was the party leader, the leadership will be transferred to the second player on the PartyInfo.members list.
In Light Fantastic, a player can start matchmaking right away for a 1v1 match or after making a party for 4 player free for all (FFA). StartMatchmaking is called to initiate the matchmaking process. The code related to matchmaking can be found in AccelByteMatchmakingLogic.cs.
Here’s what happens when the Find Match button is clicked:
rivate void FindMatchButtonClicked()
// if the player is in a party and the party leader cancel the current matchmaking
else if (result.Value.status == MatchmakingNotifStatus.cancel.ToString())
Start occurs when the party leader starts the matchmaking process, Cancel indicates that the party leader has canceled the matchmaking process, and Done occurs when the matchmaking process is finished.
ReadyForMatchConfirmation is an event that allows players to choose whether they want to join the match or not. In Light Fantastic, matches are automatically accepted when MatchmakingNotif returns Done as its status. Below is the callback for match confirmation:
A player can use cancel matchmaking by clicking on the Cancel button in the Finding Match panel. The cancel matchmaking command is stackable on the backend, so be sure that it’s only called once when the matchmaking starts. If Cancel is clicked twice, the second click will negate the next start matchmaking command.
When the matchmaking is done, all of the players will receive status updates from the Distributed Server (DS). The first status will be Creating, which indicates that the DS is being created. When the DS is ready to use a second callback will change the status from Creating to Ready. This notification will also include the IP and Port that the game client can use to connect to the DS. When the DS has accepted the players, its status will be changed to Busy.
If the players are connected to a local DS (connectToLocal), the DS status will always be Busy.
Register the callback to the DSUpdated event. Upon callback, you will need to connect the player to the DS using the IP and Port information received from DsNotif.
Registering the event:
public void SetupMatchmakingCallbacks()
lobbyLogic.abLobby.MatchmakingCompleted += result => OnFindMatchCompleted(result);
lobbyLogic.abLobby.ReadyForMatchConfirmed += result => OnGetReadyConfirmationStatus(result);
lobbyLogic.abLobby.DSUpdated += result => OnSuccessMatch(result);
Player statistics is a feature that lets players see their records in the game. In Light Fantastic, the player statistics available include the total number of wins, losses, matches, and distance traveled when playing the game.
In Light Fantastic, there are four player statistics that are set by the game server after a match is finished. These include number of wins (total-win), number of losses (total-lose), number of matches (total-match), and total distance traveled (total-distance). Because this information is managed by the game server, it can be found in AccelByteServerLogic.cs.
// class that handles all shorts of functions on UI
private UIElementHandler UIElementHandler;
public struct RankData
public string userId;
public string rank;
public string playerName;
public float winStats;
public RankData(string userId, string rank, string playerName, float winStats)
this.userId = userId;
this.rank = rank;
this.playerName = playerName;
this.winStats = winStats;
public void Init()
if (abLeaderboard == null) abLeaderboard = AccelBytePlugin.GetLeaderboard();
playerRankList = new Dictionary<string, RankData>();
Then, retrieve the top 10 ranking from the leaderboard by using QueryAllTimeLeaderboardRankingData. The parameters are the leaderboardCode that we received when we created the leaderboard, the start and end query list of players whose data we want to retrieve, and the callback.
In Light Fantastic, player entitlements appear when a player opens up their inventory from the main menu. Here, they can see the items they have and equip any of those items to their avatar. They also appear during gameplay, where player avatars are seen wearing the equipped items.
While entitlements are private information, items currently equipped by a player are saved to their UserProfile, which has public attributes. Other players can see what items the player has equipped when looking at their profile or playing in a match with them.
The entitlements logic are stored inside AccelByteEntitlementLogic.cs. To begin, retrieve the entitlement from the reference and store it in abEntitlements.
public class AccelByteEntitlementLogic : MonoBehaviour
public delegate void GetEntitlementCompletion(bool inMenum, Error error);
public event GetEntitlementCompletion OnGetEntitlementCompleted;
The GetEntitlement function includes the inMenu parameter, which indicates whether the entitlement information is needed for the player’s inventory in the main menu or in-game. The variable allItemInfo contains all of the item data available in the store and retrieved from the entitlement service. After the items’ data has been retrieved, proceed to QueryUserEntitlements.
The first parameter of QueryUserEntitlements is the entitlement name which in Light Fantastic is left empty, as it is optional. The second parameter is item ID which is also optional (and also empty here), and the third one is offset, which refers to the offset of the list that has been sliced based on the limit parameter. The value for the offset in Light Fantastic is 0. The fourth and last parameter is limit, which has a value of 99 in Light Fantastic. This means that in Light Fantastic, users can have a maximum of 99 entitlements.
The in-game callback is used to display the equipped items on the player’s avatar while they play. Like getting entitlements for the inventory, this also relies on the User Profile service to determine which entitlements are equipped.