波波技术栈
article

Nakama 游戏后端框架新手教程(零基础入门)

本文为零基础读者量身打造,系统讲解游戏后端的基本概念,并全面介绍开源框架 Nakama 的核心功能与架构。教程从环境搭建起步,逐步演示客户端注册登录、RPC 业务逻辑编写、实时对战 Match 实现、玩家数据存储及后台管理操作,帮助新手在 10 分钟内快速上手,并掌握构建游戏服务端的关键技能。

目录

  1. 先搞清楚:什么是游戏后端
  2. Nakama 是什么?
  3. 核心概念(大白话版)
  4. 10 分钟跑起来(官方一键启动)
  5. 客户端接入:注册与登录
  6. 开箱即用的功能(一行代码都不用写)
  7. 写自己的业务逻辑:RPC
  8. 实时对战:Match
  9. 玩家数据存储与通知
  10. 后台管理 Console
  11. 常见问题 FAQ
  12. 下一步怎么学

1. 先搞清楚:什么是游戏后端

玩一个游戏时,除了你看到的画面,背后还发生着很多事:

  • 你的账号存在哪?换了手机怎么找回来?
  • 排行榜上的分数是谁算的?
  • 好友列表、聊天消息存在哪?
  • 两个人对战,出招的顺序谁来定?

这些"玩家看不到、但必须有"的东西,都靠服务器来完成。服务器是一个 7×24 小时运行的程序,所有玩家的数据都由它统一管理。

问题在于:从零写一个服务器,要处理数据库、网络协议、并发、安全、防作弊、部署……工程量非常大,而且每个游戏都要重复做一遍。

游戏后端框架就是来解决这个问题的:它把每个游戏都需要的通用能力(账号、排行榜、聊天、存储、实时通信……)全部做好,你只需要写"你自己游戏的规则"(比如:石头剪刀布怎么判胜负、抽卡的概率是多少)。

类比:做网站时用现成框架(如 Django、Spring),而不是从零写 HTTP 服务器。游戏后端框架就是这个思路。

2. Nakama 是什么?

项 说明
是什么 开源的实时游戏服务器框架
用什么写的 Go(性能好、并发强)
谁维护的 Heroic Labs(官方文档完善,社区活跃)
收费吗 开源免费,可商用
官网 https://heroiclabs.com
文档 https://heroiclabs.com/docs

它内置了游戏后端几乎所有通用能力,开箱即用:

内置能力 大白话说明
账号体系 设备 ID、邮箱、微信、Steam、Facebook 等 20+ 种登录方式
好友 / 群组 加好友、建群、群公告
排行榜 / 赛季 自动算排名,支持按赛季重置
聊天 世界频道、房间、私聊
实时通信 WebSocket 长连接,实时收发消息
云存储 每个玩家的存档(金币、等级、道具)
匹配系统 把条件合适的玩家撮合进同一局
通知 给玩家发消息,离线也能补发
权威对战 判定在服务器,玩家无法作弊
内置后台 网页版管理界面,看玩家、看数据

最吸引人的一点:这些能力不需要你写一行代码,部署好服务器、调 API 就有。

3. 核心概念(大白话版)

概念 大白话解释
服务器 Server 一个运行中的程序,所有玩家都连它。就是你部署的 Nakama
客户端 Client 玩家的游戏本体(Unity/UE 做的 App、网页、手机游戏)
数据库 PostgreSQL Nakama 唯一依赖的数据库,账号、存档等所有数据都存这里
账号 Account 玩家的身份。用设备 ID、邮箱等方式登录后就有了
Token(令牌) 登录成功后服务器发的一张"通行证",之后每次请求带上它,服务器就知道你是谁
存储 Storage 每个玩家自己的键值数据(如金币=100、等级=5)
对局 Match 一场实时战斗(如一把王者荣耀、一局五子棋)
RPC 客户端能调用的"自定义接口"(如"领取每日奖励""查询战绩")
Console 网页版后台管理界面,不用写代码就能查数据、配排行榜

整体架构就一张图:

flowchart LR
    subgraph 玩家设备
        A[游戏客户端<br/>Unity / UE / 网页 / 手机]
    end
    subgraph 你的服务器
        S[Nakama 服务器<br/>7350 客户端API / 7349 gRPC / 7351 后台]
        DB[(PostgreSQL<br/>所有数据)]
    end
    A -- "HTTP / WebSocket" --> S
    S -- "读写数据" --> DB

记住一句话:客户端只跟 Nakama 说话,Nakama 负责存数据、跑逻辑、转发消息。

4. 10 分钟跑起来(官方一键启动)

这是最快的体验方式,不需要下载源码、不需要写代码,用官方提供的 Docker 配置直接启动。

4.1 唯一前提:装好 Docker

  • 到 https://www.docker.com 下载安装 Docker Desktop(Windows / macOS),Linux 装 docker-ce 即可
  • 安装后打开,确认 docker version 能正常输出版本号
  • 中国大陆用户建议先配置 Docker 镜像加速,否则拉取镜像会很慢

4.2 一键启动

官方仓库提供了开箱即用的 docker-compose.yml(包含 Nakama 服务器 + PostgreSQL 数据库):

# 1. 下载官方编排文件(也可以手动从 GitHub 复制)
curl.exe -o docker-compose.yml https://raw.githubusercontent.com/heroiclabs/nakama/master/docker-compose.yml

# 2. 启动(首次会自动拉镜像、初始化数据库,等 1~2 分钟)
docker compose up -d

4.3 怎么确认启动成功

# 两个容器都应该是 healthy 或 running
docker compose ps

# 打开后台,能看到登录页 = 成功
# 浏览器访问 http://127.0.0.1:7351

默认后台账号:admin,密码:password(本地开发用,生产环境必须改!)。

4.4 三个端口分别是什么

端口 用途 谁来用
7350 客户端 API(HTTP + WebSocket) 你的游戏客户端
7349 gRPC 接口 服务端程序
7351 Console 后台管理 你(开发者)

4.5 日常启停

docker compose up -d     # 启动
docker compose down      # 停止(数据保留在 docker volume 里)
docker compose logs -f nakama   # 看服务器日志(排查问题第一站)

5. 客户端接入:注册与登录

Nakama 的账号体系开箱即用。新手最常用的是设备登录:客户端生成一个唯一 ID(随便一个不重复的字符串即可,比如 device-1234567890),发给服务器,服务器自动注册并返回 token。

5.1 最简单的登录请求(HTTP)

curl.exe -X POST "http://127.0.0.1:7350/v2/account/authenticate/device?create=true" `
  -H "Content-Type: application/json" `
  -d '{"id":"device-1234567890"}'

返回一个 JSON,里面有 token(通行证)和 refresh_token(过期了用来续期)。

5.2 之后每个请求都要带 token

