プレイヤーとゲーム全体のグローバル統計データを追跡する
注釈:本資料はAI技術を用いて翻訳されています。
概要
この記事では、ゲームとプレイヤーのグローバル統計データを追跡するための統計設定の方法について説明します。
目標
- 統計設定の概要を提供する
- ユーザー統計データとグローバル統計データの設定方法を説明する
- AccelByte SDK を使用した統計データの使用方法(複数更新機能の活用方法を含む)を説明する
前提条件
以下へのアクセスが必要です:
- AccelByte 管理者ポータル
- AccelByte Unreal または Unity SDK
- 参考用の AccelByte 統計データ API ドキュメント
ユーザーおよびグローバル統計設定の作成
ゲームにとって、ユーザーの進行状況を一貫して追跡するための永続的な統計追跡機能を持つことは非常に重要です。
管理者ポータルで統計設定を作成するには、以下の手順に従ってください:
-
管理者ポータルのサイドバーで、Progression & Inventory > Statistics > Configurations に移動します。
-
Statistic Configuration ページで、Add Configuration ボタンをクリックします。Add New Configuration フォームが表示されます。

-
必要な情報を入力します:
-
許可された形式を使用して Stat Code を入力し、将来的に統計データを識別しやすくするために統計データの Name も入力します。作成した統計データに関する追加情報を提供するために、オプションの Description を入力することもできます。
-
サーバー側の追加検証のために、オプションの Min. Value と Max. Value を入力して、ユーザーが許可された数値を超えないようにします。また、各ユーザーの統計データの開始番号または値を決定するために、必須の Default Value を追加する必要があります。
-
-
統計機能を完全に活用するために設定できる追加の設定もあります。以下のフォームを参照してください。

