尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

深入解析:【Unity】uNet游戏服务端框架(一)服务端架构设计

深入解析:【Unity】uNet游戏服务端框架(一)服务端架构设计
📅 发布时间:2026/6/22 5:01:25

更新日期:2025年10月9日。
项目源码:获取源码。

索引

  • uNet游戏服务端框架
    • 一、uNet源码结构
    • 二、uNet架构设计
      • 1.网络玩家 NetworkPlayer
      • 2.网络实体 NetworkEntity
      • 3.网络地图 NetworkMap
      • 4.网络房间 NetworkRoom
      • 5.启动服务端

uNet游戏服务端框架

uNet游戏服务端框架为使用.Net Core开发的高性能、高并发网络游戏服务端框架,基于async / await的多线程架构天然适应IO高并发环境,使用Protobuf进行网络数据交换能够极大的降低带宽和网络延迟,同时使用对象池技术管理服务端中的大多数实例能够显著的降低GC开销。

一、uNet源码结构

在uNet解决方案目录中,存在4个项目:

在这里插入图片描述

uNet.Core:uNet框架的核心代码模块。
uNet.Engine:uNet框架中与Unity引擎进行同步交互的功能实现模块。
uNet.Example.ChineseChess:中国象棋的游戏服务端。
uNet.Example.MMO:MMORPG的游戏服务端。

二、uNet架构设计

在uNet中,将一个游戏服务端程序中可能出现的所有实例划分为了如下的四类:

类型描述
网络玩家代表网络中的玩家客户端实例
网络实体代表存在于地图、房间中的具备网络同步需求的实体(比如NPC、副本中的BOSS)
网络地图代表可同时容纳大量玩家、大量实体的游戏场景(也即是游戏中的主城)
网络房间代表可同时容纳少量玩家、少量实体的游戏场景(也即是游戏中的副本)

1.网络玩家 NetworkPlayer

网络玩家由NetworkPlayer类表示,一个NetworkPlayer实例即代表了存在于当前服务器中的一名玩家客户端,他的基础属性如下:

/// <summary>/// 网络玩家
/// </summary>
public abstract class NetworkPlayer : IObjectPoolable
{
/// <summary>/// 玩家的ID
/// </summary>
public long ID { get; private set; }
/// <summary>/// 玩家姓名
/// </summary>
public string? Name { get; protected set; }
/// <summary>/// 在本次同步中是否已改变
/// </summary>
public bool IsDirty { get; set; } = false;
/// <summary>/// 心跳包校验码
/// </summary>
public abstract int HEARTBEAT { get; }
/// <summary>/// 常规信息校验码
/// </summary>
public abstract int NORMAL { get; }
//........
}

ID:玩家的ID,玩家在当前游戏服务器中的唯一标识符,重新登录后会改变。
Name:玩家的姓名。
IsDirty:在本次同步中是否已改变,在执行网络同步时,只有标记为改变的玩家才会被同步。
HEARTBEAT:心跳包校验码,在心跳机制中,用于鉴别心跳包的校验码。
NORMAL:常规信息校验码,区别于心跳包的常规信息数据包的校验码。

由于NetworkPlayer兼顾了与客户端进行双向通信的使命,所以他自身具备了区别心跳包和常规信息数据包的能力。

在NetworkPlayer中已封装了用于收、发数据的相关方法(使用Socket收、发),直接调用即可:

