大厅事件

重要提示:只有 1.0.0 及更高版本中可以使用大厅事件。

Lobby 软件包中包含 Lobby Events 系统,该系统允许您订阅实时大厅事件。每次成员可观察的玩家/大厅状态发生变化时,都会发送事件。例如,当玩家加入或离开时,玩家更新公开/成员数据时,或者厅主更新公开/成员大厅数据时。玩家或厅主更新大厅的私人属性时,不会发送事件。

使用事件可能比通过 get 轮询大厅状态更有效,特别是因为它不需要任何操作,直到某些数据发生变化。当每秒 get 请求数量明显大于每秒收到的事件数量时,事件的效率更高。此外,事件的有效负载仅包含补丁,因此一般来说,事件的有效负载要比 get 返回的有效负载小得多,这是另一项优势。事件的最大缺点是它们不可靠,不能保证按顺序交付。有关更多信息,请参阅“大厅版本”。

注意:事件可能不可靠,不能保证按顺序交付。

在 Lobby 实例中调用 SubscribeToLobbyEventsAsync 方法可以订阅接收这个实例的更新。订阅后,Lobby 服务会在每次发生更改时调用 LobbyChanged 事件。您还可以使用 ApplyToLobby 辅助方法来向 Models.Lobby 对象应用更改。

接收更新

要订阅大厅的实时更新,必须调用以下命令:

Lobbies.Instance.SubscribeToLobbyEventsAsync(lobbyId, callbacks);
  • callbacks 对象提供用于处理实时变化的回调函数。
  • callbacks 参数接受 LobbyEventsCallbacks 的实例,该实例必须由您创建并订阅。

注意:玩家只有在大厅中时,才能接收大厅的事件。

以下代码示例展示了如何创建并订阅大厅:

m_Lobby = await Lobbies.Instance.CreateLobbyAsync(lobbyName, maxPlayers, options);
var callbacks = new LobbyEventCallbacks();
callbacks.LobbyChanged += OnLobbyChanged;
callbacks.KickedFromLobby += OnKickedFromLobby;
callbacks.LobbyEventConnectionStateChanged += OnLobbyEventConnectionStateChanged;
try {
    m_LobbyEvents = await Lobbies.Instance.SubscribeToLobbyEventsAsync(m_Lobby.Id, callbacks);
}
catch (LobbyServiceException ex)
{
    switch (ex.Reason) {
        case LobbyExceptionReason.AlreadySubscribedToLobby: Debug.LogWarning($"Already subscribed to lobby[{m_Lobby.Id}]. We did not need to try and subscribe again. Exception Message: {ex.Message}"); break;
        case LobbyExceptionReason.SubscriptionToLobbyLostWhileBusy: Debug.LogError($"Subscription to lobby events was lost while it was busy trying to subscribe. Exception Message: {ex.Message}"); throw;
        case LobbyExceptionReason.LobbyEventServiceConnectionError: Debug.LogError($"Failed to connect to lobby events. Exception Message: {ex.Message}"); throw;
        default: throw;
    }
}

注意:在上述代码示例中,OnLobbyChangedOnKickedFromLobbyOnLobbyEventConnectionStateChanged 负责处理事件。

以下代码示例提供了 OnLobbyChanged 的示例处理程序,并展示了如何处理已删除的大厅实例。

private void OnLobbyChanged(ILobbyChanges changes)
{
    if (changes.LobbyDeleted)
    {
        // Handle lobby being deleted
        // Calling changes.ApplyToLobby will log a warning and do nothing
    }
    else
    {
        changes.ApplyToLobby(m_Lobby);
    }
    // Refresh the UI in some way
}

KickedFromLobby

Lobby Event 服务使用 KickedFromLobby 处理程序来从大厅中移除用户。这可能因为多种原因而发生。例如,当连接失败时,或者厅主将用户从大厅中移除时。当用户被踢出大厅时,他们会收到一条消息,表明大厅事件连接状态已更改 (LobbyEventConnectionStateChanged) 为 unsubscribed

以下代码示例提供了 OnKickedFromLobby 的示例处理程序:

