3

我在 Photon Server 官方论坛上问过这个问题,但它没有这个网站那么活跃,所以可能会有人明白我在说什么,所以如果你有时间和知识,请分享一下。谢谢!

来了...

所以,我在 Photon 上有一个非常好的服务器原型和一个与服务器对话的基本 Unity3D 客户端。它是根据 cjrgaming 上的示例构建的。

客户端可以:连接,发送请求,建立和发送加密请求服务器可以:创建peer,接收操作请求,发送操作响应或事件给客户端,还有,我的小补充是:如果一个游戏有很多操作,您不必使用巨大的 switch case 语句,而是将操作划分为类别(类),并使用委托和字典来调用它们。

当我觉得它已经准备好发布时,我将发布它的工作示例,但现在,对于我的实际问题..(对不起,长篇文章,我不得不解释我所知道的以及到目前为止我所拥有的):

从客户端发送到服务器的实际操作是什么?还是服务器向客户端引发的事件(一次所有客户端?)?

起初,我认为每个操作都是游戏中特定的用户流。例如,操作码“1”,表示玩家X想射杀玩家Y,做某事。但是后来,我意识到,根据字节限制,您不能将所有游戏逻辑仅放在 255 次操作中,而不将其扩展到 short int 或其他内容。

然后我发现还有一个channelID,它在同一个操作码请求上可以不同......这对我来说意味着操作码不是用户流,而是客户端之间相同/相似动作的数据流和服务器,channelID 可用于区分要在服务器上计算的请求操作。

然后...!我意识到(哦,傻瓜),有参数从客户端发送到服务器,反之亦然在字典中,这增加了另一层可能的用户流。

所以..现在我想了解一些事情,但他们让我更加困惑。

谁能简要解释一下操作/事件/通道ID的目的?例如,如果您做一个小型多人游戏,您将使用什么来制作用户(游戏)流程,例如 -> 玩家击中目标,玩家在世界上捡起物品,玩家发送消息。您会为每个流使用唯一的操作代码,还是按含义对操作进行分组并使用通道来区分请求,或者甚至在这里,您对许多用户流使用相同的 channelID 并通过参数内部的一些 ID 来区分它们?

希望我有任何意义。

非常感谢大家,至少,如果有的话,请帮忙!

4

1 回答 1

14

1)频道是一个完全不同的话题,与你想要触发的不同类型的游戏逻辑的区别无关。相反,如果一项操作依赖于另一个操作,则存在确定优先级和状态的通道。

a)如果您发送一个拍摄操作和一个 2 个聊天操作,并且由于客户端的网络连接不是最好的,那么第一个聊天消息会在途中丢失,但正如您所说发送当服务器没有确认它已收到它时,Photon 客户端将可靠地自动重新发送它。现在另一个聊天消息应该被 Photon 阻止,直到第一个可以成功发送,否则显示来自同一作者的聊天消息的顺序将不再是它们被写入的顺序。现在的问题是,不仅应该阻止相同类型的操作,而且可能还有其他操作,应该只在丢失的操作被重复之后发送(例如“用户离开”的可见结果聊天” 操作不应该显示在屏幕上,直到在他离开前发送的最后一条聊天消息之后)。另一方面,并​​非所有相同类型的操作都必须被阻止。例如,玩家可以私下与 2 个不同的其他用户交谈,当发给其中一个用户的一条消息没有立即通过时,则没有理由将所有消息保留给另一个用户。光子对这个问题的解决方案是通道:在同一个通道中发送所有相互依赖的操作,但在另一个通道中发送独立于它们的操作。如果现在必须重复其中一项操作,其他通道中的操作不会被阻止,但同一通道中的操作会被阻止。另一方面,并​​非所有相同类型的操作都必须被阻止。例如,玩家可以私下与 2 个不同的其他用户交谈,当发给其中一个用户的一条消息没有立即通过时,则没有理由将所有消息保留给另一个用户。光子对这个问题的解决方案是通道:在同一个通道中发送所有相互依赖的操作,但在另一个通道中发送独立于它们的操作。如果现在必须重复其中一项操作,其他通道中的操作不会被阻止,但同一通道中的操作会被阻止。另一方面,并​​非所有相同类型的操作都必须被阻止。例如,玩家可以私下与 2 个不同的其他用户交谈,当发给其中一个用户的一条消息没有立即通过时,则没有理由将所有消息保留给另一个用户。光子对这个问题的解决方案是通道:在同一个通道中发送所有相互依赖的操作,但在另一个通道中发送独立于它们的操作。如果现在必须重复其中一项操作,其他通道中的操作不会被阻止,但同一通道中的操作会被阻止。那么就没有理由将所有消息都保留给另一个人。光子对这个问题的解决方案是通道:在同一个通道中发送所有相互依赖的操作,但在另一个通道中发送独立于它们的操作。如果现在必须重复其中一项操作,其他通道中的操作不会被阻止,但同一通道中的操作会被阻止。那么就没有理由将所有消息都保留给另一个人。光子对这个问题的解决方案是通道:在同一个通道中发送所有相互依赖的操作,但在另一个通道中发送独立于它们的操作。如果现在必须重复其中一项操作,其他通道中的操作不会被阻止,但同一通道中的操作会被阻止。

