UE5蓝图多人游戏开发:从PIE到双机局域网联调实战指南

发布时间:2026/8/4 4:08:47
UE5蓝图多人游戏开发:从PIE到双机局域网联调实战指南 1. 项目概述为什么PIE联调不够用做UE5多人游戏开发尤其是蓝图开发者你是不是也这样在编辑器里点开“Play”旁边的下拉箭头选择“Play as Client”和“Play as Dedicated Server”然后看着两个PIEPlay-In-Editor窗口跑起来就觉得联机测试搞定了我得说兄弟这真的只是万里长征第一步甚至可能让你在后续开发中踩大坑。PIE联调方便快捷适合早期逻辑验证但它和真实的多机环境差异巨大。网络延迟、带宽、硬件性能差异、防火墙、甚至操作系统调度策略这些在PIE的“沙盒”里都被极大地简化或模拟了。你可能会遇到在PIE里丝滑流畅但打包后分发给朋友测试就卡顿、掉线、甚至行为诡异的问题。这就是为什么我们必须把“双机局域网联调”作为多人游戏开发的核心环节。它模拟了最接近真实玩家环境的场景两个独立的进程或机器通过真实的网络协议如UDP进行通信。今天我就手把手带你不写一行C纯用蓝图和UE5内置的在线子系统搭建一个可运行、可调试的双机局域网测试环境。我们会从项目设置开始到创建一个简单的房间匹配和同步移动的demo最后在两台电脑或虚拟机上跑起来。目标是让你彻底摆脱对PIE联调的过度依赖获得更真实的网络调试体验。2. 核心思路与蓝图系统选型在UE5中实现多人游戏官方提供了两套主要的蓝图系统“Online Subsystem”和更底层的“Low-Level Networking”。对于大多数基于蓝图的、需要房间/匹配功能的项目我强烈推荐从Online Subsystem Blueprint (OSB)入手特别是它的“Session”接口。为什么是Online Subsystem Session抽象度高它帮你处理了网络通信的底层细节套接字创建、数据包序列化等你只需要关注“创建房间”、“查找房间”、“加入房间”这些游戏逻辑。平台兼容性好这套接口的设计初衷是抽象不同平台Steam、Epic Online Services、Xbox Live等的在线服务。即使我们只用局域网Null接口其API也是一致的未来迁移到正式平台服务会平滑很多。内置状态管理Session会话本身就是一个管理单元包含了房间属性如地图名、玩家人数上限、玩家列表等信息省去了自己维护的麻烦。蓝图支持完善UE5为Online Subsystem提供了完整的蓝图节点从创建到销毁从注册事件到处理回调都有直观的节点可用。相比之下直接使用Low-Level Networking如Spawn Actor with Replication更适合不需要房间概念、直接进行点对点连接或非常定制化的网络拓扑对于初学者和大多数游戏类型来说Session接口更易上手和规范。我们的技术路线图启用并配置Online Subsystem在项目设置中启用插件并配置使用“Null”接口用于局域网。构建核心Session蓝图创建一个游戏实例GameInstance蓝图在其中封装创建会话当主机、查找会话和加入会话当客户端的逻辑。实现简单的游戏逻辑创建一个可复制的玩家角色蓝图实现移动同步。设计测试关卡制作一个简单的关卡放置玩家出生点。进行双机部署与测试将项目打包在两台处于同一局域网的机器上运行一台作为主机创建游戏另一台作为客户端搜索并加入。3. 环境准备与项目基础配置在开始写蓝图之前我们必须先把地基打牢。这一步的配置错误会导致后续所有网络功能都无法工作。3.1 插件启用与模块配置打开你的UE5项目首先进入“编辑” - “插件”。在插件搜索框中输入“Online”。确保“Online Subsystem”和“Online Subsystem Utils”这两个插件是已启用状态。通常它们是默认启用的但务必检查。点击右上角的“重启编辑器”按钮让插件生效。接下来我们需要配置项目使用正确的Online Subsystem接口。对于纯局域网测试我们使用“Null”接口。它不依赖任何第三方平台服务直接在本地网络间通过UDP通信。打开“项目设置” - “引擎” - “Online Subsystem”。在“Default Platform Service”下拉菜单中选择“Null”。这告诉引擎在开发或未指定平台时使用Null接口。可选但推荐点击底部的“高级”下拉箭头展开“Online Subsystem”部分。你会看到一个“Config”按钮点击它。这会在你的项目Config目录下生成或打开DefaultEngine.ini文件的相关部分。确保配置文件中包含以下内容。如果没有可以手动添加[/Script/Engine.GameEngine] NetDriverDefinitions(DefNameGameNetDriver,DriverClassNameOnlineSubsystemSteam.NetDriverSteam,DriverClassNameFallbackOnlineSubsystemUtils.IpNetDriver) [OnlineSubsystem] DefaultPlatformServiceNull [OnlineSubsystemNull] bEnabledtrue [/Script/OnlineSubsystemUtils.IpNetDriver] MaxClientRate1000000 MaxInternetClientRate1000000这段配置的核心是设置默认在线子系统为Null并指定了回退的网络驱动为IpNetDriver这是处理IP网络通信的基础驱动。调整MaxClientRate可以控制网络带宽局域网内可以设高一些。3.2 创建核心蓝图类GameInstanceGameInstance是贯穿游戏整个生命周期的单例对象是管理Session会话逻辑的理想场所。它不会随着关卡切换而被销毁。在内容浏览器中右键点击空白处选择“蓝图类”。在弹出窗口的搜索框中输入“GameInstance”并选中它然后点击“选择”。将其命名为BP_MyGameInstance。双击打开这个蓝图。我们后续所有的Session管理逻辑都将写在这里。3.3 创建测试关卡与玩家角色测试关卡新建一个空白关卡保存为L_NetworkTest。简单地添加一些地面如一个Cube缩放成地板、光源和一个玩家出生点Player Start。确保至少有一个Player Start。玩家角色创建一个新的蓝图类父类选择Character命名为BP_NetworkPlayer。打开后在“类默认值”面板中找到“复制”分类。将“复制”选项设置为“是”。这是最关键的一步它意味着这个Actor及其组件的状态将在服务器和客户端之间同步。你可以为其添加一个静态网格体组件如一个球体或方块作为视觉表现。4. Session管理核心蓝图实现现在进入最核心的部分在BP_MyGameInstance中实现会话的创建、查找和加入。4.1 创建会话作为主机当玩家点击“创建游戏”或“作为主机开始”时需要执行此逻辑。在BP_MyGameInstance的事件图表中右键搜索节点“Create Session”完整路径通常在Online|Session下。你会找到一个名为“Create Session (Advanced)”的节点功能更全我们用它。关键参数配置Public Connections公共连接数即房间最大玩家数不包括主机。设为3则表示最多3个客户端1个主机4人。Use LAN必须勾选。这是我们进行局域网测试的关键。Session Name会话名称可以自定义如“MySession”。Extra Settings可以添加自定义的会话设置比如地图名称、游戏模式等。这是一个自定义结构体数组。我们可以先留空。事件绑定Create Session是一个异步操作它执行完成后会触发On Create Session Complete事件。你需要将这个事件与一个自定义事件如OnCreateSessionComplete绑定并在其中处理成功或失败后的逻辑比如成功则跳转到游戏关卡。完整流程示例首先定义一个自定义事件HostGame它由UI按钮触发。在HostGame中调用Create Session (Advanced)节点。将On Create Session Complete输出引脚连接到OnCreateSessionComplete自定义事件的输入执行引脚。在OnCreateSessionComplete事件中会有一个bool bWas Successful参数。判断如果成功则使用Open Level节点打开你的测试关卡L_NetworkTest。注意作为主机你打开关卡时引擎会自动将这个关卡作为会话的一部分加载并开始监听客户端连接。注意Create Session节点的Local Player参数通常需要传入一个Player Controller的引用。在GameInstance中我们可能还没有可用的Player Controller。一个常见的做法是在调用Create Session之前先通过Get First Local Player Controller节点获取一个控制器引用传入。如果是在游戏开始前如主菜单调用可能需要更复杂的处理但为了简化我们可以在确保有一个本地玩家存在的情况下调用。4.2 查找与加入会话作为客户端客户端需要先查找局域网内存在的会话然后选择加入。查找会话搜索节点“Find Sessions”。同样使用高级版本“Find Sessions (Advanced)”。关键参数Max Results最大结果数例如10Use LAN必须勾选为true。它也是一个异步操作完成后触发On Find Sessions Complete事件。这个事件会输出一个Session Results数组包含了所有找到的会话信息。处理查找结果在On Find Sessions Complete绑定的自定义事件中你可以遍历Session Results数组。每个结果Blueprint Session Result类型都有Session属性里面包含了Session Name、Current Players、Max Players、Ping等信息。你可以将这些信息更新到你的UI列表上供玩家选择。加入会话当玩家从UI列表中选择一个会话后调用“Join Session (Advanced)”节点。关键参数传入选中的那个Blueprint Session Result对象。同样它触发On Join Session Complete事件。在这个事件的处理中如果加入成功bWas Successful为真不能直接使用Open Level。正确的做法是使用“Get Resolved Connect String”节点传入Session Name和Search Result即之前传入的Blueprint Session Result获取到一个连接字符串。然后使用“Client Travel”节点让玩家的客户端旅行到主机所在的关卡。Client Travel节点的Server Address参数就填刚才获取的连接字符串。引擎会自动处理连接和关卡加载。4.3 蓝图节点连接与错误处理要点异步回调Online Subsystem 的大部分关键操作都是异步的。这意味着你调用一个函数后不会立即得到结果而是需要等待回调事件。务必确保所有可能的执行路径成功和失败都有对应的处理逻辑比如查找失败时显示“未找到游戏”加入失败时提示“加入失败房间可能已满”。变量存储建议在GameInstance中定义一些变量来存储关键状态例如CurrentSessionName(String)当前会话名。FoundSessions(Array of Blueprint Session Result)存储查找到的会话列表。LastJoinResult(Blueprint Session Result)最后一次尝试加入的会话结果。清理工作当玩家退出到主菜单时如果之前创建了会话作为主机应该调用“Destroy Session”节点来清理网络资源避免端口占用等问题。5. 游戏内网络同步实现成功加入同一个会话后玩家角色需要在不同机器间同步。这里我们实现最基本的移动同步。5.1 玩家角色复制设置我们之前已经将BP_NetworkPlayer的“复制”属性设为“是”。这确保了Actor本身的存在性被同步。但Actor内部变量的变化需要额外设置。打开BP_NetworkPlayer蓝图。在事件图表中默认会有Event BeginPlay和Event Tick。角色的移动组件Character Movement Component默认已经处理了移动的复制。只要你使用Add Movement Input等标准方式驱动角色在服务器端控制角色移动其位置和旋转会自动同步到所有客户端。验证为了测试我们可以在BP_NetworkPlayer的Event BeginPlay中打印一行日志并区分是在服务器还是客户端执行。Branch (Has Authority) True - Print String (Text: I am the Server!) (Text Color: Green) False - Print String (Text: I am a Client!) (Text Color: Red)Has Authority节点判断当前是否在服务器上运行。打包后主机的这个角色实例在服务器端会打印绿色文字在客户端看到的自己和其他玩家的这个角色实例会打印红色文字。5.2 自定义变量的复制假设你想同步角色的生命值。在BP_NetworkPlayer的变量面板创建一个Float类型变量命名为Health默认值设为100.0。选中这个变量在细节面板中找到“复制”选项将其设置为“复制”。这样当服务器端的Health值改变时会自动同步给所有客户端。你可以创建一个函数TakeDamage在服务器端使用Run on Server函数标记或检查Has Authority修改Health的值。客户端会看到这个值自动更新。5.3 RPC远程过程调用的使用对于不需要持续同步、而是由特定事件触发的逻辑需要使用RPC。例如角色播放一个特殊的攻击动画。创建自定义事件在BP_NetworkPlayer中创建一个自定义事件命名为PlayAttackMontage_Net。设置复制在该事件的细节面板中将“复制”下拉菜单选择为“在服务器上运行”如果逻辑应由客户端触发在服务器执行或“多播”在服务器和所有客户端上执行。对于播放动画这种视觉效果通常使用“多播”。调用在角色执行攻击的逻辑处比如按鼠标左键的事件不要直接播放动画而是调用PlayAttackMontage_Net事件。如果这个事件被标记为“多播”那么调用后服务器会接收到然后服务器将这个事件转发给所有连接的客户端所有机器上的这个角色都会播放攻击动画。实操心得网络同步的核心原则是“服务器权威”。任何影响游戏核心状态的决定如是否命中、造成多少伤害都必须在服务器端计算和验证。客户端只负责发送输入请求和表现效果。蓝图中的Has Authority节点是你的好朋友经常用它来区分逻辑应该在哪儿执行。6. 双机部署与联调实战蓝图写好了现在是真刀真枪测试的时候。你需要两台处于同一局域网的电脑。如果没有第二台物理电脑使用虚拟机如VMware或VirtualBox安装Windows系统并桥接网络也是一个非常好的选择。6.1 项目打包在UE5编辑器中点击“文件” - “打包项目” - “目标平台”选择Windows 64位。选择一个输出目录如D:\Build。打包过程可能需要一段时间。打包完成后在输出目录例如D:\Build\Windows下你会找到游戏的.exe文件以及Content等文件夹。将这个完整的构建文件夹复制到另一台测试机器上。6.2 主机服务器启动在第一台机器我们称之为主机上找到打包好的可执行文件如MyProject.exe。不要直接双击运行。为了能传递启动参数我们需要创建一个快捷方式。右键点击.exe文件选择“创建快捷方式”。然后右键点击新创建的快捷方式选择“属性”。在“目标”栏的末尾先加一个空格然后添加以下参数-server -log-server以独立服务器模式运行不显示客户端窗口。对于我们的测试主机通常也需要一个客户端窗口来操作所以我们可以不用这个参数而是让主机程序自己既当服务器又当客户端。更清晰的做法是主机也通过我们的游戏UI来“创建游戏”。因此主机可以直接运行游戏进入主菜单点击“创建游戏”。-log非常重要它会打开一个控制台窗口输出详细的日志信息包括网络连接状态、错误信息等是调试的利器。运行这个带参数的快捷方式或者直接运行游戏进入主菜单。6.3 客户端启动与连接在第二台机器上直接运行游戏可执行文件不需要-server参数。进入游戏主菜单假设你已制作了简单的UI按钮来调用我们之前在GameInstance里写的Find Sessions和Join Session函数。点击“查找游戏”或类似按钮。你的蓝图逻辑应该会搜索局域网内的会话。在找到的会话列表中选择主机创建的游戏点击“加入”。如果一切配置正确客户端会加载关卡并看到主机控制的角色反之亦然。6.4 关键检查与验证步骤防火墙确保两台电脑的Windows防火墙允许你的游戏可执行文件通过。首次运行时防火墙会弹出提示务必选择“允许”。如果没弹出可以手动在防火墙设置中添加入站规则。IP地址确保两台机器在同一个子网内如都是192.168.1.x。可以在命令行输入ipconfig查看。查看日志主机和客户端都带上-log参数运行观察控制台输出。寻找关键词如“LogNet: Join succeeded”、“LogOnline: STEAM: Creating LAN session”等成功信息或“Error”、“Timeout”等错误信息。网络调试命令在游戏运行时按“~”波浪号键打开控制台输入stat net显示详细的网络统计数据包括Ping、丢包率、带宽使用等。这是评估网络状况的黄金标准。netdebug显示当前连接的所有客户端和服务器信息。travellog显示关卡旅行日志。7. 常见问题排查与调试技巧实录即使按照步骤操作你也可能会遇到问题。这里记录了我踩过的坑和解决方案。7.1 问题客户端找不到主机创建的游戏可能原因1防火墙阻止。这是最常见的原因。排查暂时完全关闭两台电脑的防火墙仅用于测试完成后请恢复看是否能找到。如果可以说明是防火墙问题。解决为你的游戏.exe在防火墙中创建专用的入站规则允许UDP和TCP协议Online Subsystem Null 主要用UDP。可能原因2Session创建未成功。排查查看主机运行时的日志-log确认是否有“Create Session succeeded”或类似信息。检查OnCreateSessionComplete事件中的bWasSuccessful是否为真。解决确保在调用Create Session前Use LAN参数已设置为true。检查传入的Local Player参数是否有效。可能原因3网络发现服务问题。排查确保两台机器的网络发现和文件共享功能是开启的在Windows网络设置中。解决尝试使用Find Sessions节点的非高级版本或者检查Max Search Results是否设置得太小。7.2 问题客户端加入游戏后卡在加载界面或黑屏可能原因1关卡路径或名称错误。排查主机在创建会话后通过Open Level打开的关卡名称必须与客户端通过Client Travel连接的关卡完全一致包括大小写。最好将关卡路径存储在一个变量或会话设置中。解决使用Get Map Display Name节点获取关卡的准确名称并使用这个名称进行旅行。可能原因2客户端没有该关卡的资源。排查打包时确保所有用到的地图都包含在打包列表中在项目设置-打包中检查。解决重新打包并确保“将地图列表复制到打包设置”选项被勾选或者手动在“要打包的地图”列表中添加你的测试关卡。可能原因3网络端口冲突或阻塞。排查查看日志中是否有“Connection failed”或“Port in use”错误。解决默认情况下UE使用7777端口UDP进行游戏通信7778端口TCP/UDP用于信令。确保这些端口没有被其他程序占用。可以在DefaultEngine.ini中修改[/Script/OnlineSubsystemUtils.IpNetDriver]下的Port配置。7.3 问题角色移动不同步或抖动可能原因1网络更新频率。排查使用stat net查看更新频率。角色移动组件的同步由网络更新频率控制。解决在角色蓝图的Character Movement组件细节面板中可以调整Net Update Frequency网络更新频率默认100Hz和Min Net Update Frequency最小更新频率。对于局域网保持默认通常即可。如果抖动可能是网络延迟或丢包导致的外插值问题可以尝试稍微降低Net Update Frequency。可能原因2未在服务器端执行移动逻辑。排查确保驱动角色移动的输入事件如InputAxis MoveForward是在服务器端处理的或者移动本身是由服务器权威的组件如Character Movement处理的。解决检查移动逻辑是否被包裹在Run on Server的执行路径中或者确保输入是在玩家控制的Pawn上处理的引擎会自动将其发送到服务器。7.4 高级调试技巧网络模拟在编辑器中即使进行双机测试你也可以使用网络模拟功能来模拟恶劣的网络环境。在编辑器运行时的控制台输入Net PktLoss10可以模拟10%的丢包Net Lag200可以模拟200毫秒的延迟。这能帮你提前发现一些只在网络状况差时才出现的问题。Visual LoggerUE5的Visual Logger是强大的网络调试工具。在编辑器运行时你可以暂停游戏然后从主工具栏的“调试”菜单中打开“Visual Logger”。它能可视化地显示角色复制、RPC调用、属性同步等事件让你清晰地看到网络流量和事件发生的时间线。网络角色Role查看在游戏运行时可以在场景中选中一个Actor在“世界大纲视图”或“细节”面板中查看其Net Role网络角色。ROLE_Authority表示服务器端ROLE_SimulatedProxy或ROLE_AutonomousProxy表示客户端。这有助于理解每个Actor在谁那里执行逻辑。双机局域网联调是多人游戏开发从“玩具”走向“产品”的关键一步。它暴露的问题是PIE环境永远无法给你的宝贵经验。虽然初期搭建会有些繁琐但一旦流程跑通它将成为你开发周期中最可靠的测试环节。别怕麻烦现在就去配置你的两台机器把蓝图部署上去亲眼看看角色在另一台屏幕上动起来的那一刻你会对网络游戏的理解深刻得多。