-
Increment を true に設定することで、統計値が減少しないようにすることができます。この機能は、ユーザーが特定のゲームメカニクスを自分の利益のために利用しないようにするための追加のサーバー側検証を提供します。
-
すべての貢献ユーザーからの統計データの グローバル 累積値を追跡するには、Set as Global を true に設定してください。これにより、システムは個々のユーザー統計データだけでなく、グローバル統計データに貢献するすべてのユーザーからの累積統計データも追跡します。
-
Set By フィールドを Server に設定することで、ゲームサーバーのみが統計データを更新できるようにする検証を追加することもできます。これにより、ユーザーはゲームクライアントから直接統計データを更新することが拒否されます。これは、チートやゲームクライアントの改ざんを防ぐ良い方法でもあります。
-
ゲームから統計データをグループ化して整理しやすくするために、統計データの tags をオプションで設定できます。
-
Game SDK または Extend SDK を使用した統計データの使用
管理者ポータルで統計データが設定されたら、このセクションで説明されている例を参照して、SDK を使用して統計データを使用できます。
サーバー主導型の統計データ管理は、こちらのガイドに従って行うこともできます。
統計データの更新
この更新機能はゲームクライアントから直接呼び出すことができ、ゲームサーバーを利用しないシングルプレイヤーやピアツーピアマルチプレイヤーなどの非競争的なジャンルに適しています。
以下の表に示すように、いくつかの更新戦略がサポートされています:
| 更新戦略 | 使用方法 | 実装例 |
| OVERRIDE | 更新により、統計データの既存の値が最新の値に置き換えられます | ELO や MMR など、独自の計算がある場合に適しています。最新の値を渡して、サービスに保存させることができます。 |
| INCREMENT | 更新により、新しい値が正(+)か負(-)かに応じて、既存の値に新しい値が加算または減算されます | バトルで獲得した経験値を追跡するのに適しています。この方法では、ポイントを直接渡すことができ、サービスが増分を処理します。 |
| MAX | 値が既存の値よりも高い場合にのみ統計データを更新します | キル数やダメージ量などの最高/最高スコアを追跡するのに適しています。スコアが既存のスコアよりも低い場合、サービスは更新を無視します。 |
| MIN | 値が既存の値よりも低い場合にのみ統計データを更新します。 | 最高のレースラップや最速ラウンドなどの最小スコアを追跡するのに適しています。スコアが既存のスコアよりも高い場合、サービスは更新を無視します。 |
単一ユーザー統計データの更新
- Unreal
- Unity
- C# Extend SDK
- Go Extend SDK
- Java Extend SDK
- Python Extend SDK
FApiClientPtr ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient();
FString AdditionalKey = " Your additional key";
FString StatCode = " Your stat code ";
FAccelByteModelsPublicUpdateUserStatItem UserStatItem{};
UserStatItem.UpdateStrategy = EAccelByteStatisticUpdateStrategy::OVERRIDE;
UserStatItem.Value = 100.0f;
ApiClient->Statistic.UpdateUserStatItemsValue(StatCode
, AdditionalKey
, UserStatItem
, THandler<FAccelByteModelsUpdateUserStatItemValueResponse>::CreateLambda([](FAccelByteModelsUpdateUserStatItemValueResponse Result)
{
// Do something if UpdateUserStatItemsValue is successful
})
, FErrorHandler::CreateLambda([](int32 ErrorCode, FString ErrorMessage)
{
// Do something if UpdateUserStatItemsValue has an error
}));
Statistic statistic = AccelByteSDK.GetClientRegistry().GetApi().GetStatistic();
string additionalKey = " Your additional key";
string statCode = " Your stat code ";
PublicUpdateUserStatItem userStatItem = new PublicUpdateUserStatItem
{
updateStrategy = StatisticUpdateStrategy.OVERRIDE,
value = 100
};
statistic.UpdateUserStatItemsValue(statCode, additionalKey, userStatItem, result =>
{
if (result.IsError)
{
// Do something if UpdateUserStatItemsValue an error
Debug.Log($"Error UpdateUserStatItemsValue, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
return;
}
// Do something if UpdateUserStatItemsValue is successful
});
string additionalKey = "Your additional key";
string statCode = "Your stat code";
string userId = "<user-id>";
var response = sdk.Social.UserStatistic.UpdateUserStatItemValueOp
.SetAdditionalKey(additionalKey)
.SetBody(new StatItemUpdate()
{
UpdateStrategy = StatItemUpdateUpdateStrategy.OVERRIDE,
Value = 100
})
.Execute(sdk.Namespace, statCode, userId);
if (response != null)
{
//do something if success
}
userStatisticService := &social.UserStatisticService{
Client: factory.NewSocialClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace := "mygame"
statCode := "mystatcode"
userId := "myuserid"
updateStrategy := socialclientmodels.StatItemUpdateUpdateStrategyOVERRIDE
value := float64(100)
body := socialclientmodels.StatItemUpdate {
UpdateStrategy: &updateStrategy,
Value: &value,
}
additionalKey := "myadditionalkey"
input := &user_statistic.UpdateUserStatItemValueParams{
Body: &body,
Namespace: namespace,
StatCode: statCode,
UserID: userId,
AdditionalKey: &additionalKey,
}
result, err := userStatisticService.UpdateUserStatItemValueShort(input)
UserStatistic userStatisticWrapper = new UserStatistic(sdk);
String additionalKey = "Your additional key";
String statCode = "Your stat code";
String userId = "<user-id>";
StatItemIncResult response;
try {
StatItemUpdate reqBody = StatItemUpdate.builder()
.updateStrategy(StatItemUpdate.UpdateStrategy.OVERRIDE.toString())
.value(100f)
.build();
response = userStatisticWrapper.updateUserStatItemValue(UpdateUserStatItemValue.builder()
.namespace("<namespace>")
.userId(userId)
.statCode(statCode)
.additionalKey(additionalKey)
.body(reqBody)
.build());
} catch (Exception e) {
// Do something when failed
return;
}
if (response == null) {
// Null response from server
} else {
//do something if success
}
import accelbyte_py_sdk.api.social as social_service
import accelbyte_py_sdk.api.social.models as social_models
result, error = social_service.update_user_stat_item_value_1(
body=social_models.StatItemUpdate()
.with_update_strategy("OVERRIDE")
.with_value(100.0)
stat_code="YourStatCode",
additional_key="YourAdditionalKey",
user_id="********************************",
namespace=namespace, # optional, gets the value from the global instance if unspecified
sdk=sdk, # optional, gets the global instance if unspecified
)
if error:
exit(error)
1人のユーザーの複数の統計データを更新
- Unreal
- Unity
- C# Extend SDK
- Go Extend SDK
- Java Extend SDK
- Python Extend SDK
FApiClientPtr ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient();
FString AdditionalKey = " Your additional key";
FAccelByteModelsUpdateUserStatItemWithStatCode UserStatItem1{};
UserStatItem.StatCode = " Your 1st stat code ";
UserStatItem.UpdateStrategy = EAccelByteStatisticUpdateStrategy::OVERRIDE;
UserStatItem.Value = 100.0f;
FAccelByteModelsUpdateUserStatItemWithStatCode UserStatItem2{};
UserStatItem.StatCode = " Your 2nd stat code ";
UserStatItem.UpdateStrategy = EAccelByteStatisticUpdateStrategy::INCREMENT;
UserStatItem.Value = 50.0f;
TArray<FAccelByteModelsUpdateUserStatItemWithStatCode> BulkUpdateUserStatItems = { UserStatItem1, UserStatItem2 };
ApiClient->Statistic.BulkUpdateUserStatItemsValue(AdditionalKey
, BulkUpdateUserStatItems
, THandler<TArray<FAccelByteModelsUpdateUserStatItemsResponse>>::CreateLambda([](TArray<FAccelByteModelsUpdateUserStatItemsResponse> Result)
{
// Do something if BulkUpdateUserStatItemsValue is successful
})
, FErrorHandler::CreateLambda([](int32 ErrorCode, FString ErrorMessage)
{
// Do something if BulkUpdateUserStatItemsValue has an error
}));
Statistic statistic = AccelByteSDK.GetClientRegistry().GetApi().GetStatistic();
string additionalKey = " Your additional key";
StatItemUpdate userStatItem1 = new StatItemUpdate
{
statCode = " Your 1st stat code ",
updateStrategy = StatisticUpdateStrategy.OVERRIDE,
value = 100
};
StatItemUpdate userStatItem2 = new StatItemUpdate
{
statCode = " Your 2nd stat code ",
updateStrategy = StatisticUpdateStrategy.INCREMENT,
value = 50
};
StatItemUpdate[] bulkUpdateUserStatItems = { userStatItem1, userStatItem2 };
statistic.UpdateUserStatItems(additionalKey, bulkUpdateUserStatItems, result =>
{
if (result.IsError)
{
// Do something if UpdateUserStatItems an error
Debug.Log($"Error UpdateUserStatItems, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
return;
}
// Do something if UpdateUserStatItems is successful
});
string additionalKey = "Your additional key";
string userId = "<user-id>";
var response = sdk.Social.UserStatistic.BulkUpdateUserStatItemOp
.SetAdditionalKey(additionalKey)
.SetBody(new List<BulkStatItemUpdate>()
{
new BulkStatItemUpdate()
{
StatCode = "Your first stat code",
UpdateStrategy = BulkStatItemUpdateUpdateStrategy.OVERRIDE,
Value = 100
},
new BulkStatItemUpdate()
{
StatCode = "Your second stat code",
UpdateStrategy = BulkStatItemUpdateUpdateStrategy.OVERRIDE,
Value =50
}
})
.Execute(sdk.Namespace, userId);
if (response != null)
{
//do something if success
}
userStatisticService := &social.UserStatisticService{
Client: factory.NewSocialClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace := "mygame"
userId := "myuserid"
statCode1 := "statcode1"
value1 := float64(100)
statCode2 := "statcode2"
value2 := float64(100)
updateStrategy := socialclientmodels.BulkStatItemUpdateUpdateStrategyOVERRIDE
item1 := socialclientmodels.BulkStatItemUpdate {
StatCode: &statCode1,
UpdateStrategy: &updateStrategy,
Value: &value1,
}
item2 := socialclientmodels.BulkStatItemUpdate {
StatCode: &statCode2,
UpdateStrategy: &updateStrategy,
Value: &value2,
}
body := []*socialclientmodels.BulkStatItemUpdate{
&item1,
&item2,
}
additionalKey, _ := cmd.Flags().GetString("additionalKey")
input := &user_statistic.BulkUpdateUserStatItemParams{
Body: body,
Namespace: namespace,
UserID: userId,
AdditionalKey: &additionalKey,
}
result, err := userStatisticService.BulkUpdateUserStatItemShort(input)
UserStatistic userStatisticWrapper = new UserStatistic(sdk);
String additionalKey = "Your additional key";
String userId = "<user-id>";
List<BulkStatOperationResult> response;
try {
List<BulkStatItemUpdate> reqBody = Arrays.asList(
BulkStatItemUpdate.builder().statCode("Your first stat code")
.updateStrategy(StatItemUpdate.UpdateStrategy.OVERRIDE.toString())
.value(100f)
.build(),
BulkStatItemUpdate.builder().statCode("Your second stat code")
.updateStrategy(StatItemUpdate.UpdateStrategy.OVERRIDE.toString())
.value(50f)
.build()
);
response = userStatisticWrapper.bulkUpdateUserStatItem(BulkUpdateUserStatItem.builder()
.namespace("<namespace>")
.userId(userId)
.additionalKey(additionalKey)
.body(reqBody)
.build());
} catch (Exception e) {
// Do something when failed
return;
}
if (response == null) {
// Null response from server
} else {
// Do something if success
}
import accelbyte_py_sdk.api.social as social_service
import accelbyte_py_sdk.api.social.models as social_models
result, error = social_service.bulk_update_user_stat_item_2(
body=[
social_models.BulkStatItemUpdate()
.with_stat_code("YourStatCode1")
.with_update_strategy("OVERRIDE")
.with_value(100.0),
social_models.BulkStatItemUpdate()
.with_stat_code("YourStatCode2")
.with_update_strategy("INCREMENT")
.with_value(50.0),
],
user_id="********************************",
additional_key="YourAdditionalKey",
namespace=namespace, # optional, gets the value from the global instance if unspecified
sdk=sdk, # optional, gets the global instance if unspecified
)
if error:
exit(error)
ユーザー統計データの取得
ユーザー統計データの取得は簡単で、ユーザープロファイルの一部として、またはゲーム UI 内の任意の場所にユーザー統計データを表示できます。すべてのユーザー統計データをリストするか、statcodes によっていくつかの統計データを表示するか、または管理者ポータルで事前に設定したタグによって統計データを表示することもできます。
SDK 機能を使用するには、以下のスニペットを参照してください
現在のユーザーと他のユーザーの統計データを取得
- Unreal
- Unity
- C# Extend SDK
- Go Extend SDK
- Java Extend SDK
- Python Extend SDK
FApiClientPtr ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient();
FString UserId = "Player User Id";
TArray<FString> StatCodes = { "Stat Code 1", "Stat Code 2" };
TArray<FString> Tags = { "Tag 1", "Tag 2", "Tag 3" };
int32 Offset = 0;
int32 Limit = 20;
ApiClient->Statistic.GetUserStatItems(UserId
, StatCodes
, Tags
, THandler<FAccelByteModelsUserStatItemPagingSlicedResult>::CreateLambda([](FAccelByteModelsUserStatItemPagingSlicedResult Result)
{
// Do something if GetUserStatItems is successful
})
, FErrorHandler::CreateLambda([](int32 ErrorCode, FString ErrorMessage)
{
// Do something if GetUserStatItems has an error
})
, Offset
, Limit);
Statistic statistic = AccelByteSDK.GetClientRegistry().GetApi().GetStatistic();
string[] statCodes = { "Stat Code 1", "Stat Code 2" };
string[] tags = { "Tag 1", "Tag 2", "Tag 3" };
statistic.GetUserStatItems(statCodes, tags, result =>
{
if (result.IsError)
{
// Do something if GetUserStatItemshas an error
Debug.Log($"Error GetUserStatItems, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
return;
}
// Do something if GetUserStatItemshas is successful
});
string[] statCodes = new[] { "Stat Code 1", "Stat Code 2" };
string[] tags = new[] { "Tag 1", "Tag 2", "Tag 3" };
string userId = "<user-id>";
var response = sdk.Social.UserStatistic.GetUserStatItemsOp
.SetOffset(0)
.SetLimit(100)
.SetStatCodes(String.Join(",", statCodes))
.SetTags(String.Join(",", tags))
.Execute(sdk.Namespace, userId);
if (response != null)
{
//do something if success
}
userStatisticService := &social.UserStatisticService{
Client: factory.NewSocialClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace := "mygame"
userId := "myuserid"
statCodes := "statcode1,statcode2"
tags := "tag1,tag2,tag3"
input := &user_statistic.GetUserStatItemsParams{
Namespace: namespace,
UserID: userId,
StatCodes: &statCodes,
Tags: &tags,
}
result, err := userStatisticService.GetUserStatItemsShort(input)
UserStatistic userStatisticWrapper = new UserStatistic(sdk);
List <String> statCodes = List.of("Stat Code 1", "Stat Code 2");
List <String> tags = List.of("Tag 1", "Tag 2", "Tag 3");
String userId = "<user-id>";
UserStatItemPagingSlicedResult response;
try {
response = userStatisticWrapper.getUserStatItems(GetUserStatItems.builder()
.namespace("<namespace>")
.userId(userId)
.offset(0)
.limit(100)
.statCodes(String.join(",", statCodes))
.tags(String.join(",", tags))
.build());
} catch (Exception e) {
// Do something when failed
return;
}
if (response == null) {
// Null response from server
} else {
// Do something if success
}
import accelbyte_py_sdk.api.social as social_service
result, error = social_service.public_query_user_stat_items(
limit=20,
offset=0,
stat_codes=["StatCode1", "StatCode2"],
tags=["Tag1", "Tag2"],
user_id="********************************",
namespace=namespace, # optional, gets the value from the global instance if unspecified
sdk=sdk, # optional, gets the global instance if unspecified
)
if error:
exit(error)
グローバル統計データの取得
ユーザー統計データと同様に、ゲーム UI 内の任意の場所にグローバル統計データを簡単に表示することもできます。所有しているすべてのグローバル統計データを表示するか、statcode を使用して特定の統計データを選択することができます。
SDK 機能を使用するには、以下のスニペットを参照してください。
Statcode を使用してグローバル統計データを取得
- Unreal
- Unity
- C# Extend SDK
- Go Extend SDK
- Java Extend SDK
- Python Extend SDK
FApiClientPtr ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient();
FString StatCode = "Your Global Statistic Code";
ApiClient->Statistic.GetGlobalStatItemsByStatCode(StatCode
, THandler<FAccelByteModelsGlobalStatItemValueResponse>::CreateLambda([](FAccelByteModelsGlobalStatItemValueResponse Result)
{
// Do something if GetGlobalStatItemsByStatCode is successful
})
, FErrorHandler::CreateLambda([](int32 ErrorCode, FString ErrorMessage)
{
// Do something if GetGlobalStatItemsByStatCode has an error
}));
Statistic statistic = AccelByteSDK.GetClientRegistry().GetApi().GetStatistic();
string statCode = "Your Global Statistic Code";
statistic.GetGlobalStatItemsByStatCode(statCode, result =>
{
if (result.IsError)
{
// Do something if GetGlobalStatItemsByStatCode has an error
Debug.Log($"Error GetGlobalStatItemsByStatCode, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
return;
}
// Do something if GetGlobalStatItemsByStatCode is successful
});
string statCode = "GlobalStatCode";
var response = sdk.Social.GlobalStatistic.GetGlobalStatItemByStatCodeOp
.Execute(sdk.Namespace, statCode);
if (response != null)
{
//do something if success
}
globalStatisticService := &social.GlobalStatisticService{
Client: factory.NewSocialClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace := "mygame"
statCode := "mystatcode"
input := &global_statistic.GetGlobalStatItemByStatCodeParams{
Namespace: namespace,
StatCode: statCode,
}
result, err := globalStatisticService.GetGlobalStatItemByStatCodeShort(input)
GlobalStatistic globalStatisticWrapper = new GlobalStatistic(sdk);
String statCode = "GlobalStatCode";
GlobalStatItemInfo response;
try {
response = globalStatisticWrapper.getGlobalStatItemByStatCode(GetGlobalStatItemByStatCode.builder()
.namespace("<namespace>")
.statCode(statCode)
.build());
} catch (Exception e) {
// Do something when failed
return;
}
if (response == null) {
// Null response from server
} else {
// Do something if success
}
import accelbyte_py_sdk.api.social as social_service
result, error = social_service.get_global_stat_item_by_stat_code_1(
stat_code="YourGlobalStatisticCode",
namespace=namespace, # optional, gets the value from the global instance if unspecified
sdk=sdk, # optional, gets the global instance if unspecified
)
if error:
exit(error)