一、网络基础与架构选型:理解TCP/IP与UDP协议、状态同步与帧同步的区别、选择合适的网络库
做联机游戏,说白了就是解决「多个客户端怎么一起玩」的问题。我最早入行时,以为联机就是发几个数据包过去,结果第一个项目就栽了大跟头——玩家A看到B在左边,B看到自己在右边,两个人互相骂对方开挂。嗯,从那以后我才明白,网络基础不牢,地动山摇。
1.1 TCP/IP 与 UDP:两个老伙计,性格完全不同
先聊聊传输层这两个协议。TCP 和 UDP,就像快递里的「顺丰保价」和「平邮小包」。
TCP(传输控制协议):可靠、有序、但慢。它保证你发的每个包都能到达,而且顺序不乱。如果丢包了,它会重发。你想想看,这适合什么场景?聊天、登录、交易——这些数据丢一个都不行。
UDP(用户数据报协议):不可靠、无序、但快。它只管发,不管到没到。丢包了?丢了就丢了,不重发。这听起来很糙,但恰恰是实时游戏的命根子。
核心区别一句话总结:TCP 要脸,UDP 要命。要脸的意思是数据必须完整,要命的意思是延迟必须低。
我在项目中遇到过最典型的案例:一个 FPS 游戏用了 TCP,结果玩家开枪后子弹要等 200ms 才飞出去——因为前面有个登录验证的包堵住了。换成 UDP 后,延迟直接降到 30ms。当然,UDP 也有坑,后面会讲。
| 特性 | TCP | UDP |
|---|---|---|
| 可靠性 | 可靠,保证送达 | 不可靠,可能丢包 |
| 顺序性 | 保证顺序 | 不保证顺序 |
| 延迟 | 较高(重传机制) | 低(无重传) |
| 适用场景 | 登录、聊天、交易 | 位置同步、射击、动作 |
我的建议:不要非黑即白。很多成熟框架会在 UDP 之上自己实现「可靠通道」,只对关键数据做重传。比如位置包丢了就丢了,但开火指令必须可靠。
1.2 状态同步 vs 帧同步:两种思路,两种人生
聊完传输层,咱们说说游戏逻辑层的同步策略。这是架构选型前必须想清楚的问题。
状态同步:服务器说了算。客户端把操作发给服务器,服务器计算完结果,再把「最终状态」广播给所有人。你按了 W,服务器算出你往前走了一步,然后告诉所有人「这个玩家现在在 (1,0,0)」。
优点很明显:防作弊容易,逻辑都在服务器。缺点也明显:服务器压力大,延迟高——你按了键,要等服务器回包才能看到效果。
帧同步:各算各的。服务器只转发「操作指令」,不负责计算。每个客户端收到所有人的指令后,各自跑一遍逻辑,保证结果一致。你按了 W,服务器告诉所有人「玩家A按了W」,然后每个客户端自己算出他走到 (1,0,0)。
优点:服务器负载低,响应快。缺点:防作弊难,逻辑必须完全确定(不能有随机数、浮点误差)。
怎么选? 我个人习惯:RTS、格斗游戏用帧同步;MMO、FPS 用状态同步。但这不是铁律。我记得有个项目做 MOBA,一开始用帧同步,结果每次版本更新都要处理「不同客户端计算结果不一致」的 bug,后来改成状态同步反而省心了。
| 对比维度 | 状态同步 | 帧同步 |
|---|---|---|
| 服务器职责 | 计算+广播 | 仅转发指令 |
| 客户端响应 | 有延迟(等服务器) | 即时(本地预测) |
| 防作弊 | 容易 | 困难 |
| 逻辑确定性 | 不要求 | 必须确定 |
| 典型游戏 | MMO、FPS | 格斗、RTS |
避坑指南:我曾经在一个帧同步项目里,因为用了 Mathf.Sin() 在不同平台上精度不同,导致两个客户端跑出完全不同的结果。排查了三天才发现。所以帧同步里,所有数学运算必须用定点数或者自己实现确定性的函数。
1.3 网络库选型:Mirror、Photon、Netcode 怎么挑?
选网络库,就像选武器。没有最好的,只有最合适的。我三个都用过,说说真实感受。
Mirror:开源、轻量、基于 UNET 的改进版。适合中小型项目,尤其是你想完全掌控网络层的时候。它不提供服务器托管,你得自己部署。优点是代码透明,出了问题能自己修。缺点是功能相对基础,没有高级的匹配、房间管理。
Photon:商业方案,提供全套服务。包括服务器托管、匹配、房间、云存储。你几乎不用写服务器代码,把逻辑挂上去就能跑。适合快速原型和中小团队。缺点是贵,而且你没法改底层——万一遇到性能瓶颈,只能干瞪眼。
Netcode for GameObjects(Unity 官方):Unity 亲儿子,2022 年后开始发力。集成了很多现代网络概念,比如 NetworkVariable、RPC、对象同步。优点是和 Unity 生态深度绑定,未来可期。缺点是还不够成熟,文档和社区资源相对少。
我的选型建议:
- 想学底层、做定制化项目 → Mirror
- 快速出产品、不想管服务器 → Photon
- 用 Unity 最新技术栈、愿意踩坑 → Netcode
我个人习惯是:教学和练手用 Mirror,因为它代码清晰,能让你理解网络本质。商业项目看情况,如果团队小、时间紧,Photon 是真香。至于 Netcode,我最近在用它做一个小 Demo,感觉越来越顺手了,但离生产级还有距离。
一个小技巧:不管你选哪个库,先把「心跳包」和「断线重连」做扎实。我见过太多项目,网络库选得花里胡哨,结果玩家一掉线就再也连不回来。基础功能永远比花哨特性重要。
小结
这一章我们聊了三个核心问题:TCP vs UDP 怎么选、状态同步 vs 帧同步怎么分、Mirror/Photon/Netcode 怎么挑。说白了,没有标准答案,只有权衡。你想想看,做联机游戏,本质上就是在「延迟、可靠性、开发成本」这三个角里找平衡点。
下一章,我们会动手搭建一个 Mirror 的基础框架,把理论落地成代码。到时候你会发现,很多概念其实没那么玄乎——跑起来就懂了。