/// <summary>/// 发送数据到客户端
/// </summary>
/// <param name="bytes">数据内容</param>
/// <param name="token">用于取消异步的token</param>
/// <returns>是否发送成功</returns>
protected async Task<bool> SendDataAsync(byte[]? bytes, CancellationToken token){//代码后续讲解......}/// <summary>/// 从客户端接收数据/// </summary>
/// <param name="token">用于取消异步的token</param>
/// <returns>网络消息</returns>protected async Task<NetworkMessage?> ReceiveDataAsync(CancellationToken token){//代码后续讲解......}

2.网络实体 NetworkEntity

网络实体由NetworkEntity类表示,除了玩家以外的,存在于地图或副本中的其他需要进行网络同步的实例,都统称为网络实体。

比如副本中的小怪和BOSS,他们需要进行网络同步,以在不同的玩家客户端中表现为相同状态(比如相同的血量,相同的攻击姿态),所以他们是网络实体。

但某些NPC,站在原地不动,玩家仅仅能点击他进行对话或接受任务,他们不需要进行网络同步,所以他们不是网络实体。

NetworkEntity的基础属性如下:

/// <summary>/// 网络实体
/// </summary>
public abstract class NetworkEntity : IObjectPoolable
{
/// <summary>/// 实体的ID
/// </summary>
public long ID { get; private set; }
/// <summary>/// 在本次同步中是否已改变
/// </summary>
public bool IsDirty { get; set; } = false;
/// <summary>/// 实体名称
/// </summary>
public abstract string Name { get; }
/// <summary>/// 实体类型
/// </summary>
public abstract string Type { get; }
//......
}

ID:实体的ID,实体在当前地图或副本中的唯一标识符,不同类型的实体可能重复。
IsDirty:在本次同步中是否已改变,在执行网络同步时,只有标记为改变的实体才会被同步。
Name:实体的名称,同一类型的实体,他们一般具有相同的名称。
Type:实体的类型,用于在网络环境中区分实体(比如服务端的某个实体Type为Enemy,客户端的相同实体的Type也应该为Enemy,确保在网络同步时能够正确定位到该实体)。

3.网络地图 NetworkMap

网络地图由NetworkMap类表示,一个NetworkMap实例即代表了存在于当前服务器中的一个地图场景,在地图中可容纳大量玩家或实体,玩家与实体之间产生交互并经过网络同步,最终完成一整套的游戏玩法。

交互
交互
收集状态数据
收集状态数据
状态同步
状态同步
玩家
实体
地图

他的基础属性如下:

/// <summary>/// 网络地图(用于容纳大量网络玩家和大量网络实体)
/// </summary>
public abstract class NetworkMap : IObjectPoolable
{
/// <summary>/// 地图名称
/// </summary>
public abstract string Name { get; }
/// <summary>/// 地图类型
/// </summary>
public abstract string Type { get; }
/// <summary>/// 执行网络同步的间隔时间(毫秒)
/// </summary>
public abstract int SyncInterval { get; }
}

Name:地图的名称,同一类型的地图,他们一般具有相同的名称,且地图实例本身就是唯一的。
Type:地图的类型,用于在网络环境中区分地图(比如服务端的某个地图Type为Map1,客户端的相同地图的Type也应该为Map1,确保在网络同步时能够正确定位到该地图)。
SyncInterval:执行网络同步的间隔时间(毫秒),地图拥有自动对其中的玩家和实体进行网络同步的功能,此为2次同步之间的间隔时间,设置得越低同步频率越高,但同时服务端压力也越大,可能导致网络延迟卡顿。

注:通常情况下,地图的同步间隔时间可以设置较长,以降低性能开销。

4.网络房间 NetworkRoom

网络房间由NetworkRoom类表示,一个NetworkRoom实例即代表了存在于当前服务器中的一个房间场景,在房间中可容纳少量玩家或实体,玩家与实体之间产生交互并经过网络同步,最终完成一整套的游戏玩法。

交互
交互
收集状态数据
收集状态数据
状态同步
状态同步
玩家
实体
房间

由于同一类型的NetworkRoom是可以创建多个的,所以他们在大多数时候也被叫做副本。

他的基础属性如下:

/// <summary>/// 网络房间(用于容纳少量网络玩家和少量网络实体)
/// </summary>
public abstract class NetworkRoom : IObjectPoolable
{
/// <summary>/// 房间ID
/// </summary>
public long ID { get; private set; }
/// <summary>/// 房间名称
/// </summary>
public abstract string Name { get; }
/// <summary>/// 房间类型
/// </summary>
public abstract string Type { get; }
/// <summary>/// 执行网络同步的间隔时间(毫秒)
/// </summary>
public abstract int SyncInterval { get; }
}

ID:房间的ID,在当前服务器中的唯一标识符,不同类型的房间可能重复。
Name:房间的名称,同一类型的房间,他们一般具有相同的名称。
Type:房间的类型,用于在网络环境中区分房间(比如服务端的某个房间Type为Room1,客户端的相同房间的Type也应该为Room1,确保在网络同步时能够正确定位到该房间)。
SyncInterval:执行网络同步的间隔时间(毫秒),房间拥有自动对其中的玩家和实体进行网络同步的功能,此为2次同步之间的间隔时间,设置得越低同步频率越高,但同时服务端压力也越大,可能导致网络延迟卡顿。

注:通常情况下,房间的同步间隔时间可以设置较短,以带来更流畅的体验。

uNet的网络同步采用的是状态同步的方式,而网络同步的时机为固定频率同步,这不一定适合所有游戏,只是我们本系列教程所采用的方式,当然,其他方式(比如帧同步)后续可能也会考虑。

5.启动服务端

启动服务端的话将非常简单,比如通过查看MMORPG的服务端入口函数Main,将看到极简的代码:

namespace uNet.Example.MMO
{
class Program
{
static void Main(string[] args)
{
//定义服务端配置信息,比如监听的IP地址、端口号,玩家类型(继承至NetworkPlayer,同一游戏服务端中只能存在一种玩家类型)
ServerConfig config = new ServerConfig("127.0.0.1", 11000, typeof(MMO_Player), 10, 20);
//创建服务端入口
ServerEntry entry = new ServerEntry(config);
//创建一个地图(比如这里是初始地图:暴风要塞)
entry.CreateMap<MMO_BeginnerMap>();//启动服务端entry.Start();//启用常规日志的打印显示Log.IsEnableInfo = true;//按下ESC键退出程序ConsoleKeyInfo consoleKeyInfo = Console.ReadKey();while (consoleKeyInfo.Key != ConsoleKey.Escape){consoleKeyInfo = Console.ReadKey();}}}}

服务端为控制台程序,启动完成后如下:

在这里插入图片描述

相关新闻

  • 2025年上海装修设计标杆公司最新推荐:中古风装修/轻法式装修/现代简约装修/极简风装修、上海千祥建筑定义品质居住新标准
  • 清理docker的overlay2目录
  • 中电金信​​:「AI智变」这个AI自动化工厂,助力模型高质效落地

最新新闻

  • 嵌入式调试器环境变量配置:路径搜索原理与实战管理指南
  • Web安全实战:深入理解CSRF攻击原理与四层立体化防御体系
  • 电动车托运全攻略:跨省带电池寄运合规方法 - 快递物流资讯
  • 2026年宁波余姚装修公司推荐榜:这5家口碑排名最可靠 - 米諾
  • 从”词元出海”到”认知变现”: 我用七境体系, 把Token经济翻译成普通人能懂的知识产品
  • 2026年宁波本地装饰公司推荐与装修避坑实用指南 - 资讯快报

日新闻

  • 2026速览惠州叛逆青少年学校前十大排名名单出炉 - 武汉中职最新信息发布
  • 2026上饶白蚁消杀哪家好?15年本土2大权威白蚁防治公司推荐(金盾虫控/青蚁卫士) - 我叫一
  • 天龙八部单机版终极数据管理工具:5个技巧快速掌握游戏数据编辑

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号