我目前正在尝试为少数玩家(我认为少于 20 人)编写简单的快节奏游戏的多人游戏服务器(作为“作为实时客户端-服务器应用程序示例的简单多人游戏”任务的一部分)。我将 TCP 套接字用于需要保证交付的数据包(即:聊天消息、登录和注销请求、ping 数据包等),将 UDP 用于不一定需要交付的所有内容,因为只有最后一个通过的数据包是重要(即:用户输入、游戏世界和对象更新等)。
我应该在这里提一下,我的游戏世界是什么样子的。每个对象服务器端都有其 id、角色和所有者成员。Id 基本上是客户端的标识符,因此,一旦我向他们发送对象更新,他们就知道要更新哪个对象。Owner是关于对象所有者的信息,即:控制actor的玩家。一旦玩家失去连接/注销,我用它来删除孤立的对象。然而,大多数对象都将此值设置为 Server。最后角色决定对象对客户是否重要。这可以设置为 ServerSide(对于不需要复制到客户端的对象,因为它们仅用于服务器端游戏状态计算),RelevantToOwner(此对象仅复制到其所有者,即:玩家私人库存不需要复制给每个人),
当用户发送登录数据包时,我检查我是否有空闲插槽,如果有,那么我将世界复制给他(发送当前世界状态 - 每个没有将角色设置为 ServerSide 或 RelevantToList 的对象 - 除非客户端当然在列表中对于那个对象)。
然后在服务器游戏状态更新循环的每次迭代之后,我发送完全相同的东西 - 整个世界状态。
当用户发送注销数据包时,我将他从登录的客户端中删除,释放插槽,并从游戏世界中删除所有孤立对象(以该用户为所有者的对象)。
以下是我的问题:
- 这个模型适合实时多人游戏还是我做错了?
- 有没有办法减少初始世界复制后发送的数据包数量(即:仅更新自上次迭代以来状态发生变化的对象。我已经考虑过了,到目前为止我遇到了这种方法的一个巨大问题- 如果上一次迭代的 UDP 数据包丢失并且对象的状态在后续迭代中没有改变,则在播放器端不会更新对象。)
- 我如何将多个对象更新打包到一个数据包中(我目前正在发送一个效率低下且可能非常错误的对象/数据包。
- 有人可以给我指出一些简单的客户端/服务器游戏的工作示例(来源会很好),这样我就可以看到专业人士是如何做到的?C++ 或 C 会很好,但 Java / C# / Python 也很好。