这是一篇关于 Serious Engine 的技术文章,涵盖了其网络多玩家、消息层、游戏会话层等方面的内容,主要观点、关键信息和重要细节如下:
Overview(概述):
- Serious Sam 是一款从一开始就作为多人游戏构建的游戏,其游戏模式包括单人离线战役、多人在线、局域网或本地合作及各种游戏模式,还支持演示记录和回放。
- 演示功能:通过记录游戏状态和游戏流块来实现,游戏流块是描述游戏事件的消息,如玩家动作、添加或移除玩家等。
- 确定性游戏模型:为确保演示回放的准确性,引擎的游戏模型必须是完全确定性的,例如通过使用确定性的随机数生成器和浮点精度控制来避免不同运行时环境导致的同步问题。
- Tick vs. Frame(游戏逻辑周期与渲染帧率):游戏逻辑周期(Tick)与渲染帧率(Frame)解耦,渲染帧率可根据硬件和设置变化,而游戏逻辑速率固定为每秒 20 次,但通过插值实现了平滑的运动和动画效果。
Networked Multiplayer(网络多玩家):
- 网络模型:Serious Engine 的网络模型实际上是客户端 - 服务器模式,单个多人游戏会话中有一个服务器,客户端连接到服务器,服务器接收和处理消息并将相关信息转发给客户端。
数据包层(Packet Layer):
- 使用 UDP 协议,为实现可靠性和数据包排序,Croteam 在 UDP 之上实现了自己的自定义协议。
CPacket
结构用于表示数据包,通过序列号、可靠标志、重试次数等字段来管理数据包的发送和接收,可靠数据包通过确认机制实现重传。- 数据包的发送和接收通过不同的接口函数实现,包括服务器和客户端的发送与接收函数,以及广播接口。
- 建立连接时,客户端发送带有连接请求标志的可靠广播数据包,服务器接收后为客户端分配唯一标识符并发送响应。
消息层(Message Layer):
CNetworkMessage
是消息抽象,可通过简单的接口进行读写和操作,消息可以压缩和包含子消息。- 消息压缩采用 LZ77 或 LZRW1 等压缩算法,例如在发送玩家动作时使用增量编码来减少网络传输的数据量。
- 消息不加密,但聊天消息在未压缩时可通过 Wireshark 捕获到明文内容。
CMessageDispatcher
是数据包层的包装器,根据所选的网络提供程序(如本地、TCP/IP 服务器或客户端)进行准备和操作。
游戏会话层(Game Session Layer):
- 包括主机游戏、加入游戏、开始演示回放等功能,在主机游戏时服务器会初始化各种状态和参数,客户端加入游戏时会进行一系列的连接和状态同步操作。
- 游戏主循环在客户端和服务器中相似,但服务器有额外的处理,如处理 GameAgent 更新和远程管理命令。
- 预测机制用于减少网络延迟对游戏交互性的影响,通过预测玩家动作和使用预测器来模拟游戏状态的推进,但本地玩家和远程玩家的预测方式略有不同。
Conclusion and Additional Thoughts(结论和额外思考):
- 与 Doom 和 Quake 的比较:Serious Engine 的网络模型与 Doom 有些相似,都采用类似的客户端 - 服务器架构,但与 Quake 的客户端 - 服务器模式不同,Serious Engine 每个客户端都维护自己的游戏状态。
- 消息可移植性:在开发过程中,由于使用单一编译器和平台,一些与结构布局和字节序相关的问题没有显现,但在跨平台开发中可能会成为问题。
- 最终思考:Serious Engine 的架构在多种游戏模式下考虑周全,虽然存在作弊的可能性,但主要用于合作模式。文章作者认为深入研究他人的代码是学习的好方法,并邀请读者关注其 Twitter 账号。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。