在Unity中制作非单机项目常用的免费网络框架,这里选取了三款比较火的网络框架,Mirror、FishNet和Netcode for GameObject(NGO)。
比较了最常用的免费网络解决方案。可能还有值得探索的付费选项。您需要对此进行自己的研究。数据表格更新日志截止到: 2024/09/12
Mirror:点击跳转
FishNet:点击跳转
NGO:点击跳转
类别 | 特征 | Mirror | FishNet | NGO | 描述 |
General | Topology | Client-Server | Client-Server | Client-Server | 支持的的模式 |
General | Open Source Initiative | OSI | Other | OSI | 软件许可证已获得开放源代码促进会的批准。某些功能可能需要付费服务,甚至需要付费服务。 |
General | Source Available | Y | Y | Y | 源代码可公开免费获取。 |
General | Long-Term Support | N | Y | N | 长期支持通过从新版本中修复错误并将其包含到旧 LTS 版本中来确保框架的稳定性。 |
General | Roadmap | Y | Y | Y | 路线图有助于了解计划中的功能变更,有时还会附带预计到达时间 (ETA)。 |
General | Update Stability | N | Y | N | 允许安全地应用更新,而无需由于网络解决方案内的变化而重构代码。 |
General | API Design | Singleton | Instanced | Singleton | 实例化 API 可让单个可执行文件充当多个服务器,或让客户端同时连接到多个服务器。单例 API 仅允许每个可执行文件运行一个解决方案核心实例。 |
General | Dedicated Server | Y | Y | Y | 是否可以进行专用服务器构建,通过将构建目标设置为“专用服务器”(Unity 中的内置平台目标)。 |
General | Authority | Server | Server | Server | 客户端或服务器是否对游戏具有权限。反作弊需要服务器权限。拥有服务器权限并不一定意味着框架不支持客户端权限。 |
General | Listen Server (Host) | Y | Y | Y | 是否任何人都可以在玩游戏时为其他人主持游戏。主持玩家具有延迟优势,并且更容易作弊。不建议在真正的竞技游戏中主持,但适合与朋友一起玩或合作游戏。 |
Connection | Connection Approval | Y | Y | Y | 服务器可以选择在允许连接继续之前验证连接尝试。 |
Connection | Allocation Free Transports | N | Y | Y | 拥有免费分配的传输可以确保更少的垃圾收集和显著更好的扩展。 |
Connection | WebSocket Transport | Y | Y | Y | 允许 WebGL 构建作为客户端连接,但由于 WebSockets 而存在额外的延迟。注意:由于平台的技术限制,WebGL 构建通常不能作为服务器或主机。 |
Connection | Steam Transport | Y | Y | Y | 允许通过 Steam 网络玩游戏。 |
Connection | Unity Transport | N | Y | Y | 允许通过 Unity 传输和服务玩游戏。 |
Connection | Epic Transport | Y | Y | Y | 允许通过 Epic 在线服务网络玩游戏。 |
Connection | Oculus Transport | N | N | N | 支持使用 Mata 网络服务。 |
Connection | Photon Transport | N | Y | Y | 支持使用 Photon 网络服务。 |
Connection | Offline Transport (Single Player) | N | Y (Paid) | N | 允许离线玩游戏,无需互联网连接。 |
Connection | Multiplex Transport | Y | Y | Y | 允许服务器处理来自不同传输或平台类型的客户端连接。 |
Messaging | Runtime RPC Settings | N | Y | N | 允许在运行时通过代码更改 RPC 的使用或设置,例如:可靠变为不可靠,TargetRpc 变为 ObserversRpc。 |
Messaging | Reliable RPCs | Y | Y | Y | RPC 将按照发送的顺序接收和运行。 |
Messaging | Unreliable RPCs | Y | Y | Y | 发送的 RPC 不可靠,可能永远不会到达,或者无序到达。 |
Messaging | Broadcast RPCs | L | Y | Y | 多个对象脚本可以实现并运行广播 RPC 方法,而不仅仅是发送 RPC 的脚本。 |
Messaging | Local RPCs | N | Y | N | 除了远程执行外,RPC 还可以在本地执行。 |
Messaging | Buffered RPCs | N | Y | N | RPC 可以自动获取自新加入的客户端以来的最新值。 |
Messaging | Client-to-Client RPCs | N | N | Y | 允许通过一次方法调用在客户端之间发送 RPC。注意:这仍然可以通过发送 ServerRpc 来实现,然后 ServerRpc 会中继到一个或多个客户端;如果该过程不是由框架自动执行的,则不被视为开箱即用的支持。 |
Messaging | Large Packets | N | Y | N | 允许发送超出传输缓冲区大小的数据包而不会出现错误或丢失连接。这可确保所有传输类型均具有相同的传输体验。 |
Messaging | Data Batching | Y | Y | Y | 将数据合并成尽可能少的数据包,以实现更高效的网络和更好的性能。 |
Synchronization | Value-Type Variables | Y | Y | Y | 同步值类型。 |
Synchronization | Nullable-Type Variables | L | Y | N | 同步可空类型。 |
Synchronization | Custom type serialization | Y | Y | Y | 允许开发人员控制使用类型序列化的数据。 |
Synchronization | Automatic type serialization | Y | Y | N | 网络解决方案可以自动为非标准类型(例如自定义类)创建序列化器。 |
Synchronization | Custom Collections / Types | Y | Y | Y | 允许创建作为序列化逻辑容器的自定义类型。 |
Synchronization | Fields | Y | Y | Y | 允许单个变量类型同步。 |
Synchronization | Timers | N | Y | N | 允许有效地同步和管理服务器和客户端之间的倒计时器。 |
Synchronization | List Collection | Y | Y | Y | 允许有效地同步列表集合。 |
Synchronization | Dictionary Collection | Y | Y | N | 允许有效地同步字典集合。 |
Synchronization | Set Collection | Y | Y | N | 允许有效地同步集合,例如 HashSet。 |
GameObjects | Player Prefab Spawning | Y | Y | Y | 生成用于连接客户端的玩家预制件。 |
GameObjects | Auto Prefab Detection | N | Y | N | 避免必须手动管理可以作为网络对象生成的预制件列表。 |
GameObjects | Object Pooling | L | Y | L | 允许从对象池中生成网络对象,这通常会导致更快的生成和更少的垃圾分配。 |
GameObjects | Automatic Object Pooling | N | Y | N | 允许池化任何类型的网络对象,而无需编写自定义池化代码。 |
GameObjects | Offline Networked Objects | N | Y | N | 允许联网对象实例化而无需通过网络同步。这对于将同一预制件用于多种用途非常有用;例如可能需要或不需要联网的射弹基座。 |
GameObjects | Nested Network Behaviours | Y | Y | Y | 允许 NetworkBehaviour 脚本存在于网络对象的子对象上。 |
GameObjects | Nested Network Prefabs | N | Y | N | 允许联网对象(和预制件)存在于联网对象的子对象上。 |
GameObjects | Parent Spawning | N | Y | N | 允许网络对象在其他网络对象下生成。 |
GameObjects | Predicted Spawning | N | Y | N | 允许客户端生成或取消生成网络对象,而无需等待服务器完成操作。 |
GameObjects | Predicted Owner | N | Y | N | 允许客户端无需等待服务器完成更改即可取得对象的所有权。这样,客户端就可以立即使用需要所有权的对象,而不受延迟影响。 |
GameObjects | Runtime Parent Synchronization | N | Y | N | 在运行时同步父级变化,例如将玩家设置为移动平台的子级。 |
GameObjects | Synchronize Client Objects | N | Y | N | 允许客户端知道哪个客户端拥有某个对象,以及任何客户端拥有的所有对象。 |
GameObjects | Synchronize Transform | Y | Y | Y | 允许转换值通过网络同步。某些网络解决方案可能比其他解决方案占用更少的带宽。 |
GameObjects | Transform Interpolation | Y | Y | Y | 允许变换属性随着时间的推移朝着目标值进行线性插值,从而实现平滑移动。 |
GameObjects | Transform Extrapolation | N | Y (Paid) | N | 允许将变换线性外推至假定的未来值。这对于隐藏不规则延迟或数据包丢失非常有用。 |
GameObjects | Server Authoritative Transform | Y | Y | Y | 允许仅由服务器控制变换。根据客户端的延迟,移动会有延迟。这与客户端预测不同。 |
GameObjects | Client Authoritative Transform | Y | Y | Y | 允许客户端控制变换。没有延迟,但客户端可以轻松欺骗其移动。这与客户端预测不同。 |
GameObjects | Transform Prediction | N | Y | N | 允许轻松实现客户端对变换的预测。此功能对于必须防止作弊的快节奏游戏至关重要。这与刚体预测不同。 |
GameObjects | RigidBody Prediction | N | Y | N | 允许轻松实现刚体上的滑动侧预测。这还允许实时准确地与联网刚体进行交互;就像 Rocket League 一样。 |
GameObjects | Animator Synchronization | Y | Y | Y | 允许 Animator 状态通过网络同步。 |
GameObjects | Animator Interpolation | N | Y | N | 允许动画线性插入到最新值以确保平滑的混合树。 |
GameObjects | Server Authoritative Animation | Y | Y | Y | 允许动画仅由服务器控制。这将导致动画因延迟而延迟。 |
GameObjects | Client Authoritative Animation | Y | Y | Y | 允许客户端控制动画。这还允许立即更改客户端动画,并且还具有作弊能力。 |
Scenes | Scene Network Objects | Y | Y | Y | 允许在编辑时将联网对象放置在场景中。 |
Scenes | Additive Scenes | N | Y | N | 允许附加地加载多个场景。 |
Scenes | Stacked Scenes (instances) | N | Y | N | 允许在服务器上多次加载同一场景,在客户端上仅加载一次。单个服务器上实例化地下城的要求,意味着:并非所有客户端都需要位于同一场景中。 |
Scenes | Online/Offline Scenes | Y | Y | N | 根据客户端或服务器的本地连接状态,自动在单个离线或在线场景之间切换。 |
Scenes | Scene Hotloading | N | Y | N | 允许根据需要加载和卸载服务器和客户端上的场景。 |
Miscellaneous | Timing Architecture | Variable Rate | Tick or Variable | Tick | 客户端和服务器之间如何同步时间、状态或数据。 |
Area of Interest | Network Level of Detail | N | Y | N | 限制向玩家发送物体距离数据的频率,以减少服务器使用的带宽。 |
Area of Interest | Area of Interest | Y | Y | L | 通过条件控制哪些客户端可以看到哪些联网对象。 |
Area of Interest | Global Conditions | Y | Y | N | 允许各种管理员确定所有联网对象的状况。 |
Area of Interest | Individual Conditions | N | Y | N | 允许某些联网对象或预制件覆盖全局条件,或在其自身条件之外使用。 |
Area of Interest | Stacked Conditions | N | Y | N | 允许同时使用多个条件。例如:联网对象必须位于特定场景中,并且玩家必须在该对象 10 个单位范围内才能看到该对象。 |
Area of Interest | Included Conditions | Y | Y | N | 网络解决方案附带多种条件可供选择。 |
Area of Interest | Custom Conditions | Y | Y | L | 可以用最少的努力制定和实施自定义条件。 |
Utility | Lag Compensation | Y | Y (Paid) | N | 允许对撞机及时回滚,以实现准确的命中登记,而不管延迟如何。 |
Utility | Host migration | N | N | N | 注意:所有解决方案都应该可以进行自定义实现,但可能需要保持游戏状态,然后重新启动会话。 |
Utility | Addressables Support | N | Y | Y | 允许通过网络使用可寻址场景和对象。 |
Utility | Code Stripping | N | Y (Paid) | N | 从客户端版本中删除服务器代码,并从服务器版本中删除客户端代码。这有助于提高服务器安全性。 |
Utility | Server Discovery (LAN) | Y | Y | Y | 允许同一局域网内的设备一起玩。 |
Utility | Network Profiler | Y (Paid) | L | Y | 显示每个网络功能使用的带宽的详细信息。 |
Utility | Latency Simulator | Y | Y | Y | 允许模拟服务器和客户端的延迟、数据包丢失等。 |
Utility | Instance Dependency Injection | N | Y | N | 允许组件在网络解决方案中注册。这允许自定义系统或管理器与服务器或客户端实例关联。 |
主观分析
1. Mirror
优点:
- 易用性: Mirror 是 Unity 中非常流行的网络框架,它的接口和设计理念与旧版的 UNet 非常相似,因此很多 Unity 开发者容易上手。
- 活跃的社区: Mirror 拥有一个非常活跃的开发者社区,很多问题都可以在论坛或文档中找到解决方案。
- 文档完善: 提供了详细的文档和示例,适合新手入门。
- 性能好: 在小型到中型项目中,Mirror 的性能表现不错,支持可靠的网络通信。
- 开源: Mirror 是开源的,可以根据需要进行自定义修改。
缺点:
- 扩展性差: 尽管 Mirror 适合快速开发,但对于大型复杂的网络架构,可能会遇到扩展性的问题,特别是当你需要一些非常定制化的功能时。
- 不再官方支持: 虽然 Mirror 很流行,但它并不是 Unity 官方的解决方案,未来 Unity 会优先支持 Netcode for GameObject,这意味着 Mirror 可能会逐步被替代。
学习难易度:
- 中等: 由于其与 UNet 类似,熟悉 UNet 的开发者会觉得非常容易上手。对于初学者来说,Mirror 提供了简单易懂的示例代码,但需要一定的网络基础。
2. FishNet
优点:
- 性能优化: FishNet 在性能优化方面有一些独特的实现,特别是在高并发和大规模多人游戏中表现非常好。
- 高级功能: FishNet 提供了很多高级功能,如网络物体同步、分布式负载、客户端和服务器之间的数据压缩等。
- 灵活性: 比 Mirror 更加灵活,允许更深层次的自定义,适合对网络框架有更高要求的开发者。
- 现代设计: FishNet 是从头开始设计的,支持更高效的同步机制和架构,适合想要利用最新技术的开发者。
缺点:
- 文档不足: 相比 Mirror,FishNet 的文档和社区资源较少,这可能会增加学习的难度。
- 复杂性: 由于它包含了很多高级功能和配置选项,学习曲线相对较陡,特别是对于没有网络开发经验的开发者来说。
- 不如 Mirror 稳定: 在一些小型项目中可能不如 Mirror 稳定,且对某些网络情况的适应性较差。
学习难易度:
- 较难: FishNet 提供了很多灵活的配置和功能,但也因此增加了学习难度。如果没有较强的网络编程基础,可能需要一定的时间来熟悉它的使用。
3. Netcode for GameObject (NGO)
优点:
- Unity 官方支持: Netcode for GameObject 是 Unity 官方推荐的网络框架,长期来看它是最有可能持续更新和发展的框架。
- 与 Unity 紧密集成: 作为 Unity 官方的解决方案,它与 Unity 引擎紧密集成,未来的版本更新可能会提供更多的原生支持,减少兼容性问题。
- 现代化设计: 相比 UNet,NGO 引入了现代化的网络通信机制,支持高效的数据同步和可靠的网络连接。
- 文档和示例: Unity 官方为 NGO 提供了详尽的文档和教程,易于学习。
缺点:
- 功能相对基础: 相比 Mirror 和 FishNet,NGO 的一些功能还不够全面,特别是在自定义和高性能需求方面可能不如其他两个框架。
- 学习曲线: 由于 Unity 官方希望提供一个易于理解的框架,NGO 的学习曲线相对较低,但对于有特定需求的开发者,可能会感到功能不够灵活。
- 当前的生态较小: 虽然是官方框架,但相对于 Mirror 的用户群体和社区支持,NGO 目前的生态还在逐步发展中。
综合对比和长远推荐:
优先推荐:
- 长期发展角度: Netcode for GameObject (NGO) 作为 Unity 官方的网络框架,具有最强的长期发展潜力。它会随着 Unity 引擎的演进不断更新,并且官方会优先支持。考虑到 Unity 对 NGO 的投入,以及与 Unity 引擎的深度集成,学习 NGO 无疑是一个稳妥的选择,尤其是对于未来的项目。
适合中小型项目或快速开发:
- Mirror 依然是一个非常好的选择,尤其是对于需要快速开发和原型制作的项目。它已经非常成熟,并且有庞大的社区和文档支持。如果项目需要快速上线,且没有太复杂的网络需求,Mirror 仍然是不错的选择。
适合大规模、高性能需求的项目:
- FishNet 是适合那些对性能有更高要求,且能够投入时间去学习的开发者。如果你的项目需要处理大量的玩家、复杂的物体同步,或者你希望最大化利用最新的网络架构技术,FishNet 是一个值得深入了解的框架。
这些选择并非绝对,最终的决定取决于你的项目需求、团队技能以及未来的维护和扩展计划。
以上观点仅限个人,如有不同,还请评论区探讨。