private void OnKickedFromLobby()
{


    // These events will never trigger again, so let’s remove it.
    this.m_LobbyEvents = null;
    // Refresh the UI in some way
}

以下代码示例提供了 OnLobbyEventConnectionStateChanged 的示例处理程序:

注意:当与 Lobby Events 的连接发生错误时,Lobby 不会尝试重新连接。

private void OnLobbyEventConnectionStateChanged(LobbyEventConnectionState state)
{
    switch (state)
    {
        case LobbyEventConnectionState.Unsubscribed: /* Update the UI if necessary, as the subscription has been stopped. */ break;
        case LobbyEventConnectionState.Subscribing: /* Update the UI if necessary, while waiting to be subscribed. */ break;
        case LobbyEventConnectionState.Subscribed: /* Update the UI if necessary, to show subscription is working. */ break;
        case LobbyEventConnectionState.Unsynced: /* Update the UI to show connection problems. Lobby will attempt to reconnect automatically. */ break;
        case LobbyEventConnectionState.Error: /* Update the UI to show the connection has errored. Lobby will not attempt to reconnect as something has gone wrong. */
    }
}

向大厅应用更改

订阅 LobbyEventCallbacks.LobbyChanged 事件后,每次大厅发生更新时,您都会收到一组更改。大厅可能在任何给定时间出现大量的变化,因此 Lobby 软件包中包含一个辅助函数,用于将这些更改应用到大厅。

以下代码片段展示了如何使用 ApplyToLobby 辅助函数来应用大厅更改:

private void OnLobbyChanged(ILobbyChanges changes)
{
    changes.ApplyToLobby(m_Lobby);
    // Refresh the UI in some way
}

调用 changes.ApplyToLobby 会原地更新大厅上发生变化的所有字段。当大厅的变化发生在原地时,该调用会修改传递到 ApplyToLobby 函数的大厅对象值。如果您需要检查是否已应用特定的更改,请检查 ILobbyChanges 接口上的 ChangedLobbyValue 成员。

以下代码示例展示了如何检查这些值:

private void OnLobbyChanged(ILobbyChanges changes)
{
    changes.ApplyToLobby(m_Lobby);
    if (changes.Name.Changed)
    {
        // Do something specific due to this change
    }
    // Refresh the UI in some way
}

大厅版本

如果要检查新获取的大厅相较于上次观察到的大厅是否发生了变化,大厅版本非常有用。每个大厅都公开了一个 Version 属性。版本从 1 开始,并且在每次成员可观察的玩家/大厅状态发生变化时都会递增。

如果与大厅的一组新更改相关联的版本没有比上次观察到的大厅版本大 1,则表示更新接收顺序发生了混乱或发生了更新丢失。如果您收到了丢失消息,请执行 get 来检索最新版本。

GetLobby API 可以选择性地接受大厅的版本作为参数。为了节省带宽,只有当指定的版本与当前版本不匹配时,才会返回大厅数据。

以下示例展示了这种情况的一个例子:

var lobby = await Lobbies.Instance.GetLobbyAsync("lobbyId");
var version = lobby.Version;

// check if a newer version of the lobby is available:
var newLobby = await Lobbies.Instance.GetLobbyAsync("lobbyId", version);
if (newLobby != null)
{
    // New lobby version received
    version = lobby.Version;
    // observe changed values in newLobby:

}

故障排除

确保您处理了提供的所有事件,尤其是 OnLobbyEventConnectionStateChangedOnKickedFromLobby,因为它们可能表示 Lobby Events 已停止。

OnLobbyEventConnectionStateChanged

Lobby Events 的连接状态指示您是否会收到事件。

具体的连接状态包括:

Unsubscribed

  • 您已使用 ILobbyEvents.UnsubscribeAsync 选择了取消订阅
  • 您将不再收到任何大厅事件。

Subscribing

  • Lobby Events 正在尝试建立连接。
  • 您将不会收到大厅事件。

Subscribed

  • Lobby Events 成功建立连接。
  • 您将会收到大厅事件。

