跳到主要内容

群组

最后更新:2026 年 9 月 14 日

群组是一个具名的事件通道。连接按名字订阅一个群组,发布到该群组的任何内容都会送达所有订阅者。它让你一次性把一条消息扇出给一组客户端——大厅聊天、“玩家已准备”信号、向一局中所有人广播——而无需逐个知道他们是谁。

群组直接构建在 Events 系统之上:群组只是你已经用于事件的那套发布/订阅的一个路由作用域。

信息

群组成员身份是按连接作用域的。你在一个活动连接上订阅,只要该连接存在你就是成员;没有存储的花名册,也没有显式的“永久退出群组”。连接断开,订阅随之断开——而在一次透明重连之后,SDK 会自动为你重新订阅你的群组。

备注

群组是一个消息通道,不是带座位的游戏房间。如果你想让平台撮合玩家并维持一局实时对战——预订票据、容量、游戏服务器——见连接到游戏。游戏房间其实就构建在群组之上:房间通过向一个群组发布来向其玩家广播。


模型​

两个动词几乎涵盖一切:订阅一个群组以接收它的事件,发布到一个群组以发送一条。

发布者PublishForGroup群组"lobby-42"订阅者订阅者订阅者发布路由给每个订阅者

加入与离开​

订阅一个群组以开始接收它的事件,取消订阅以停止。两者都可 await,并返回命令是否成功。

await PlayServEvents.SubscribeGroupAsync("lobby-42");
// …稍后
await PlayServEvents.UnsubscribeGroupAsync("lobby-42");

离开时你不必取消订阅:因为成员身份绑定到连接,关闭连接会把你从所有群组移除。取消订阅用于你想在保持连接的同时离开某个群组。群组命令有一个较短的超时(10 秒)——订阅失败会以 PlayServGroupSubscriptionException 呈现。

备注

没有服务器端的接受/拒绝步骤,也没有成员花名册。订阅是一条路由指令,而不是服务器裁决的请求——任何连接到你项目的人都能订阅它的任意群组名。把授权放进你发布的事件里,或用云函数守护敏感操作,而不是靠群组成员身份。


向群组发布​

发布一个带类型的事件,当前每个订阅者都会收到:

PlayServEvents.PublishForGroup("lobby-42", new ChatMessage { Text = "gg" });

事件以 GroupEventMessage 信封送达,携带群组名、事件类型名和 JSON 载荷;订阅者按类型接收。除群组变体外,还有两种相关的发送:

  • Publish<T>(evt)——不带群组作用域地发布。
  • PublishForUser<T>(userId, evt)——送达某个特定用户的连接。

接收事件​

订阅一个类型,以处理来自你已加入的任意群组的事件:

PlayServEvents.Subscribe<ChatMessage>(msg => {
// 渲染 msg.Text
});

Subscribe<T> 返回一个 IDisposable,你释放它即停止监听(还有 IObservable<T> 重载,以及用于原始 JSON 的 SubscribeRaw<T>)。接收按事件类型进行——加入群组决定哪些事件到达你,类型订阅决定你如何处理它们。


群组名按你的项目作用域​

群组名会自动按项目命名空间化,因此你项目里的 "lobby-42" 绝不会与另一个项目冲突,也不能从另一个项目订阅。尝试订阅超出你项目作用域的名字会以 GroupOutsideProject 失败。


限制​

限制值
每连接群组数64
群组名长度最多 256 个字符

超过每连接数量会使订阅以 GroupSubscriptionLimitReached 失败。上限是按连接计的,因此它限制的是单个客户端的扇入量,而非你项目可拥有的群组数量。


群组不是什么​

为了把预期讲清楚,群组有意不提供:

  • 在场 / 成员列表——没有“谁在这个群组里”的查询,也没有 SomeoneJoined / SomeoneLeft 事件。成员身份不作为状态被追踪;它是一个实时路由集合。若需要在场,自行建模:让客户端发布“hello”/“bye”事件,或使用游戏服务器自己的房间花名册。
  • 服务器端加入的接受/拒绝——订阅不会按用户被拒。
  • 关闭 / 拆除——你不关闭群组;当所有人断开或取消订阅后,它自然就没有订阅者了。

下一步​