Configuring the Lobby with the SDK
概要
AccelByte ロビーサービスは、ゲームとプレイヤーを継続的に接続します。ロビーはゲームのメインハブとして機能するため、他の多くのサービスに接続されています。
ロビーサービスは、[WebSocket プロトコル](https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol) を使用しています。WebSocket は、サーバーとクライアント間の双方向通信を可能にすることで、信頼性の高い、リアルタイムデータ転送を保証します。
このトピックの目標
- ロビーサービスへの接続方法を説明する。
- 接続/切断イベントの処理方法を説明する。
- ユーザープレゼンスの処理方法を説明する。
- 告知をリッスンする方法を説明する。
前提条件
- プレイヤーがロビーに到達するまでに発生する[認証](../../01-access/03-authentication/index.mdx) フローに精通している。
- 管理者ポータルにアクセスでき、ログインできる。
- AccelByte UnrealまたはUnity SDK をインストールしている。これには、ゲームクライアントの認証情報が含まれる。
- クライアント ID
- クライアントの秘密
- AccelByte ロビー API ドキュメントにアクセスできる。
Client SDK でのロビーの実装
ロビーへの接続
以下のコマンドを使用して、AccelByte ロビーサービスをゲームに接続できます。
- OSS
- Unreal Engine
- Unity
bAutoLobbyConnectAfterLoginSuccess
を true に設定します([OnlineSubsystemAccelByte]
セクションの DefaultEngine.ini)。設定が完了すると、OSS はユーザーのログイン時にロビーに接続しようとします。- 自動的に接続されない場合は、
FOnlineIdentityAccelByte::ConnectAccelByteLobby
を呼び出します。
// Manually connect to lobby
int32 LocalUserNum = 0;
FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(OnlineSubsystem->GetIdentityInterface());
AB_TEST_TRUE(IdentityInterface.IsValid());
IdentityInterface->ConnectAccelByteLobby(LocalUserNum);
AccelByte::FRegistry::Lobby.Connect();
AccelBytePlugin.GetLobby().Connect();
ロビー接続の設定を完了したら、プレゼンス、パーティ、フレンド、チャット などのロビー機能を追加できます。
接続/切断イベントの処理
この機能は、ロビーサーバー接続に対する変更をゲームに告知します。SDK では既に自動再接続メカニズムが提供されていますが、自動再接続がタイムアウトすると、手動で再接続する必要があります。
- OSS
- Unreal Engine
- Unity
OSS で、ユーザーがログアウトすると、ロビーは自動的に切断されます。
FRegistry::Lobby.Connect();
FRegistry::Lobby.SetConnectSuccessDelegate(AccelByte::Api::Lobby::ConnectSuccess.CreateLambda([]()
{
// Do something If ConnectSuccessDelegate has been successful
}));
FRegistry::Lobby.SetConnectFailedDelegate(AccelByte::Api::Lobby::ConnectError.CreateLambda([]()
{
// Do something if ConnectFailedDelegate has been successful
}));
FRegistry::Lobby.SetConnectionClosedDelegate(AccelByte::Api::Lobby::ConnectionClosed.CreateLambda([]()
{
// Do something if ConnectionClosedDelegate has been successful
}));
AccelBytePlugin.GetLobby().Connect();
AccelBytePlugin.GetLobby().Connected += () =>
{
// Do something if Lobby Connected
};
AccelBytePlugin.GetLobby().Disconnected += error =>
{
// Do something if Lobby Disconnected
Debug.Log($"Lobby Disconnected, Error Code: {(int) error}");
};
プレゼンス
プレゼンスサービスはソーシャルパッケージの一部です。プレゼンスサービスは、ユーザーのプレゼンス (状況とアクティビティ) ステータスを処理します。
状況ステータスとは、オンライン時におけるユーザーの状況 (オンライン、オフライン、離席中など) を表示するものです。アクティビティステータスは、ユーザーの現在のアクティビティを表示するために使用される任意の文字列値です。idle (アイドル中)、playing shooter game (シューティングゲームをプレイ中)、in Lobby (ロビーに滞在中)、in matchmaking (マッチメイキング中)、in match (マッチ中) などがあります。プレゼンスサービスはフレンドサービスに依存しており、オンラインのフレンドを一覧表示し、変化するプレゼンスステータスを取得するためのフィルターとして使用されます。
一般的なワークフロー:
- ユーザーがロビーとの接続を初期化した後、すべてのフレンドのプレゼンスステータス (状況とアクティビティ) を取得します。
- ユーザーがアクティビティを変更するたびに、ユーザーのステータスを設定します。
- フレンドのプレゼンスステータスの更新をリッスンし、フレンドのプレゼンスステータスを更新します。
- ユーザーがロビーサーバーから切断されると、ユーザーの状況は自動的に 0 にリセットされます。
- ユーザーのアクティビティは、ユーザーがロビーサーバーから切断された際にも保持されます。
Availability (状況) は列挙型整数で表されます。
- 0:offline (オフライン)
- 1:available (応対可能)
- 2:busy (取り込み中)
- 3:invisible (非表示)
Activity (アクティビティ) は、以下のような任意の文字列として設定できます。
- Playing Survival (サバイバルをプレイ中)
- In Lobby (ロビーに滞在中)
- In Match (マッチ中)
ステータスの作成とフレンドのステータスの表示
プレイヤーのプレゼンスは、ゲーム、プレイヤーポータル、またはランチャーのいずれかで設定できます。これにより、プレイヤーのフレンドは、プレイヤーがいつオンラインなのか、何をしているかを見ることができます。
- OSS
- Unreal Engine
- Unity
OnlineSubsystem = static_cast<FOnlineSubsystemAccelByte*>(IOnlineSubsystem::Get(ACCELBYTE_SUBSYSTEM));
PresenceInterface = OnlineSubsystem->GetPresenceInterface();
// listen to friend presence change notification
auto OnPresenceReceived = PresenceInterface->AddOnPresenceReceivedDelegate_Handle(FOnPresenceReceivedDelegate::CreateLambda([](const class FUniqueNetId& UserId, const TSharedRef<FOnlineUserPresence>& Presence)
{
// do something when friend presence changed
}));
// create / change status
PresenceInterface->SetPresence(*CurrentUser.Get(), Status, IOnlinePresence::FOnPresenceTaskCompleteDelegate::CreateLambda([](const FUniqueNetId& User, bool bWasSuccessful)
{
// do something when presence set presence success
}));
// View Changed Friend's Status
AccelByte::FRegistry::Lobby.SetUserPresenceNotifDelegate(THandler<FAccelByteModelsUsersPresenceNotice>::CreateLambda([](const FAccelByteModelsUsersPresenceNotice Result)
{
UE_LOG(LogTemp, Log, TEXT("Friend %s, Activity: %s | Availability: %s "), Result.UserID, Result.Activity, Result.Availability);
}
));
// Create/Change Status
AccelByte::FRegistry::Lobby.SetUserPresenceResponseDelegate(Api::Lobby::FSetUserPresenceResponse::CreateLambda([](FAccelByteModelsSetOnlineUsersResponse result)
{
UE_LOG(LogTemp, Log, TEXT("User Status Changed!"));
}));
FString UserActivity = TEXT("Playing Game");
AccelByte::FRegistry::Lobby.SendSetPresenceStatus(Availability::Busy, UserActivity);
// View Changed Friend's Status
AccelBytePlugin.GetLobby().FriendsStatusChanged += result =>
{
Debug.Log("Friend " + result.Value.userID + ", Activity: " + result.Value.activity + " | Availability: " + result.Value.availability);
};
// Create/Change Status
string userActivity = "Playing Game";
AccelBytePlugin.GetLobby().SetUserStatus(
UserStatus.Busy,
userActivity,
result =>
{
Debug.Log("User Status Changed!");
}
);
フレンドのステータスリストの取得
プレイヤーは、すべてのフレンドのステータスリストも見ることができます。
- Unreal Engine
- OSS
- Unity
AccelByte::FRegistry::Lobby.SetGetAllUserPresenceResponseDelegate(Api::Lobby::FGetAllFriendsStatusResponse::CreateLambda([](FAccelByteModelsGetOnlineUsersResponse result)
{
for(int i = 0; i < Result.friendId.Num(); i++)
{
UE_LOG(LogTemp, Log, TEXT("Friend %s, Activity: %s | Availability: %s "), Result.friendId[i], Result.Activity[i], Result.Availability[i]);
}
}));
AccelByte::FRegistry::Lobby.SendGetOnlineUsersRequest();
この機能は OSS では使用できません。
AccelBytePlugin.GetLobby().ListFriendsStatus(result =>
{
for(int i = 0; i < onlineFriendsResult.Value.friendsId.Length; i++)
{
Debug.Log("Friend " + result.Value.friendId[i] + ", Activity: " + result.Value.activity[i] + " | Availability: " + result.Value.availability[i]);
}
});
フレンドのプレゼンスの一括取得
プレイヤーのプレゼンス情報を一括して取得できます。これにより、プレゼンスステータス (オンライン、取り込み中、非表示、オフラインなど) に基づいてユーザー数もカウントされます。countOnly
パラメータを true に設定して、ユーザーのアカウントデータを取得せずにカウントを取得することもできます。
- OSS
- Unreal Engine
- Unity
OnlineSubsystem = static_cast<FOnlineSubsystemAccelByte*>(IOnlineSubsystem::Get(ACCELBYTE_SUBSYSTEM));
PresenceInterface = OnlineSubsystem->GetPresenceInterface();
auto OnPresenceReceived = PresenceInterface->AddOnPresenceReceivedDelegate_Handle(FOnPresenceReceivedDelegate::CreateLambda([](const class FUniqueNetId& UserId, const TSharedRef<FOnlineUserPresence>& Presence)
{
// do something when query user Presence done
}));
PresenceInterface->QueryPresence(UserId);
TArray<FString> UserIds = {FString("12345abcd"), FString("abcd12345")};
bool CountOnly = true;
FRegistry::Lobby.Connect();
FRegistry::Lobby.BulkGetUserPresence(UserIds, THandler<FAccelByteModelsBulkUserStatusNotif>::CreateLambda([](const FAccelByteModelsBulkUserStatusNotif& Result)
{
// Do something if BulkGetUserPresence has been successful
}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something if BulkGetUserPresence has an error
UE_LOG(LogTemp, Log, TEXT("Error BulkGetUserPresence, Error Code: %d Error Message: %s"), ErrorCode, *ErrorMessage);
}), CountOnly);
var userIds = new List<string>();
userIds.Add("123456789");
userIds.Add("987654321");
bool countOnly = false;
AccelBytePlugin.GetLobby().BulkGetUserPresence(userIds, result =>
{
if(!result.IsError)
{
foreach( var user in result.Value.data)
{
Debug.Log("UserId: " + user.userID + " | Availability: " + user.availability.ToString());
}
Debug.Log("User's status count. Online: " + result.Value.online + " | Busy:" + result.Value.busy + " | Invisible:" + result.Value.invisible + " | Offline:" + result.Value.offline);
}
else
{
Debug.Log("Error: " + result.Error.Code + " | Message: " + result.Error.Message);
}
}, countOnly);
});
告知
告知に関するタスクは複数あります。
フリーフォーム告知の送信
- 告知 REST API エンドポイントを呼び出して、テキスト告知メッセージを送信します。
- 告知クライアントは新しい告知をリッスンします。
テンプレート告知の送信
- 管理者は、テンプレートスラッグ (識別子)、コンテキスト (置換されるテンプレート値)、テンプレート言語を含む告知テンプレートを作成します。
- 管理者はテンプレートをパブリッシュします。
- テンプレートスラッグ、コンテキスト、言語は、サービスコンシューマー (管理者ユーザーまたはその他のサービス) に送信されます。
- サービスコンシューマーは、告知 REST API エンドポイントを呼び出し、テンプレートスラッグ、言語、テンプレートコンテキストの値を指定します。
- 告知クライアントは新しい告知をリッスンします。
非同期告知の送信
- フリーフォーム告知またはテンプレート告知のワークフローに従います。
- REST API エンドポイントを呼び出す際は、クエリパラメータを非同期として指定します。
- プレイヤーがオンラインの場合、メッセージはすぐに送信されます。
- プレイヤーがオフラインの場合、メッセージは保存されます。
保存された告知の取得
- プレイヤーがロビーサーバーに接続します。
- 告知がプレイヤーに送信されます。
ユーザーに送信される告知はすべて、一般的な形式です。クライアントは、告知に設定されたトピックに基づいて、告知を表示/配置する場所を決定できます。たとえば、ゲームの更新告知はポップアップとして表示する、ゲームサーバーの告知は「システム」チャットボックスに表示するなどです。
Websocket 告知形式
告知メッセージ:
type: messageNotif
topic: updateNotification
from: system
to: user123
payload: message content 123
sentAt: 2018-11-25T23:45:05Z
`### SDK からの告知の取得
告知を同期または非同期のいずれかで取得できます。
同期告知の取得
SDK を使用して同期告知を取得するには、告知デリゲートを追加する必要があります。
- Unreal Engine
- OSS
- Unity
const auto NotificationDelegate = AccelByte::Api::Lobby::FMessageNotif::CreateLambda([](const FAccelByteModelsNotificationMessage& Result)
{
UE_LOG(LogTemp, Log, TEXT("There is an incoming notification."));
UE_LOG(LogTemp, Log, TEXT("From: %s \nTo: %s\nTopic: %s"), *Result.From, *Result.To, *Result.Topic);
UE_LOG(LogTemp, Log, TEXT("Notification: %s"), *Result.Payload);
});
AccelByte::FRegistry::Lobby.SetMessageNotifDelegate(NotificationDelegate);
AccelByte::FRegistry::Lobby.Connect();
この機能は OSS では利用できません。
public static void OnReceiveNotification(Result<Notification> result)
{
Debug.Log(result.IsError);
Debug.Log(“There is an incoming notification.”);
Debug.Log(result.Value.payload);
}
public static void Main(string[] args)
{
var lobby = AccelBytePlugin.GetLobby();
lobby.OnNotification += OnReceiveNotification;
lobby.Connect();
}
トピックごとに告知をフィルタリングすることもできます。
- Unreal Engine
- OSS
- Unity
const auto NotificationDelegate = AccelByte::Api::Lobby::FMessageNotif::CreateLambda([](const FAccelByteModelsNotificationMessage& Result)
{
UE_LOG(LogTemp, Log, TEXT("There is an incoming notification."));
if(Result.Topic == “INGAME”)
{
UE_LOG(LogTemp, Log, TEXT("Game notification: %s"), *result.Payload);
}
Else if(Result.Topic == “EVENT”)
{
UE_LOG(LogTemp, Log, TEXT("Event notification: %s"), *result.Payload);
}
});
この機能は OSS では利用できません。
public static void OnReceiveNotification(Result<Notification> result)
{
Debug.Log(result.IsError);
Debug.Log(“There is an incoming notification.”);
switch(result.Value.topic){
case “INGAME” : Debug.Log(“Game notification: “ + result.Value.payload); break;
case “EVENT” : Debug.Log(“Event notification: “ + result.Value.payload); break;
}
}