curl.exe "http://127.0.0.1:7350/v2/account?http_key=defaulthttpkey" `
  -H "Authorization: Bearer <上一步拿到的token>"

5.3 更推荐:用官方 SDK

自己拼 HTTP 协议容易出错,Nakama 提供了全平台官方 SDK,几行代码就能登录:

平台 SDK
Unity / C# nakama-csharp
Unreal / C++ nakama-cpp
JavaScript / Node nakama-js
Java / Android nakama-java
Swift / iOS nakama-swift

例如 JS 登录:

import { Client } from "@heroiclabs/nakama-js";
const client = new Client("defaultkey", "127.0.0.1", "7350");
const session = await client.authenticateDevice("device-1234567890", true);
console.log(session.token); // 拿到通行证

登录方式随时可以扩展:邮箱、微信、Steam、Apple……都是换一个接口的事,不用改服务器。

6. 开箱即用的功能(一行代码都不用写)

下面是 Nakama 内置的能力,不需要写任何业务逻辑,调 API 就能用。新手建议先把这些玩熟,再考虑写自己的代码:

功能 能做什么 怎么开始
排行榜 提交分数,自动排名 Console 里建一个排行榜,客户端调 API 提交分数
赛季 排行榜按赛季自动重置 Console 配置赛季起止时间
好友 / 群组 加好友、建群、拉人进组 客户端调好友/群组 API
聊天 世界频道、房间、私聊 WebSocket 连上后加入频道发消息
云存储 玩家存档(金币、道具、设置) 调 Storage API 读写
匹配系统 按条件撮合玩家进同一局 客户端发起匹配,服务器撮合
通知 给玩家发消息(在线送达,离线补发) 调 Notification API
实时消息 玩家之间实时收发数据 WebSocket 频道或对局内

打个比方:这些是框架送的"家具",先搬进屋里用起来;下面两章讲的 RPC 和 Match,才是你自己"装修"的部分。

7. 写自己的业务逻辑:RPC

排行榜、账号、聊天都是通用的;但你的游戏特有的规则(签到、抽卡、发放奖励、判胜负……)需要自己写。

Nakama 支持三种语言写游戏逻辑,选你熟悉的即可:

语言 特点 适合谁
Lua 上手最快,改完即生效 快速原型、小团队
TypeScript 类型安全,生态好 有前端经验的团队
Go 性能最好,和服务器同语言 追求性能、熟悉 Go 的团队

7.1 一个 RPC 是什么

RPC 就是一个**"客户端叫、服务器跑、返回结果"**的函数。比如"领取每日奖励":

// 服务器端:注册一个叫 daily_reward 的接口
func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB,
                nk runtime.NakamaModule, initializer runtime.Initializer) error {

    if err := initializer.RegisterRpc("daily_reward", rpcDailyReward); err != nil {
        return err
    }
    return nil
}

// 实现:读玩家存储 → 判断今天领没领 → 发奖励、写存储 → 返回结果
func rpcDailyReward(ctx context.Context, logger runtime.Logger, db *sql.DB,
                    nk runtime.NakamaModule, payload string) (string, error) {
    userID, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
    if !ok || userID == "" {
        return "", runtime.NewError("user not authenticated", 3)
    }
    // ...你的奖励逻辑...
    return `{"reward":"gold:100"}`, nil
}

7.2 客户端怎么调用

# 需要玩家身份的接口,带 token:
curl.exe -X POST "http://127.0.0.1:7350/v2/rpc/daily_reward" `
  -H "Authorization: Bearer <token>" `
  -H "Content-Type: application/json" `
  -d '""'

# 服务器返回永远是字符串(包一层 payload):
# {"payload":"{\"reward\":\"gold:100\"}"}

7.3 Go 写逻辑的两种打包方式

方式 怎么做 优点 缺点
Go 插件(.so) 逻辑编译成.so,服务器启动时加载 不用动服务器源码,热替换 版本必须和服务器完全一致,只支持 Linux
编译进服务器 把逻辑代码直接编进服务器二进制 一个二进制搞定,无版本问题 升级 Nakama 要重新合并

新手建议先用官方推荐的方式跑通,再考虑优化。

8. 实时对战:Match

对战是多人游戏的核心。Nakama 的 Match 有两种模式:

模式 判定在哪 能否作弊 适合
中继模式(Relayed) 客户端判定,服务器只转发消息 能作弊 联机小游戏、朋友互玩、快速原型
权威模式(Authoritative) 服务器判定 不能作弊 竞技游戏、有排名的玩法

8.1 中继模式(新手先玩这个)

客户端创建一个对局 → 其他玩家加入 → 互相发消息(比如坐标、出招),服务器只负责转发。逻辑简单,先用它把实时链路跑通。

8.2 权威模式(进阶)

服务器运行一个"对局对象",每秒执行若干次逻辑(tick),处理玩家消息、判定结果、广播给所有玩家:

创建对局 → 玩家加入 → 玩家发操作 → 服务器每tick处理并广播 → 对局结束

典型的生命周期:

  1. 玩家请求创建对局(或系统撮合)
  2. 其他玩家加入
  3. 玩家在回合内提交操作(如出拳、走棋)
  4. 服务器判定结果,广播给所有人
  5. 更新排行榜 / 存储 / 通知
  6. 对局结束,清理

