独立游戏前后端一体化解决方案 · 独立游戏开发者的圆梦大使
📖 文档 · 🚀 快速开始 · 💬 QQ群: 467608841
🌐 语言: English | 简体中文 | 繁體中文 | 日本語 | 한국어
GameFrameX Server 是基于 C# .NET 10.0 开发的高性能游戏服务器框架,采用 Actor 模型设计,支持热更新机制。框架将持久化状态与业务逻辑严格分离,专为多人在线游戏场景设计。
设计理念:大道至简,以简化繁
- Actor 模型 — 基于 TPL DataFlow 的无锁高并发架构,通过消息传递避免传统锁竞争
- 状态-逻辑分离 — 持久化数据(Apps 层)与可热更业务逻辑(Hotfix 层)严格分离
- 零停机热更新 — 运行时替换业务逻辑程序集,无需重启服务器
- 多协议网络 — 支持 TCP、WebSocket、HTTP 协议,内置消息编解码与压缩
- MongoDB 持久化 — 基于 CacheState 的透明 ORM 映射,自动序列化/反序列化
- 源码生成器 — 基于 Roslyn 的 Agent 代码生成,自动处理 Actor 消息队列调度
- 配置表系统 — 集成 Luban 配置生成,支持 JSON 热加载
- OpenTelemetry — 内置 Prometheus 指标导出、健康检查、性能监控
┌──────────────────────────────────────────────────────────────┐
│ 客户端层 │
├──────────────────────────────────────────────────────────────┤
│ 网络层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ TCP │ │WebSocket │ │ HTTP │ │ KCP │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────────────────────────┤
│ Hotfix 层(可热更) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ ComponentAgent │ HttpHandler │ EventHandler │ │
│ └──────────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ Apps 层(不可热更) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ State │ │Component │ │ActorType │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────────────────────────┤
│ 框架层(NuGet 包) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Core │ │ NetWork │ │ DataBase │ │ Monitor │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├──────────────────────────────────────────────────────────────┤
│ 数据库层 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MongoDB │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
| 依赖 | 版本要求 |
|---|---|
| .NET SDK | 10.0+ |
| MongoDB | 4.x+ |
| IDE | Visual Studio 2022 / JetBrains Rider / VS Code |
# 1. 克隆仓库
git clone https://github.com/GameFrameX/Server_main.git
cd Server_main
# 2. 还原依赖
dotnet restore
# 3. 构建
dotnet build
# 4. 运行游戏服务器
dotnet run --project GameFrameX.Launcher \
--ServerType=Game \
--ServerId=1000 \
--APMPort=29090| 端点 | 地址 | 说明 |
|---|---|---|
| 健康检查 | http://localhost:29090/health |
服务健康状态 |
| 指标监控 | http://localhost:29090/metrics |
Prometheus 指标 |
| 测试接口 | http://localhost:28080/game/api/test |
HTTP 连通性测试 |
Server_main/
├── GameFrameX.Launcher/ # 应用入口点(可执行程序)
│ ├── Program.cs # 启动引导:注册状态类型与协议消息
│ └── StartUp/
│ └── AppStartUpGame.cs # 游戏服务器启动流程
│
├── GameFrameX.Hotfix/ # 热更新层(业务逻辑,可运行时替换)
│ ├── Logic/
│ │ ├── Http/ # HTTP 请求处理器
│ │ │ ├── TestHttpHandler.cs
│ │ │ ├── ReloadHttpHandler.cs
│ │ │ ├── Player/ # 账户登录、在线查询
│ │ │ └── Bag/ # 道具发放
│ │ ├── Player/
│ │ │ ├── Bag/ # 背包组件代理
│ │ │ ├── Login/ # 登录/登出逻辑
│ │ │ └── Pet/ # 宠物组件代理
│ │ ├── Account/ # 账号组件代理
│ │ └── Server/ # 服务器全局组件代理
│ └── StartUp/ # 热更新启动流程
│ ├── AppStartUpHotfixGameByEntry.cs # 加载入口
│ ├── AppStartUpHotfixGameByMain.cs # 网络/连接管理
│ ├── AppStartUpHotfixGameByHeart.cs # 心跳处理
│ └── AppStartUpHotfixGameByGateWay.cs # 网关通信
│
├── GameFrameX.Apps/ # 应用状态层(不可热更)
│ ├── ActorType.cs # Actor 类型枚举定义
│ ├── Account/Login/ # 登录状态 + 组件
│ ├── Player/
│ │ ├── Bag/ # 背包状态 + 组件
│ │ ├── Player/ # 玩家状态 + 组件
│ │ └── Pet/ # 宠物状态 + 组件
│ ├── Server/ # 服务器全局状态 + 组件
│ └── Common/
│ ├── Session/ # 会话管理(SessionManager)
│ ├── Event/ # 事件 ID 定义
│ └── EventData/ # 事件参数
│
├── GameFrameX.Config/ # 配置表系统(Luban 生成)
│ ├── ConfigComponent.cs # 配置加载单例
│ ├── Tables/ # 生成的配置表类
│ ├── TablesItem/ # 配置数据模型
│ └── json/ # JSON 配置数据文件
│
├── GameFrameX.Proto/ # 网络协议定义
│ ├── Basic_10.cs # 基础协议(心跳等)
│ ├── Bag_100.cs # 背包协议
│ ├── User_300.cs # 用户/账号协议
│ └── BuiltIn/ # 内置系统协议
│
├── GameFrameX.CodeGenerator/ # Roslyn 源码生成器
│ ├── AgentGenerator.cs # Agent 包装代码生成
│ └── AgentTemplate.cs # 代码模板
│
├── Server.sln # Visual Studio 解决方案
├── Dockerfile # Docker 多阶段构建
├── docker-compose.yml # Docker Compose 编排
└── LICENSE # MIT + Apache 2.0 双许可证
GameFrameX 采用三层分离的开发模式,确保业务逻辑可以在不停服的情况下热更新。
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ State │────▶│ Component │◀────│ ComponentAgent│
│ (数据定义) │ │ (组件外壳) │ │ (业务逻辑) │
│ Apps 层 │ │ Apps 层 │ │ Hotfix 层 │
│ 不可热更 │ │ 不可热更 │ │ 可热更 │
└──────────────┘ └──────────────┘ └──────────────┘
继承 CacheState,定义持久化数据结构。框架自动处理 MongoDB 序列化。
// GameFrameX.Apps/Player/Bag/Entity/BagState.cs
public sealed class BagState : CacheState
{
public Dictionary<int, BagItemState> List { get; set; } = new();
}
public sealed class BagItemState
{
public long ItemId { get; set; }
public long Count { get; set; }
}继承 StateComponent<TState>,作为状态和逻辑的桥梁。
// GameFrameX.Apps/Player/Bag/Component/BagComponent.cs
[ComponentType(GlobalConst.ActorTypePlayer)]
public class BagComponent : StateComponent<BagState> { }继承 StateComponentAgent<TComponent, TState>,编写可热更的业务代码。
// GameFrameX.Hotfix/Logic/Player/Bag/BagComponentAgent.cs
public class BagComponentAgent : StateComponentAgent<BagComponent, BagState>
{
public async Task OnAddBagItem(INetWorkChannel netWorkChannel,
ReqAddItem message, RespAddItem response)
{
// 校验物品配置是否存在
foreach (var item in message.ItemDic)
{
if (!ConfigComponent.Instance.GetConfig<TbItemConfig>()
.TryGet(item.Key, out var _))
{
response.ErrorCode = (int)OperationStatusCode.NotFound;
return;
}
}
await UpdateChanged(netWorkChannel, message.ItemDic);
}
public async Task<BagState> UpdateChanged(INetWorkChannel netWorkChannel,
Dictionary<int, long> itemDic)
{
var bagState = OwnerComponent.State;
var notify = new NotifyBagInfoChanged();
foreach (var item in itemDic)
{
if (bagState.List.TryGetValue(item.Key, out var value))
{
value.Count += item.Value;
}
else
{
bagState.List[item.Key] = new BagItemState
{
Count = item.Value, ItemId = item.Key
};
}
}
await netWorkChannel.WriteAsync(notify);
await OwnerComponent.WriteStateAsync(); // 自动持久化到 MongoDB
return bagState;
}
}继承 BaseHttpHandler,使用 [HttpMessageMapping] 注册路由。
// GameFrameX.Hotfix/Logic/Http/TestHttpHandler.cs
[HttpMessageMapping(typeof(TestHttpHandler))]
[HttpMessageResponse(typeof(HttpTestResponse))]
[Description("测试通讯接口")]
public sealed class TestHttpHandler : BaseHttpHandler
{
public override Task<string> Action(string ip, string url,
Dictionary<string, object> parameters)
{
var response = new HttpTestResponse { Message = "hello" };
return Task.FromResult(HttpJsonResult.SuccessString(response));
}
}框架提供两种 RPC 处理器基类,自动注入 ComponentAgent:
// 玩家级别消息(绑定特定玩家 Actor)
[MessageMapping(typeof(ReqAddItem))]
internal sealed class AddItemHandler
: PlayerRpcComponentHandler<BagComponentAgent, ReqAddItem, RespAddItem>
{
protected override async Task ActionAsync(ReqAddItem request, RespAddItem response)
{
await ComponentAgent.OnAddBagItem(NetWorkChannel, request, response);
}
}
// 全局级别消息(绑定服务器 Actor)
[MessageMapping(typeof(ReqHeartBeat))]
internal sealed class HeartBeatHandler
: GlobalRpcComponentHandler<ServerComponentAgent, ReqHeartBeat, RespHeartBeat>
{
protected override Task ActionAsync(ReqHeartBeat request, RespHeartBeat response)
{
return Task.CompletedTask;
}
}使用 [Event] 特性绑定事件 ID,框架自动分发给对应的 ComponentAgent。
[Event(EventId.PlayerLogin)]
internal sealed class PlayerLoginEventHandler : EventListener<PlayerComponentAgent>
{
protected override Task HandleEvent(PlayerComponentAgent agent, GameEventArgs args)
{
return agent.OnLogin();
}
}使用 Roslyn 源码生成器自动处理 Actor 消息队列调度。通过特性标注控制调用行为:
| 特性 | 说明 | 适用场景 |
|---|---|---|
[Service] |
默认模式,方法调用进入 Actor 消息队列排队执行 | 所有业务方法 |
[ThreadSafe] |
跳过消息队列,直接调用(要求方法线程安全) | 纯读操作、无状态计算 |
[Discard] |
即发即弃,不等待返回值 | 日志、统计等不需要结果的场景 |
[TimeOut(ms)] |
为消息队列调用设置超时时间 | 需要超时控制的长操作 |
public class ServerComponentAgent : StateComponentAgent<ServerComponent, ServerState>
{
// 进入 Actor 消息队列排队执行
[Service]
public virtual Task<bool> IsOnline(long roleId) { ... }
// 跳过消息队列,线程安全直接调用
[Service]
[ThreadSafe]
public virtual long FirstStartTime()
{
return State.FirstStartTime;
}
// 即发即弃,不阻塞调用方
[Service]
[Discard]
public virtual ValueTask AddOnlineRole(long roleId)
{
OwnerComponent.OnlineSet.Add(roleId);
return ValueTask.CompletedTask;
}
}使用 ConfigComponent 单例访问 Luban 生成的配置表:
var config = ConfigComponent.Instance.GetConfig<TbItemConfig>();
// 使用 TryGet 安全查询
if (config.TryGet(itemId, out var itemConfig))
{
// 使用 itemConfig.Name, itemConfig.Type 等
}通过 GameDb 静态类进行 MongoDB CRUD 操作:
// 查询
var state = await GameDb.FindAsync<LoginState>(
m => m.UserName == userName && m.Password == password);
// 新增/更新
await GameDb.AddOrUpdateAsync(loginState);
// 列表查询
var list = await GameDb.FindListAsync<LoginState>(m => m.Id != 0);
// 删除
var count = await GameDb.DeleteAsync(state);热更新系统允许在不停服的情况下替换业务逻辑。
- Apps 层(
GameFrameX.Apps):包含状态定义和组件外壳,不可热更 - Hotfix 层(
GameFrameX.Hotfix):包含所有业务逻辑,可热更 - Hotfix 程序集输出到
hotfix/目录,运行时由HotfixManager加载
# 通过 HTTP 接口触发(指定版本号)
curl "http://localhost:28080/game/api/Reload?version=1.0.1"| 配置项 | 说明 | 默认值 | 示例 |
|---|---|---|---|
ServerType |
服务器类型 | — | Game |
ServerId |
服务器唯一标识 | — | 1000 |
InnerPort |
TCP 内部通信端口 | — | 29100 |
HttpPort |
HTTP 服务端口 | 0 |
28080 |
WsPort |
WebSocket 服务端口 | 0 |
29110 |
MetricsPort |
Prometheus 指标端口 | 0 |
29090 |
DataBaseUrl |
MongoDB 连接字符串 | — | mongodb://localhost:27017 |
DataBaseName |
数据库名称 | — | gameframex |
dotnet GameFrameX.Launcher.dll \
--ServerType=Game \
--ServerId=1000 \
--InnerPort=29100 \
--HttpPort=28080 \
--WsPort=29110 \
--MetricsPort=29090 \
--DataBaseUrl=mongodb://127.0.0.1:27017 \
--DataBaseName=game_dbdocker-compose up --build| 端口 | 协议 | 说明 |
|---|---|---|
29090 |
HTTP | APM 指标 / 健康检查 |
29100 |
TCP | 游戏客户端连接 |
29110 |
WebSocket | WebSocket 连接 |
28080 |
HTTP | HTTP API |
消息 ID 由模块 ID 位移计算:(moduleId << 16) + seqId
| 模块 | ID 范围 | 文件 | 说明 |
|---|---|---|---|
| 系统 | -10 ~ -1 | Player_-10.cs, Service_-3.cs |
内置系统协议 |
| 基础 | 10 | Basic_10.cs |
心跳、服务器就绪通知 |
| 背包 | 100 | Bag_100.cs |
物品增删改查、使用、合成 |
| 用户 | 300 | User_300.cs |
登录、注册、角色列表 |
| 组件 | 技术 |
|---|---|
| 运行时 | .NET 10.0 |
| 数据库 | MongoDB |
| 网络框架 | SuperSocket |
| 序列化 | protobuf-net |
| 配置生成 | Luban |
| 代码生成 | Roslyn Source Generator |
| 监控 | OpenTelemetry + Prometheus |
| 对象映射 | Mapster |
| 容器化 | Docker + Docker Compose |
- Fork 本仓库
- 创建功能分支(
git checkout -b feature/amazing-feature) - 提交更改(
git commit -m 'feat: 添加某个功能') - 推送到分支(
git push origin feature/amazing-feature) - 创建 Pull Request
本项目采用 MIT License 和 Apache License 2.0 双许可证分发。详见 LICENSE 文件。