Unsynced

  • 连接出现临时问题。
  • Lobby Events 将自动尝试重新建立连接。
  • 您将不会收到大厅事件。

Error

  • 连接出现不可恢复的问题。
  • 这可能表示存在更大的问题,例如互联网中断。需要手动干预并可能需要重新订阅。
  • 您将不会收到大厅事件。

API

接口

ILobbyServiceSDK

方法/属性名称返回类型描述
SubscribeToLobbyEventsAsyncTask<ILobbyEvents>订阅大厅事件并返回对象来控制该订阅。

ILobbyEvents

方法/属性名称返回类型描述
CallbacksLobbyEventCallbacks获取您在调用 SubscribeToLobbyAsync 时提供的 callbacks 对象。
SubscribeAsyncTask订阅事件。此操作会在您首次调用 SubscribetoLobbyAsync 时自动完成,但如果您取消订阅,则可以稍后重新订阅。
UnsubscribeAsyncTask取消订阅大厅事件,这样一来,您将停止接收更改。

ILobbyChanges

方法/属性名称返回类型描述
LobbyDeletedbool一个布尔值,指示大厅是否已删除。如果大厅已删除,该值为 true;如果大厅仍然可用,则该值为 false。
名称ChangedLobbyValue<string>对大厅名称的更改(如果发生了更改的话)。
IsPrivateChangedLobbyValue<bool>对大厅是否为私人的更改(如果发生了更改的话)。
IsLockedChangedLobbyValue<bool>对大厅是否已锁定的更改(如果发生了更改的话)。
AvailableSlotsChangedLobbyValue<int>对大厅中可用空位的更改(如果发生了更改的话)。
MaxPlayersChangedLobbyValue<int>对大厅中最大玩家人数的更改(如果发生了更改的话)。
DataChangedOrRemovedLobbyValue<Dictionary<string, ChangedOrRemovedLobbyValue<DataObject>>>对大厅数据的更改(如果发生了更改的话)。
PlayerLeftChangedLobbyValue<List<int>>已退出玩家(若有)的列表。
PlayerJoinedChangedLobbyValue<List<LobbyPlayerJoined>>已加入玩家(若有)的列表。
PlayerDataChangedLobbyValue<Dictionary<int, LobbyPlayerUpdated>>对玩家数据的更改(如果发生了任何更改的话)。
HostIdChangedLobbyValue<string>对厅主 ID 的更改(如果发生了更改的话)。
Version整型大厅的最新版本。
LastUpdatedChangedLobbyValue<DateTime>大厅发生更改的时间。
ApplyToLobbyvoid通过大厅和变更应用程序来原地更新给定的大厅。

类、结构体和枚举

LobbyEventCallbacks

事件名称参数类型描述
LobbyChangedILobbyChanges当服务器上的大厅发生变化时,Lobby 服务会触发此事件并提供发生的一组变化。
KickedFromLobby 当服务器上的大厅订阅被中止时。
LobbyEventConnectionStateChangedLobbyEventConnectionState当订阅连接发生状态变化时。

ChangedLobbyValue

属性名称返回类型描述
T更改提供的新值。
Changedbool如果发生了更改,则为 true;如果没有发生更改,则为 false。

LobbyValueChangeType

枚举值名称枚举值描述
Unchanged0值未更改。
Changed1值已更改。
Removed2值已移除。

ChangedOrRemovedLobbyValue

属性名称返回类型描述
T更改提供的新值。
Changedbool如果发生了更改,则为 true;如果没有发生更改,则为 false。
ChangeTypeLobbyValueChangeType此操作是更改还是移除。

错误代码

添加了以下错误代码:

LobbyExceptionReason 枚举值错误代码描述
AlreadySubscribedToLobby16601您已订阅此大厅并尝试了再次进行订阅
SubscriptionToLobbyLostWhileBusy16602尝试执行连接相关操作(例如订阅或取消订阅)时,连接丢失或中断
LobbyEventServiceConnectionError16603尝试连接到 Lobby 服务时发生了错误。确保发送了有效的大厅 ID