权威模式需要实现一个 Match 接口(约 7 个回调方法:创建、加入、离开、循环、结束……),官方文档有完整示例,等中继模式玩熟后再学也不迟。

9. 玩家数据存储与通知

9.1 存储:玩家存档怎么存

Nakama 的云存储是**集合(Collection)→ 键(Key)→ 值(Value)**的三级结构,类似"表 → 行 → 单元格":

collection: "profile"          ← 集合(类似一张表,如"玩家档案")
  key: "stats"                 ← 键(类似一行数据,如"战绩")
    value: {"wins":3,"losses":1}  ← 值(任意 JSON)

写入时可以控制权限:

权限 含义 建议
读权限 谁能读到这份数据 1=公开,2=仅本人
写权限 谁能改这份数据 0=仅服务器(防作弊首选),1=本人可写

重要经验:关键数据(金币、战绩)一定要服务器写,客户端写就会被破解修改。

9.2 通知:给玩家发消息

通知适合"登录奖励到账""好友上线""开战提醒"这类场景,支持在线即时送达 + 离线补发:

_ = nk.NotificationsSend(ctx, []*runtime.NotificationSend{
    {UserID: userID, Subject: "每日奖励到账", Code: 1001, Persistent: true},
})

玩家下次登录,没看的通知会自动补到客户端。

10. 后台管理 Console

Nakama 自带一个网页后台,是开发者日常用得最多的工具:

项 值
地址 http://127.0.0.1:7351
默认账号 admin
默认密码 password(生产必须改)
界面语言 目前仅英文,浏览器右键"翻译成中文"即可

常用菜单:

菜单 能干什么
Users 看玩家账号、封号、重置密码
Storage 直接查看/修改玩家存档
Leaderboards 创建排行榜、配置赛季、看排名
API Explorer 在线调接口,不用写代码就能试
Runtime 看服务器加载了哪些自定义逻辑(RPC / Match)
Matches 看正在运行的实时对局
Status 服务器状态、版本号

调试技巧:遇到问题先看这里。Storage 里能直接看到数据到底写没写进去,比反复看代码快得多。

11. 常见问题 FAQ

问题 解答
镜像拉取很慢 / 拉不下来 配置 Docker 镜像加速(国内常用:腾讯云、163、DaoCloud、华为云)
7350 / 7349 / 7351 都是什么 客户端 API / gRPC / 后台管理,见 §4.4
忘记后台密码怎么办 修改 docker-compose 里的console.password 环境变量后重启
Console 能改成中文吗 目前没有中文版,用浏览器翻译
客户端收到的 op_code 是字符串? Nakama 的 JSON 协议会把 int64 序列化成字符串,比较时用Number(x) 转一下
用 Go 插件报版本不一致 服务器和插件必须同一 Go 版本 + 同一 nakama-common 版本编译
生产环境上线要改什么 后台密码、API key、JWT 密钥、开启 HTTPS、数据库备份、日志监控
想先看代码怎么写的 官方仓库heroiclabs/nakama 有完整示例(如 "go" 示例模块)

12. 下一步怎么学

学习路线建议(按顺序):

1. 跑通官方 demo(§4 一键启动,进 Console 点点看)
2. 用 SDK 接入登录、读写存储(§5、§9)
3. 建一个排行榜,提交分数看排名(§6,全程不用写代码)
4. 写第一个 RPC(§7)
5. 用中继模式跑通一个实时对局(§8)
6. 最后挑战权威模式对局(§8.2)

资源:

资源 地址
官方文档(最权威) https://heroiclabs.com/docs
官方 GitHub(源码+示例) https://github.com/heroiclabs/nakama
官方客户端 SDK GitHub 搜heroiclabs/nakama-js、nakama-unity 等
社区 GitHub Issues、官方 Discord、中文技术博客

最后送你一句经验:Nakama 的学习曲线主要在"概念"而不是"代码"——先搞懂账号、存储、对局、RPC 这几个概念,写起来很快。祝顺利!


本教程为通用入门文档,以 Nakama 官方文档为准。文中命令在 Windows / macOS / Linux 上均可运行(PowerShell 与 bash 的换行符略有差异)。