Skip to Content
CrossingNet

学习路径

按顺序走完九章:从装进项目、看懂设置,到在大厅、房间、匹配、局域网和封禁之间独立排查问题。每章有一个可执行的案例和一条完成判据。

这一页是走法,不是参考。按下面的顺序做,每章产出一个能看见的东西;九章走完, 你可以独立起一套大厅 + 房间、跑通一次匹配、用局域网开一局、并在出问题时知道先看哪条日志。

学完能得到什么(九项能力,覆盖矩阵在页末):

  1. 把 CrossingNet 放进项目并让它编译通过
  2. 看懂并配好插件设置里拉起房间必须的那几项(RoomMapPackage 等)
  3. 起一个大厅进程,读得懂 CrossingNet.Status
  4. 手工拉起一个房间,认出 Spawning → Ready
  5. 让客户端带着票据进房,看到座位分配
  6. 结束一局并确认结算被 ACK
  7. 跑通一次自动匹配
  8. 在同一个网段开房并被发现
  9. 用日志、命令和设备注册表排查一局为什么没成

不教什么:玩法规则、UI、账号与登录系统、打包发布流程、性能调优。这些要么在别处,要么还没有。

路径总表

#章节前置你会做出什么完成判据实测案例预计耗时
1装进项目无能编译的工程编辑器 Plugins 里 CrossingNet 已启用,无编译错误案例 1-A10 min
2认识设置第 1 章一份不会被拉起报错的配置DefaultGame.ini 里 ServerExePath(服务器可执行文件) / ServerArgsPrefix(服务器前置参数) / RoomMapPackage(房间地图) / LobbyControlAddress(大厅控制地址) 四项非空案例 2-A10 min
3起大厅第 2 章一个跑着的大厅进程CrossingNet.Status 返回实例表(可以为空)案例 3-A15 min
4拉起房间第 3 章一个 Ready 的实例大厅日志出现 HealthFirstOK port=...案例 4-A10 min
5客户端进房第 4 章一个坐在房间里的玩家房间日志出现 SeatAssigned案例 5-A15 min
6结束与结算第 5 章一局结算记录大厅日志出现 SettlementRecorded 与 SettlementAcked案例 6-A10 min
7自动匹配第 6 章两个客户端被配到同一局大厅日志出现 MatchFound案例 7-A20 min
8局域网开房第 2 章(不需要大厅)另一台机器在列表里看见房间CrossingNet.LANList 后日志出现 [LAN] rooms=1案例 8-A20 min
9运维与封禁第 6 章一条封禁记录与一条可检索的日志CrossingNet.DeviceList banned 输出里有该设备案例 9-A15 min

⚠️ 案例状态:全部 未验证。 这些命令与字段来自插件源码与 README.md,但没有在本机实跑过 (插件由作者自行编译,本轮未编译)。每条案例都写明了"要验证它需要什么"。按 WRT-LP-S06, 不标 实测 的案例不得被引用成"已验证"。

前置与环境

项要求
版本Unreal Engine 5.8.2(源码版);CrossingNet 0.1.0
平台Windows x64(其余平台未验证)
依赖无外部依赖;工程需要已经能正常编译和启动
起点目录一个能打开编辑器的 UE 工程。下文用 <Project> 指工程名、<Project目录> 指工程所在目录、<UE> 指引擎根目录(那一层里直接能看到 Engine 文件夹)

本页命令分两种:标 powershell 的在 Windows 终端(PowerShell/CMD)里执行;标 text 的是 UE 控制台,只有存在游戏视口时按 ~ 才能打开——PIE 的 Listen Server 游戏窗口可以,-server 进程没有视口,按不出来。两者不能互换。

还有一件事:CrossingNet.* 命令只写日志,不会在输入行下面回显。执行完去编辑器底部的 Output Log(或 -log 窗口、Saved/Logs/)里找 [Status]、[Session] 开头的行。

案例 1-A · 装进项目

本章产出:编辑器插件列表里出现 CrossingNet,且工程能编译通过。

<Project>/Plugins/CrossingNet/          ← 整个插件目录放这里
  CrossingNet.uplugin
  Source/
  Config/Presets/

打开工程 → Edit ▸ Plugins → 搜索 CrossingNet → 勾选 → 重启编辑器;确认没有编译错误。

插件目录里有什么:

路径内容
Source/CrossingNet/运行时模块:身份、大厅、房间、匹配、档案、事件、网络、局域网、设备
Source/CrossingNetEditor/编辑器模块:设置面板与编辑器工具
Config/Presets/6 份设置预设(LoL / 王者 / 守望 / 三角洲 / 四队积分 / 1v1 BO3)
README.md功能矩阵、接口表、日志与错误码速查

为什么这样工作:插件按 .uplugin 描述文件加载两个模块(CrossingNet、CrossingNetEditor), 目录名与插件名一致最省事。

常见失败

症状原因修
插件列表里没有 CrossingNet放错了层级(例如 Plugins/Plugins/...)确保 Plugins/CrossingNet/CrossingNet.uplugin 存在
编译报缺少模块项目模块没依赖 CrossingNet在项目 Build.cs 的 PublicDependencyModuleNames 加 "CrossingNet"

自测:把插件目录改名再改回来,编辑器是否仍能识别?(考的是插件名由 .uplugin 决定,不是目录名)

下一章用它:设置项就长在这个插件上,先认清它再来配。

案例 2-A · 认识设置

本章产出:一份不会被拉起报错的配置。

前置检查:第 1 章的插件已经启用、能编译。

在哪看:编辑器 Project Settings ▸ Plugins ▸ CrossingNet(面板标题是 CrossingNet 联机设置;所有项都在 Config/DefaultGame.ini 的 [/Script/CrossingNet.CrossingNetSettings] 段里)。设置分成 13 类:

01 模式与基础      02 服务器与房间    03 匹配与队列    04 身份与令牌
05 对局规则        06 结算与段位      07 赛季          08 组队
09 观战与迟到      10 存档与身份      11 运维与指标    12 网络与控制
13 局域网开房

第一次只需要看懂四类里的五项——其余都可以先留默认值:

项类别填什么空着会怎样
ServerExePath(服务器可执行文件)02 服务器与房间拉起房间进程的可执行文件。开发期指向引擎的 UnrealEditor.exe;生产指向打包的 Server.exeDebugAssign/匹配都会拉不起实例
ServerArgsPrefix(服务器前置参数)02 服务器与房间跟在可执行文件后的整行参数,含 <Project>.uproject -server -game房间进程起不来,实例卡在 Spawning
RoomMapPackage(房间地图)02 服务器与房间房间进程加载的地图,常用 /Engine/Maps/Entry;自己的图写 /Game/...DebugAssign 直接报 RoomMapPackage 未配置
LobbyControlAddress(大厅控制地址) + LobbyControlPort(大厅控制端口)12 网络与控制大厅控制通道地址,例如 127.0.0.1:57300房间回传不了状态与结算
JoinTokenSecret(令牌密钥)04 身份与令牌票据签名密钥,开发用默认、生产必须换客户端进房被拒(BadToken)

写进 Config/DefaultGame.ini 的样子:

[/Script/CrossingNet.CrossingNetSettings]
; 服务器可执行文件
ServerExePath=<UE>/Engine/Binaries/Win64/UnrealEditor.exe
; 服务器前置参数
ServerArgsPrefix="<Project目录>/<Project>.uproject -server -game -unattended -nullrhi"
; 房间地图
RoomMapPackage=/Engine/Maps/Entry
; 大厅控制地址
LobbyControlAddress=127.0.0.1:57300

<UE> 是引擎根目录(里面能看到 Engine 文件夹),<Project目录> 是工程所在目录; 别漏 <UE>\Engine 那一层。

输出在哪:改完启动一次大厅,日志里会有配置摘要:

[Config] event=Summary mode=1v1 warmPool=false maxInstances=8

如果某项空着,第一次用到它的命令会报错,例如:

[Session] event=DebugAssignFailed mode=1v1 error=RoomMapPackage 未配置(Project Settings -> CrossingNet)

为什么这样工作:大厅要靠这几项拉起房间进程并把地址发回客户端;它们不是可选项,只是有默认值的项 (RoomMapPackage 没有默认值,所以必须手填)。

常见失败

症状原因修
DebugAssign 报 RoomMapPackage 未配置这一项是空的填 /Engine/Maps/Entry 或 /Game/...,重启大厅
实例卡在 Spawning 后超时ServerExePath(服务器可执行文件) / ServerArgsPrefix(服务器前置参数) 不对手动在终端执行这两项拼出来的命令,看进程为什么退出
客户端 BadToken大厅与房间的 JoinTokenSecret(令牌密钥) 不一致两边读同一份 ini,改完重启

自测:把 RoomMapPackage 清空再 DebugAssign,日志里报的是什么错?恢复后再试一次。

下一章用它:设置对了,大厅才拉得起房间。

案例 3-A · 起大厅

本章产出:一个能接收控制台命令、并且看得到实例表的大厅。

前置检查:第 2 章的五项配置非空。

⚠️ 先说清楚 ~ 这件事:~ 打开的是视口控制台,只有存在游戏视口时才有。 用 -server 启动的是无窗口的权威进程,它没有视口,所以没有 ~,也敲不进任何命令。 想在控制台里敲 CrossingNet.Status,要么用下面方式 A(有视口),要么用方式 B(启动时一次性执行)。

方式 A(推荐,能交互):在编辑器里跑 Listen Server

插件判断「是不是服务端」用的是 World->GetNetMode() != NM_Client,所以 Listen Server 也会被当成服务端, 大厅逻辑照常跑。这条路径尚未实跑验证,但它是目前唯一能一边跑一边敲命令的方式。

  1. 用编辑器打开你的地图(大厅用什么图都可以,/Engine/Maps/Entry 也行)
  2. 编辑器工具栏 Play 按钮右边的小三角 → Net Mode 选 Play As Listen Server
  3. 点 Play,游戏窗口出现后点一下窗口
  4. 按 ~,打开控制台,输入:
CrossingNet.Status

输出在哪:不会在输入行下面回显——输出是日志行,去编辑器底部的 Output Log(输出日志) 里看。预期多出:

[Status] event=Snapshot netmode=2 instances=0 queue=0

每有一个实例,还会多一行:

[Status] event=Instance id=A1B2C3 state=Ready reason=None pid=1234 game=57000 health=58100 players=0+0/2 mode=1v1 age=3s winner=0 rated=0

netmode 取值:0=Standalone、1=DedicatedServer、2=ListenServer、3=Client。 方式 A 下应该是 2;instances=0 表示还没有房间,正常。

从这一章往后,凡写着「在控制台里输入」的地方,都是在这个游戏窗口里按 ~。

方式 B(无窗口,接近生产):-ExecCmds 一次性执行

在 PowerShell 里(把 <UE> 与 <Project目录> 换成你自己的路径,注意中间那层 Engine):

& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" /Engine/Maps/Entry -server -game -nullrhi -unattended -ExecCmds="CrossingNet.Status" -log -PORT=57200

例如:

& "D:\UnrealEngine-5.8.2\Engine\Binaries\Win64\UnrealEditor.exe" "D:\MyGame\MyGame.uproject" /Engine/Maps/Entry -server -game -nullrhi -unattended -ExecCmds="CrossingNet.Status" -log -PORT=57200
  • -ExecCmds 在启动时执行一次,多个命令用逗号分隔;输出在日志窗口(-log)与 Saved/Logs/ 里
  • 这种方式不能交互:想再执行一条,就得改 -ExecCmds 重启,状态也从头开始
  • 生产环境的大厅就是这样跑的:命令靠启动参数与外部工具发,不靠手敲

为什么这样工作:大厅是一个权威进程,额外监听控制端口(默认 57300); Status 只是读这层的数据。渲染设备有无(-nullrhi)不影响大厅逻辑,但没有渲染就没有视口,也就没有 ~。

常见失败

症状原因修
按 ~ 没反应 / 敲不了字跑的是 -server 进程,没有视口用方式 A;或改用 -ExecCmds(方式 B)
UnrealEditor.exe 不是内部或外部命令路径漏了 Engine 这一层,或工程路径写错用绝对路径并以 & "路径" 开头,形如 <UE>\Engine\Binaries\Win64\UnrealEditor.exe
敲了回车没反应输出在日志里,不在输入行下面;若日志里也没有 [Status] event=Snapshot,多半是在编辑器底部的 Cmd 输入框里敲的——那是编辑器世界,没有 GameInstance,函数直接返回到 PIE 的 Listen Server 游戏窗口里按 ~ 再试
控制台里 CrossingNet.Status 报未知命令插件没加载(第 1 章没做完)看日志里有没有 [Session] event=ControlReady
端口被占-PORT 与别的进程冲突换端口;同时确认 LobbyControlPort(大厅控制端口) 没被占

自测:方式 A 里不点 Play(只开编辑器)时,Status 能看到什么?为什么?

下一章用它:大厅负责拉起并盯住房间进程。

案例 4-A · 拉起房间

本章产出:一个 Ready 的实例。

前置检查:上一章的大厅还在跑,CrossingNet.Status 能打出 [Status] event=Snapshot。

在哪输入:CrossingNet.* 是 UE 控制台命令,两种给法挑一种:

  • 方式 A(PIE Listen Server):在那个游戏窗口里按 ~,输入下面这行
  • 方式 B(无窗口大厅):把命令写进启动参数 -ExecCmds="CrossingNet.DebugAssign 1v1",重启大厅
CrossingNet.DebugAssign 1v1

输出在哪:大厅的日志——编辑器的 Output Log、-log 弹出的日志窗口,或 Saved/Logs/<Project>.log。 预期依次出现:

[Session] event=SpawnStart mode=1v1 port=57000
[Session] event=HealthFirstOK port=57000

为什么这样工作:DebugAssign 跳过匹配,直接 SpawnInstance 拉起一个实例, 进程起来后房间在健康端口回 OK;…,大厅才把它从 Spawning 挪到 Ready。

常见失败

症状原因修
DebugAssignFailed,error 里写着 RoomMapPackage 未配置第 2 章那一项没填填 /Engine/Maps/Entry 或 /Game/...,重启大厅
敲了命令,日志里没有 SpawnStart命令在大厅以外的世界执行了(例如编辑器的 Cmd 输入框),或大厅没跑在 PIE 游戏窗口按 ~,或确认大厅进程在跑
卡在 SpawningServerExePath(服务器可执行文件) / ServerArgsPrefix(服务器前置参数) 写的可执行文件拉不起来看 Saved/CrossingNet/Logs/instance_<端口>.log 有没有生成
超时关闭StartupTimeoutSeconds(启动超时,秒) 内没回健康查健康端口段与防火墙

自测:把 GamePortRange 改窄到只剩一个端口,连开两个实例会发生什么?

下一章用它:Ready 的实例才能坐人。

案例 5-A · 客户端进房

本章产出:房间里有一个玩家。

前置检查:上一章拉起的实例仍是 Ready(大厅日志里最后一次是 HealthFirstOK)。

在哪输入:Windows 终端(PowerShell)。这是一条启动客户端进程的命令,不是 UE 控制台命令:

& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" 127.0.0.1:57200 -game -log -CrossingNetGuestSlot=1
  • <UE>、<Project目录> 换成你自己的路径
  • -log 让客户端也有日志窗口;不加就只能去 Saved/Logs/ 找
  • -CrossingNetGuestSlot=1 给这台机器上的第一个客户端一个固定身份槽位,避免同机多开冲突

输出在哪:房间侧的分座位结果在房间进程的日志 Saved/CrossingNet/Logs/instance_<端口>.log; 客户端自己的旅行日志在它的输出日志里。预期房间日志:

[Room] event=JoinTokenAccepted player=<guid> role=Player team=0
[Room] event=SeatAssigned player=<guid> seat=0

为什么这样工作:大厅签发票据,客户端带着票据旅行;房间用同一个 JoinTokenSecret 校验后分座位。

常见失败

症状原因修
客户端窗口一闪就没了 / 连不上地址或端口写错,或大厅没在 57200 上监听看客户端日志里的 [Travel] 行
旅行超时分配地址是 127.0.0.1 但客户端在另一台机器配 PublicAddress(对外地址)
JoinTokenRejected两边 JoinTokenSecret(令牌密钥) 不一致改 ini 并重启大厅与房间

自测:把 JoinTokenTtlSeconds 改成 1,隔几秒再进房,日志会是什么?

下一章用它:有人才能开局、结束、结算。

案例 6-A · 结束与结算

本章产出:一条落地并回了 ACK 的结算记录。

前置检查:按第 5 章让一个客户端进了房,房间日志里出现过 SeatAssigned。

在哪输入:自动结束参数写进 ini;CrossingNet.ForceSettle 是 UE 控制台命令(方式 A 在游戏窗口按 ~,方式 B 写进 -ExecCmds 重启)。

做法一(不用命令):给房间加自动结束参数,房间到点自己结束。参数配在大厅的 DefaultGame.ini 里:

; 额外服务器参数
ExtraServerArgs=-CrossingNetAutoEndGame=8

做法二(用命令):在大厅的 UE 控制台里强制结算——方式 A 在游戏窗口按 ~,方式 B 写进 -ExecCmds="CrossingNet.ForceSettle" 重启:

CrossingNet.ForceSettle

输出在哪:大厅日志。预期:

[Session] event=SettlementRecorded match=<id>
[Session] event=SettlementAcked match=<id>

为什么这样工作:房间把结果带 matchId 发给大厅,大厅先回 ACK 再异步落盘,按 matchId 幂等。

常见失败

症状原因修
一直 SettlementPush 无 ACK控制通道不通(57300)查端口与防火墙
SettlementDuplicate同一局被结算两次正常保护,不用处理

自测:大厅重启后,用同一个 matchId 再发一次结果会发生什么?

下一章用它:自动匹配最终也会走到这条结算链路。

案例 7-A · 自动匹配

本章产出:两个客户端被配到同一局。

前置检查:大厅还在跑,而且第 5 章能进房、第 6 章能结算。

在哪输入:Windows 终端,开两个窗口各跑一条(换成你自己的路径):

& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" 127.0.0.1:57200 -game -log -CrossingNetGuestSlot=1 -CrossingNetAutoMatch -CrossingNetAutoReady
& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" 127.0.0.1:57200 -game -log -CrossingNetGuestSlot=2 -CrossingNetAutoMatch -CrossingNetAutoReady

输出在哪:大厅日志里出现 QueueJoin → MatchFound,随后是 ReadyCheck 与分配; 两个客户端的日志里各有一条 [Assign] 与 [Travel]。

为什么这样工作:两个客户端各自入队,匹配器按 MatchBaseEloWindow 聚合; 配到后进 ReadyCheck,确认后才分配实例与票据。

常见失败

症状原因修
一直排队模式与 ModeConfigs(模式配置) 不匹配(例如排 2v2 但只配了 1v1)检查 +ModeConfigs
排队超时MatchMaxWaitSeconds(最大匹配等待,秒) 到了还没配到放宽窗口或检查人数

自测:只开一个客户端时,它会在什么时候以什么错误码结束排队?

下一章用它:没有大厅,局域网也能开一局。

案例 8-A · 局域网开房

本章产出:另一台机器在局域网列表里看见房间。

前置检查:两台机器接在同一个路由器或交换机下(同一网段),并且不需要大厅。

先在两台机器上各开一个带窗口的游戏(局域网发现要在游戏里执行,不需要 -server):

& "<UE>\Engine\Binaries\Win64\UnrealEditor.exe" "<Project目录>\<Project>.uproject" /Engine/Maps/Entry -game -log

在哪输入:两台机器各自的游戏窗口里按 ~(这是 UE 控制台命令)。

机器 A(当房主):

CrossingNet.LANHost 我的房间 /Engine/Maps/Entry 57100

机器 B(找房间):

CrossingNet.LANDiscover
CrossingNet.LANList

输出在哪:机器 B 的日志里出现

[LAN] rooms=1

随后加入:

CrossingNet.LANJoin 192.168.1.23:57100

为什么这样工作:房主每 LANAnnounceInterval 秒发 OFFER,客户端收包后按 HostId 去重, 地址只取 UDP 源地址。

常见失败

症状原因修
[LAN] rooms=0两台机器不在同一网段,或组播被交换机拦了关 LANUseMulticast(使用组播),只用广播
列表有但连不上防火墙挡住游戏端口放行 LANGamePortRange(局域网游戏端口范围)

自测:把 LANUseMulticast 关掉后,LANDiscover 的行为有什么变化?

下一章用它:知道怎么开房,也要知道怎么把人挡在门外。

案例 9-A · 运维与封禁

本章产出:一条设备封禁记录,和一条能按 trace 检索的日志。

前置检查:至少有一个客户端连过大厅(这样才登记过设备)。

在哪输入:大厅的 UE 控制台——方式 A 在游戏窗口按 ~,方式 B 写进 -ExecCmds="CrossingNet.DeviceList" 重启(多条命令用逗号分隔)。

CrossingNet.DeviceList
CrossingNet.DeviceBan <deviceKey> 0 测试
CrossingNet.DeviceList banned

<deviceKey> 从第一条命令的输出里抄——[Device] 行开头那 8 位。

输出在哪:大厅日志。预期:

[Device] list bannedOnly=0 count=1
[Device] A1B2C3D4 platform=Win64 banned=0 until=0 accounts=1
[Device] list bannedOnly=1 count=1

同时 Saved/CrossingNet/Devices.json 里会出现该设备的记录。

为什么这样工作:设备注册表只在大厅服务端初始化,DeviceBan 只封精确硬件指纹; 弱指纹与候选只记录不自动封。

常见失败

症状原因修
命令被拒绝在客户端执行了到大厅(服务端)执行
封了但还能进登录拒绝点在项目登录层插件只给信号,接入点要项目自己接

自测:minutes=0 与 minutes=60 的区别在哪张表、哪个字段上看?

下一章:没有下一章;从这里开始,按你要做的事去查参考页。

覆盖矩阵

能力章节验证方式
装进项目并编译通过1案例 1-A 的完成判据
看懂并配好必填设置2案例 2-A 的四项非空 + [Config] event=Summary
起大厅并读懂实例表3案例 3-A
拉起房间并认出 Ready4案例 4-A
客户端带票据进房5案例 5-A
结束一局并确认 ACK6案例 6-A
跑通自动匹配7案例 7-A
局域网开房与发现8案例 8-A
用命令与日志排查9案例 9-A

没有覆盖什么:玩法规则的实现、UI 与表现层、账号与登录、打包与发布、性能与容量、 观战与迟到的实际体验、系列赛与赛季的配置调优。这些在事件参考、 配置参考与各专题页里,但没有配套案例。

走完之后

On this page