第一个对局
一个大厅进程加两个客户端,跳过匹配直接拉起实例,从分配到结算看完整日志。
这一节跑最短的一条路:不做匹配,让大厅直接分配一个实例,客户端带票据旅行进房, 看房间把座位、开局、结算各记一行日志。
1. 启动大厅(无窗口)
大厅可以像生产环境一样无窗口运行,代价是没有地方敲命令:~ 是视口控制台,-server 进程没有视口。
本章后面要用到的命令,有两种给法——写进 -ExecCmds 在启动时执行一次,或者按
学习路径 3-A 的方式 A 用 PIE Listen Server,在那个游戏窗口里按 ~。
& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" /Engine/Maps/Entry -server -game -nullrhi -unattended -log -PORT=57200
<UE>是引擎根目录(里面能看到Engine文件夹)。引擎可执行文件在<UE>\Engine\Binaries\Win64\下——别漏中间那层Engine,漏了就会报「不是内部或外部命令」。
| 参数 | 作用 |
|---|---|
-server -game | 跑权威侧 |
-nullrhi -unattended | 不建渲染设备、不弹对话框;也就是没有窗口、没有 ~ |
-log | 额外开一个日志窗口,方便当场看输出 |
-PORT=57200 | 大厅自己的游戏端口;控制端口另配(默认 57300) |
命令会占住当前终端,直到大厅进程退出。日志里会看到:
[Config] event=Summary mode=1v1 warmPool=false maxInstances=8
[Match] event=MatcherReady
[Session] event=ControlReady port=573002. 让大厅分配一个实例
无窗口的大厅,命令只能由启动参数一次性带上:
& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" /Engine/Maps/Entry -server -game -nullrhi -unattended -log -ExecCmds="CrossingNet.DebugAssign 1v1" -PORT=57200如果 DebugAssign 报 RoomMapPackage 未配置,先按学习路径 · 认识设置填好配置再回来。
想反复敲命令(再查一次 Status、再 ForceSettle),用 PIE Listen Server:Play 按钮旁选 Play As Listen Server,
进游戏窗口后按 ~,输入:
CrossingNet.DebugAssign 1v1
CrossingNet.*命令只写日志,不会在输入行下面回显:执行完去 Output Log 里找[Status]/[Session]开头的行。
它跳过队列直接 SpawnInstance 拉起一个 1v1 房间,并把第一个进来的人分过去。日志:
[Session] event=SpawnStart mode=1v1 port=57000
[Session] event=HealthFirstOK port=57000
[Assign] event=Assigned instance=<guid> port=57000HealthFirstOK 出现之前实例一直是 Spawning;超过 StartupTimeoutSeconds(默认 180 秒)
就会带 StartupTimeout 关掉。
3. 客户端进来(Windows 终端)
& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" 127.0.0.1:57200 -game -log -CrossingNetGuestSlot=1这条命令输入在 Windows 终端,不是 UE 控制台;<UE>、<Project目录> 换成你自己的路径,-log 让客户端也有日志窗口,-CrossingNetGuestSlot=N 给同机多个客户端各一个身份槽位,避免同名冲突。
旅行进房后房间侧校验票据(bRequireJoinToken=True 时),按角色分座位:
[Room] event=JoinTokenAccepted player=<guid> role=Player team=0
[Room] event=SeatAssigned player=<guid> seat=0
[Room] event=Roster players=1票据不对会走 [Room] event=JoinTokenRejected 或 [Assign] event=Rejected,并在事件里带错误码。
4. 准备、开局、结束
| 动作 | 谁做 | 日志 |
|---|---|---|
| 准备 | 客户端 ServerSetReady(true) | [Room] event=ReadyChanged |
| 开局 | 人齐后房间推 OnGameStart | [Room] event=GameStart |
| 结束 | 房间 EndGame / 大厅 CrossingNet.ForceSettle | [Room] event=GameEnd、[Session] event=MatchResult |
CrossingNet.ForceSettle 需要控制台:无窗口大厅写进 -ExecCmds,或改用 PIE Listen Server 后按 ~。测试时最省事的是让房间自己结束:
; 额外服务器参数
ExtraServerArgs=-CrossingNetAutoEndGame=8结算链路:
[Room] event=Settlement match=<id> winner=0
[Session] event=SettlementRecorded match=<id>
[Session] event=SettlementAcked match=<id>
[Room] event=SettlementAcked大厅先回 ACK 再异步落盘;房间没等到 ACK 会重试,最多 3 次。
5. 两个客户端对打
跑大厅时让客户端自动入队:
-CrossingNetAutoMatch -CrossingNetAutoReady两个客户端各自入队,匹配器按 MatchBaseEloWindow(默认 100)聚合,配到后走 ReadyCheck,
再走和上面一样的分配与旅行。
卡住时先查这四处
| 现象 | 先看 |
|---|---|
| 客户端旅行超时 | 大厅日志里 [Assign] 的地址是不是 127.0.0.1;PublicAddress(对外地址) 配错没 |
| 实例起不来 | ServerExePath(服务器可执行文件) / ServerArgsPrefix(服务器前置参数) 是否可执行;instance_<端口>.log 有没有落盘 |
| 大厅说卡死 | 健康端口段与防火墙;ProbeIntervalSeconds(健康探测间隔,秒)、HealthFailureThreshold(健康失败阈值) |
| 结算一直重试 | 大厅控制端口通不通;CrossingNet.Status 里该实例是否已 Closed |
下一页:架构。