b) 通道的另一种方式是,确定优先级:通道ID越低,优先级越高。因此,如果您有少量的高优先级数据和其他只有低优先级的数据,但可能碰巧出现大量数据,那么最好在低优先级的通道上发送高优先级数据。频道 ID。这样它仍然会立即出去,尽管在具有更高 ID 的通道中可能有很多数据已经排队等待发送,但尚未发送出去。

2) 操作和事件都是消息。实际上有三种类型的消息:操作请求、操作响应和事件。

a) 客户端可以通过 PhotonPeer.opCustom() 向服务器发送带有一定操作码的 operationRequest。一些典型的操作,如加入和离开房间,已经由 Photon 应用层的应用程序(如 Lite 或 LoadBalancing 应用程序)实现。如果有为 Photon 应用程序提供的客户端 API,那么该 API 可以提供诸如 opJoin() 之类的开箱即用的函数,这些函数使用正确的参数将调用包装到 opCustom(),就像提到的应用程序的客户端 API做。

b) 根据在应用程序级别上如何实现具有特定代码的操作,服务器可能会向客户端发送 operationResponse,它已从客户端接收到 operationReqeust。例如 LitePeer.opJoin() 将触发来自服务器的加入响应,但 LitePeer.opRaiseEvent 不会触发响应。

c) 根据应用程序级别的操作如何实现,服务器可能会也可能不会向某些客户端发送事件。例如 LitePeer.opJoin() 将触发一个加入事件,该事件将发送给该​​房间中的所有玩家。LitePeer.opRaiseEvent() 默认让服务器为同一房间中的所有客户端(发送客户端除外)引发一个事件,该事件包含您传递给它的有效负载。然而 opRaiseEvent() 为其调用客户端提供了指定接收客户端的可能性。

3)“玩家击中目标,玩家在世界上捡起物品,玩家发送消息”如果您需要任何特殊的服务器端逻辑,那么您可以使用不同的代码将它们实现为自己的操作。如果不是这种情况,那么您将使用 opRaiseEvent() 发送这些信息,但您仍将为这 3 个中的每一个指定不同的 eventCode。但是,操作和 eventCodes 旨在用于区分不同类型的信息,就像聊天消息,捡起一个命中,位置更新等。所以玩家a告诉玩家b他已经击中了玩家c,而玩家b告诉玩家d,他已经击中了玩家d,都将使用相同的代码。关于哪个玩家被击中的信息 - 就像它被击中的强度或使用哪种武器一样 - 属于操作的有效载荷。

于 2012-07-25T15:36:00.627 回答