Use the SDK to set and query stats - Stat tracking and display - (Unity module)
Unwrap the Wrapper
In this tutorial, you will learn how to implement statistics (stats) using the AccelByte Gaming Services (AGS) Game SDK.
Byte Wars uses a wrapper class named StatsEssentialsWrapper
that acts as the wrapper to cache and handle stats-related functionalities when using the AGS Game SDK. This way, it provides modularity without overriding engine classes.
The StatsEssentialsWrapper
class uses the ApiClient
, Statistic
, and ServerStatistic
classes provided by the AGS Game SDK. These classes interact with the AGS Statistics service to update and query the statistics value.
What's in the Starter Pack
Just as in the UI tutorial of this module, a StatsEssentialsWrapper_Starter
class has been provided for you with the starter code. This file is available in the Resources section and consists of the following file:
StatsEssentialsWrapper_Starter.cs: /Assets/Resources/Modules/StatsEssentials/Scripts/StatsEssentialsWrapper_Starter.cs
The file contains some functionalities for you already:
Namespaces declarations for using the
Statistic
andServerStatistic
classes from the AGS Game SDK.using AccelByte.Api;
using AccelByte.Core;
using AccelByte.Models;
using AccelByte.Server;Local variables that hold the references to the
Statistic
andServerStatistic
classes.private Statistic statistic;
private ServerStatistic serverStatistic;
Integrate Statistics service
This section will guide you through implementing the AGS Statistics service using the AGS Game SDK.
Integrate into client side
Open Byte Wars in Unity.
Open
StatsEssentialsWrapper_Starter.cs
. In theStart()
function, initialize thestatistic
variable to get theStatistic
object of the clientApiClient
.void Start()
{
var apiClient = AccelByteSDK.GetClientRegistry().GetApi();
statistic = apiClient.GetStatistic();
}Implement the function to update a statistic value. Since the process is asynchronous, create a callback function that will inform the user regarding the result. You add the AGS Game SDK
Result
andResultCallback
as parameters so the result will be accessible from other scripts.private void OnUpdateUserStatsFromClientCompleted(Result<UpdateUserStatItemValueResponse> result, ResultCallback<UpdateUserStatItemValueResponse> customCallback = null)
{
if (!result.IsError)
{
Debug.Log("Update user's statistics value from client successful.");
}
else
{
Debug.Log($"Update user's statistics value from client failed. Message: {result.Error.Message}");
}
customCallback?.Invoke(result);
}Create a new function called
UpdateUserStatsFromClient
that takesstatCode
,statValue
,additionalKey
, andResultCallback
as parameters. To use theUpdateUserStatItemsValue
function from the AGS Game SDK, you need to create aPublicUpdateUserStatItem
object that defines the update strategy and hold the statistics value. Since you are setting the statistics value exactly to what you want, you will use theOVERRIDE
forupdateStrategy
.public void UpdateUserStatsFromClient(string statCode, float statValue, string additionalKey, ResultCallback<UpdateUserStatItemValueResponse> resultCallback = null)
{
PublicUpdateUserStatItem userStatItem = new PublicUpdateUserStatItem
{
updateStrategy = StatisticUpdateStrategy.OVERRIDE,
value = statValue
};
statistic.UpdateUserStatItemsValue(
statCode,
additionalKey,
userStatItem,
result => OnUpdateUserStatsFromClientCompleted(result, resultCallback)
);
}Create the function to query statistics values. Create another callback function in
StatsEssentialsWrapper_Starter
class that will inform the user of the query result. Similar to before, you add the AGS Game SDKResult
andResultCallback
as the parameters.private void OnGetUserStatsFromClientCompleted(Result<PagedStatItems> result, ResultCallback<PagedStatItems> customCallback = null)
{
if (!result.IsError)
{
Debug.Log("Query user's statistics value from client successful.");
}
else
{
Debug.Log($"Query user's statistics value from client failed. Message: {result.Error.Message}");
}
customCallback?.Invoke(result);
}Create a new function called
GetUserStatsFromClient
that calls theGetUserStatItems()
function from theStatistic
class from the AGS Game SDK. You can get all statistic values of the player at once by providing an array of targetedstatCodes
, an array oftags
as a filter, and aResultCallback
to the function.public void GetUserStatsFromClient(string[] statCodes, string[] tags, ResultCallback<PagedStatItems> resultCallback)
{
statistic.GetUserStatItems(
statCodes,
tags,
result => OnGetUserStatsFromClientCompleted(result, resultCallback)
);
}
Integrate into server side
Open Byte Wars in Unity.
Open
StatsEssentialsWrapper_Starter.cs
. In theStart()
function, initialize theserverStatistic
variable to get theStatistic
class from the serverApiClient
.void Start()
{
var apiServer = AccelByteSDK.GetServerRegistry().GetApi();
var serverStatistic = apiServer.GetStatistic();
}Implement the function for updating the statistic values for many users. Since the process is asynchronous, create a callback function that will inform the user regarding the result. Add the AGS Game SDK
Result
andResultCallback
as parameters so the result will be accessible from other scripts.private void OnUpdateManyUserStatsFromServerCompleted(Result<StatItemOperationResult[]> result, ResultCallback<StatItemOperationResult[]> customCallback = null)
{
if (!result.IsError)
{
Debug.Log("Update user's statistics value from server successful.");
}
else
{
Debug.Log($"Update user's statistics value from server failed. Message: {result.Error.Message}");
}
customCallback?.Invoke(result);
}Create a new function to call the
UpdateManyUsersStatItems()
function in theServerStatistic
class, with the target stat code, dictionary of target players'userId
, and the corresponding target value stored instatValue
. You also haveResultCallback
as parameters so the result will be accessible from other scripts. Inside the function, you will process theStatItems
dictionary into a list ofStatItemUpdate
objects with theOVERRIDE
update strategy.public void UpdateManyUserStatsFromServer(string statCode, Dictionary<string, float> newStatItemsValue, ResultCallback<StatItemOperationResult[]> resultCallback)
{
List<UserStatItemUpdate> bulkUpdateUserStatItems = new List<UserStatItemUpdate>();
foreach (var newStatItem in newStatItemsValue)
{
UserStatItemUpdate userStatItem = new UserStatItemUpdate()
{
updateStrategy = StatisticUpdateStrategy.OVERRIDE,
statCode = statCode,
userId = newStatItem.Key,
value = newStatItem.Value
};
bulkUpdateUserStatItems.Add(userStatItem);
}
serverStatistic.UpdateManyUsersStatItems(
bulkUpdateUserStatItems.ToArray(),
result => OnUpdateManyUserStatsFromServerCompleted(result, resultCallback)
);
}infoA game server can update multiple statistic values of a specific player as long as the server knows the player's user ID.
Create the function for querying statistic values. Create another callback function in
StatsEssentialsWrapper_Starter
that will inform the user of the query result. Similar to before, you add the AGS Game SDKResult
andResultCallback
as parameters.private void OnGetUserStatItemsFromServerCompleted(Result<FetchUserStatistic> result, ResultCallback<FetchUserStatistic> customCallback = null)
{
if (!result.IsError)
{
Debug.Log("Query user's statistics value from server successful.");
}
else
{
Debug.Log($"Query user's statistics value from server failed. Message: {result.Error.Message}");
}
customCallback?.Invoke(result);
}Create another function that will call the
BulkFetchStatItemsValue()
function in theServerStatistic
class with an array of target players'userId
, the target statistics value'sstatCode
, andResultCallback
as parameters. Similar to theUpdateUserStatItems()
function in theServerStatistic
class, game servers can also query multiple statistic values of a specific player at once.public void BulkGetUsersStatFromServer(string[] userIds, string statCode, ResultCallback<FetchUserStatistic> resultCallback)
{
serverStatistic.BulkFetchStatItemsValue(
statCode,
userIds,
result => OnGetUserStatItemsFromServerCompleted(result, resultCallback)
);
}
Resources
- GitHub link to the file in the Unity Byte Wars repository: