【问题标题】:Photon Server newbie questions光子服务器新手问题
【发布时间】:2012-06-05 03:19:34
【问题描述】:

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

来了……

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

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

当我觉得它已经准备好发布时,我会发布它的工作示例,但是现在,对于我的实际问题..(抱歉,我的帖子很长,我必须解释我所知道的以及到目前为止我所拥有的):

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

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

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

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

所以..现在我想明白了,但他们让我更加困惑。

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

希望我说得有道理。

非常感谢大家,至少,如果有帮助,请花时间!

【问题讨论】:

    标签: c# unity3d photon


    【解决方案1】:

    1) 频道是一个完全不同的话题,与区分你想要触发的不同类型的游戏逻辑无关。相反,通道用于确定优先级并声明一个操作是否依赖于另一个操作。

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

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

    2) 操作和事件都是消息。实际上有三种类型的消息:operationRequest、operationResponse 和 event。

    一) 客户端可以通过 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,都将使用相同的代码。关于哪个玩家被击中的信息 - 就像它被击中的强度或使用哪种武器一样 - 属于操作的有效载荷。因此,例如,您可以将被击中的玩家的玩家 ID、弹药类型以及他失去的生命能量作为有效载荷传递给 opRaiseEvent() 或 opCustom()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多