【Unity网络同步框架 - Nakama研究(二)】
Unity网络同步框架 - Nakama研究(二)
虽说官方文档和网站以及论坛建立的不错,而且还有中文翻译且质量也不错,但是总会遇到一些词不达意,说了但是依旧没懂的部分,甚至问
AI
也问不出什么东西,所以需要有一些比较明显的博客来记录实战部分
服务端搭建
使用官方推荐的
Docker
进行安装
- 在将
Docker
软件下载到Windows
环境后,请确保已安装node-js
、typescript
、lua
和Go
等环境(后续的对应扩展需要),否则先进行npm
相关库的安装,需要翻墙或者镜像库安装。 - 进入根目录,运行
cmd
控制台(在文件管理器上方地址栏直接输入cmd),输入docker compose up
,即能运行服务器(如需要配置文件见下文)。如果更改模块,需要重新编译运行,请输入docker compose up --build nakama
(或者在Docker
中停止运行再打开) - 如果遇到问题,一般情况是缺少对应的库,或者需要下载的库在墙外,下载超时了,很少会遇到不支持对应的数据库
CockroachDB
或者PostgreSQL
啥的,如果遇到了其他问题,建议上官网或者论坛查查 - 运行成功后,你应该能在
Docker
中看到如下:
这代表你的服务端已经正常开启了,接下来我们测试一下对应的一些方法和函数。
我的配置文件docker-compose
(官网上也能找到类似的)
version: '3'
services:
cockroachdb:
image: cockroachdb/cockroach:latest-v23.1
command: start-single-node --insecure --store=attrs=ssd,path=/var/lib/cockroach/
restart: "no"
volumes:
- data:/var/lib/cockroach
expose:
- "8080"
- "26257"
ports:
- "26257:26257"
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health?ready=1"]
interval: 3s
timeout: 3s
retries: 5
nakama:
image: registry.heroiclabs.com/heroiclabs/nakama:3.22.0
entrypoint:
- "/bin/sh"
- "-ecx"
- >
/nakama/nakama migrate up --database.address root@cockroachdb:26257 &&
exec /nakama/nakama --name nakama1 --database.address root@cockroachdb:26257 --logger.level DEBUG --session.token_expiry_sec 7200 --metrics.prometheus_port 9100
restart: "no"
links:
- "cockroachdb:db"
depends_on:
- cockroachdb
- prometheus
volumes:
- ./:/nakama/data
environment:
- NAKAMA_RUNTIME_PATH=/nakama/data/modules
expose:
- "7349"
- "7350"
- "7351"
- "9100"
ports:
- "7349:7349"
- "7350:7350"
- "7351:7351"
healthcheck:
test: ["CMD", "/nakama/nakama", "healthcheck"]
interval: 10s
timeout: 5s
retries: 5
prometheus:
image: prom/prometheus
entrypoint: /bin/sh -c
command: |
'sh -s <<EOF
cat > ./prometheus.yml <<EON
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['localhost:9090']
- job_name: nakama
metrics_path: /
static_configs:
- targets: ['nakama:9100']
EON
prometheus --config.file=./prometheus.yml
EOF'
ports:
- '9090:9090'
volumes:
data:
服务器简单测试
布置完了服务器,现在我们应该如何使用以及观察对应的服务器内的数据
- 为了方便测试,我们在这里先不使用
Unity
,直接打开一个C#
程序,我们只是测试一下而已,按照简单的来。有几个重要的网站需要记一下:- 本地控制台
- 接口
Api
地址(包含client
和console
)
- 测试代码如下:
using Newtonsoft.Json.Linq;
using System.Text;
class Program
{
private static readonly string nakamaApiMatchUrl = "http://127.0.0.1:7350/v2/match";
private static readonly string nakamaApiUrl = "http://127.0.0.1:7350/v2/account/authenticate/device?create=true";
private static readonly string nakamaApiLogoutUrl = "http://127.0.0.1:7350/v2/session/logout";
private static readonly string nakamaApiStorageUrl = "http://127.0.0.1:7350/v2/storage";
private static readonly string nakamaApiKey = "defaultkey";
private static string nakamaAuthToken = "nakama.autoToken";
static async Task Main(string[] args)
{
await AuthenticateDevice();
await FetchMatchList();
await FetchStorageObjectAsync();
await LogOut();
}
static async Task AuthenticateDevice()
{
try
{
var authHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{nakamaApiKey}:"));
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Basic {authHeader}");
var postData = new { id = "someuniqueidentifier" };
var json = Newtonsoft.Json.JsonConvert.SerializeObject(postData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(nakamaApiUrl, content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var responseJson = JObject.Parse(responseContent);
Console.WriteLine("Authentication successful.");
Console.WriteLine($"Session Token: {responseJson["token"]}");
if(responseJson.ContainsKey("token"))
nakamaAuthToken = responseJson["token"].ToString();
}
else
{
Console.WriteLine($"Error authenticating device: {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred: {ex.Message}");
Console.WriteLine("Please check the URL and network connection. If the issue persists, ensure the URL is correct and the server is running.");
}
}
static async Task LogOut()
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {nakamaAuthToken}");
var response = await client.PostAsync($"{nakamaApiLogoutUrl}", null);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var _content = JObject.Parse(content);
}
else
{
Console.WriteLine($"Error : {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred: {ex.Message}");
}
}
static async Task FetchMatchList()
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {nakamaAuthToken}");
var response = await client.GetAsync($"{nakamaApiMatchUrl}?limit=10&min_size=1&max_size=10");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var matches = JObject.Parse(content);
if(matches.ContainsKey("matches"))
{
foreach (var match in matches["matches"])
{
Console.WriteLine($"Match ID: {match["match_id"]}, Size: {match["size"]}");
}
}
else
{
Console.WriteLine($"Match list is empty");
}
}
else
{
Console.WriteLine($"Error fetching match list: {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred: {ex.Message}");
}
}
static async Task FetchStorageObjectAsync()
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {nakamaAuthToken}");
var response = await client.GetAsync($"{nakamaApiStorageUrl}/test/0ba39c8d-5b3d-429d-a570-85af6df61b49");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var storageContent = JObject.Parse(content);
}
else
{
Console.WriteLine($"Error fetching match list: {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error occurred: {ex.Message}");
}
}
}
- 上面的代码中简单测试了几个功能部分:登录,获取比赛(房间)列表,存储数据,登出。
- 其中有一些坑需要注意一下:
- 上面的配置中,不同的服务有不同的端口,其中7350是http请求的端口,也能自行指定;
Nakama
中的比赛(房间)分为权威(服务器创建)和非权威(玩家自创建),要注意区分(查询时会返回不同)- 存储分为服务器内存的存储和数据库本地的持久存储,上面的测试是一个临时行的测试,请求的全文是
/v2/storage/{collection}/{userId}
,如果需要严格测试的话,该测试需要后期进行才能跑通
如果成功的话,运行的结果应该是上面类似(有部分数据没有打印出来,偷懒直接断点看了)