1. 项目概述为什么要在本地折腾Photon Server如果你刚开始接触Unity网络游戏开发可能听过Photon这个名字。它是一个非常流行的实时多人游戏网络引擎很多独立开发者和中小团队都在用。官方提供了云服务直接调用API就能快速搭建联机功能这很方便。但问题来了对于新手来说直接上云很多底层逻辑是黑箱出了问题你根本不知道是代码写错了还是网络配置有问题或者是服务器本身抽风了。调试起来像在抓瞎。所以我强烈建议新手甚至是有一定经验的开发者在项目初期或者学习阶段先在本地把Photon Server搭起来。这就像学开车你不能只在模拟器上练得真车摸一摸知道引擎盖下面是什么结构出了问题才知道该看哪里。本地搭建Photon Server能让你彻底搞清楚一个联机请求从客户端发出到服务器处理再返回客户端的完整生命周期。你会明白配置文件怎么写日志怎么看端口怎么开连接失败到底卡在哪一步。这个过程里踩的每一个坑都是实打实的经验以后项目上线用云服务你心里也有底排查问题快人一步。这次我就带你走一遍Photon Server本地搭建与连接测试的完整流程从下载、配置、运行到Unity客户端连接最后附上我这些年总结的常见问题排查清单。目标很明确让你在自己的电脑上跑通第一个Photon联机Demo并理解背后的每一个环节。2. 核心思路与工具选型解析2.1 Photon Server的核心组件与工作原理在动手之前我们得先搞明白Photon Server是个什么东西。简单来说它不是一个单一的“服务器程序”而是一个服务器端框架。它帮你处理了网络通信中最复杂、最底层的部分比如TCP/UDP连接管理、数据包的序列化与反序列化、线程调度、房间管理等让你可以专注于游戏逻辑本身。Photon Server通常包含以下几个核心部分Photon Socket Server这是通信的核心负责管理客户端连接。Photon Applications你的游戏服务器逻辑就写在这里。比如一个“MMO应用”或者“棋牌游戏应用”。配置文件和日志系统用来定义服务器行为、端口、应用路径以及记录运行状态。本地搭建就是把Photon Server的这套框架运行在你自己的Windows电脑上让你的Unity客户端也运行在同一台或局域网内的电脑上能够连接进来模拟真实的网络环境。2.2 为什么选择Photon PUN/Quantum还是Photon ServerPhoton旗下有几个产品新手容易混淆。这里简单区分一下Photon PUN (Photon Unity Networking)这是一个托管服务。你几乎不需要关心服务器它提供了一个高级别的API专注于房间管理和状态同步非常适合快速原型和中小型实时游戏如休闲竞技、棋牌。你写的逻辑大部分在客户端。Photon Quantum这是一个确定性的锁步模拟框架用于需要极高同步精度和反作弊的竞技游戏如MOBA、RTS。它很强大但学习曲线陡峭。Photon Server (On-Premises)这就是我们今天要弄的自托管服务器。你需要自己部署和运行服务器程序拥有完全的控制权。适合需要深度定制服务器逻辑、处理复杂业务、或对数据安全和延迟有极高要求的项目。学习它你对网络层的理解会深刻得多。对于新手学习网络原理Photon Server是更底层、更彻底的选择。理解了它再去看PUN你会觉得豁然开朗。2.3 本地环境准备清单在开始前请确保你的开发环境满足以下要求操作系统Windows 10 或 Windows 11。Photon Server原生支持Windows。虽然理论上可以在Linux上用Mono运行但对于新手强烈建议用Windows避免不必要的兼容性问题。Unity版本2019.4 LTS 或更新版本推荐2021.3 LTS或2022.3 LTS。LTS版本更稳定社区资源也多。Photon Server SDK你需要从Photon官网下载Photon Server SDK。注意它有免费版支持最多20个并发连接对于学习和测试完全够用。.NET Framework确保你的Windows已安装 .NET Framework 4.7 或更高版本。通常Win10/11已自带但最好检查一下。文本编辑器推荐VS Code或Notepad用于修改配置文件。记事本也行但编码容易出问题。注意下载Photon Server SDK可能需要注册一个Exit Games账户。这是正规的开发者注册过程很简单。3. Photon Server本地部署详解3.1 下载、解压与目录结构解析首先去Photon官网找到“Photon Server SDK”的下载页面。下载完成后你会得到一个类似Photon-OnPremise-Server-SDK_v5-0-xxx.zip的压缩包。把它解压到一个你容易找到的路径切记路径不要包含中文或特殊字符比如D:\PhotonServer。解压后目录结构大致如下PhotonServer/ ├── deploy/ # 这是核心部署目录我们主要操作这里 │ ├── bin/ # 服务器运行所需的核心动态库 │ ├── lib/ # 依赖库 │ ├── log/ # 日志文件输出目录启动后生成 │ ├── PhotonControl.exe # 服务器控制台图形界面 │ └── PhotonSocketServer.exe # 核心Socket服务器进程 ├── src-server/ # 服务器端应用示例源码C# ├── lib/ # 开发依赖库 └── doc/ # 官方文档我们绝大部分工作都在deploy文件夹里。3.2 关键配置文件PhotonServer.configdeploy目录下的PhotonServer.config是服务器的大脑。用文本编辑器打开它。这个XML文件结构清晰我们重点关注几个部分?xml version1.0 encodingutf-8? configuration applicationSettings Photon.SocketServer.PhotonServerSettings !-- 1. 应用根目录 -- setting nameApplicationRootPath serializeAsString value./value !-- 点号代表当前目录deploy也可以设绝对路径 -- /setting !-- 2. 要加载的应用 -- setting nameApplicationsToDeploy serializeAsString !-- 这里列出了服务器启动时要加载的应用对应deploy下的子目录 -- valueMyGameServer/value /setting !-- 3. 性能与日志配置 -- setting nameEnablePerformanceCounters serializeAsString valuetrue/value /setting setting nameLogPath serializeAsString valuelog/value !-- 日志输出到deploy/log目录 -- /setting /Photon.SocketServer.PhotonServerSettings /applicationSettings /configurationApplicationRootPath 指定应用查找的根目录。保持.即可表示应用在deploy目录下寻找。ApplicationsToDeploy 这是最关键的配置。它告诉Photon Server启动时去加载哪个或哪些应用。这里的MyGameServer对应deploy目录下的一个名为MyGameServer的文件夹。一个Photon Server可以同时承载多个不同的游戏应用。LogPath 日志输出目录。出问题时第一时间看这里。3.3 创建你的第一个服务器应用ApplicationPhoton Server的应用是以文件夹形式存在的。在deploy目录下新建一个文件夹名字必须和你在PhotonServer.config的ApplicationsToDeploy里设置的一致比如MyGameServer。然后在这个MyGameServer文件夹里你需要创建几个必要的文件MyGameServer.dll 这是你的服务器端游戏逻辑编译后的程序集。对于新手我们可以先用Photon自带的示例应用。在src-server目录里找到LoadBalancing示例用Visual Studio打开并编译将生成的LoadBalancing.dll和ExitGamesLibs.dll复制到MyGameServer文件夹并把LoadBalancing.dll改名为MyGameServer.dll。这是最快上手的办法。MyGameServer.dll.config 这是你的应用的配置文件通常从示例中复制过来修改。它定义了应用监听的端口和协议。让我们重点看一下这个MyGameServer.dll.config?xml version1.0 encodingutf-8? configuration configSections section namePhoton typePhoton.SocketServer.PhotonSettings, Photon.SocketServer/ /configSections Photon Application !-- 应用名称用于日志标识 -- NameMyGameServer/Name /Application SocketServer !-- 监听的IP0.0.0.0表示监听所有网络接口 -- ListenIP0.0.0.0/ListenIP !-- 游戏通信端口客户端将连接这个端口 -- GameServerPort5055/GameServerPort GameServerAddress0.0.0.0/GameServerAddress ProtocolUdp/Protocol !-- 也可以是 Tcp -- !-- WebSocket端口用于WebGL等 -- WebSocketPort9090/WebSocketPort /SocketServer /Photon /configurationGameServerPort 这是默认的游戏通信端口记住它比如5055。你的Unity客户端就要连接这个端口。Protocol 协议类型。Udp更快适合实时动作游戏但可能丢包Tcp可靠适合回合制或指令型游戏。新手可以先从Udp开始。WebSocketPort 如果你未来要做WebGL游戏需要用到这个端口。3.4 启动服务器与验证运行状态配置好后回到deploy目录双击运行PhotonControl.exe。你会看到一个控制台窗口弹出这是Photon Server的图形化管理界面。在Photon Control界面你应该能看到一个名为Photon Socket Server的服务。选中它点击右侧的Run按钮。如果一切正常状态会从Stopped变为Running并且下方的日志区域会开始滚动信息显示应用MyGameServer已被加载并在监听端口5055。验证服务器是否真的在监听打开命令提示符CMD输入命令netstat -ano | findstr :5055。如果看到类似TCP 0.0.0.0:5055 0.0.0.0:0 LISTENING的行说明服务器进程已经在5055端口上成功监听这是最关键的一步。实操心得第一次启动时Windows防火墙很可能会弹出警告询问是否允许PhotonSocketServer.exe通过防火墙。务必选择“允许访问”包括私有网络和公共网络。如果错过了弹窗导致连接失败需要手动去Windows防火墙设置里添加入站规则。4. Unity客户端连接配置与测试服务器跑起来了现在我们来让Unity客户端连接它。4.1 导入Photon Unity Networking (PUN) 或 Realtime SDK在Unity中你需要导入Photon的客户端SDK。虽然我们服务器用的是Photon Server但客户端连接通常使用Photon Realtime SDK更底层更灵活或PUN 2更高级更方便。为了理解原理我建议从Photon Realtime SDK开始。在Unity Asset Store中搜索 “Photon Realtime” 或 “PUN 2”下载并导入到你的空项目中。导入后Unity会弹出设置向导。你需要一个Photon AppId。这个Id对于云服务是唯一的但对于我们本地服务器可以随意填写一个比如my-local-test-app。因为本地服务器不验证这个Id它只是客户端配置的一部分。当然你也可以在Photon官网创建一个免费账户获取一个真实的AppId这对于以后过渡到云服务有好处。4.2 配置连接参数AppId、服务器地址、端口关键步骤来了告诉Unity客户端不去连Photon的云服务器而是连我们本地的服务器。找到导入SDK后生成的PhotonServerSettings文件通常在Resources文件夹下。在Inspector面板中你需要修改几个字段AppId Realtime 填写你刚才在向导里设置的AppId或者任意字符串。Server 从默认的Photon Cloud切换到Master Server或Name Server。对于本地服务器我们通常直接指定服务器地址和端口所以这个设置影响不大但为了清晰可以选Master Server。Host Type 选择Self Hosted。这是最重要的设置表明我们要连接自托管服务器。Master Server Address 填写你的本地IP地址。不要填localhost或127.0.0.1除非你的Unity编辑器也和服务器在同一台机器的同一个进程里运行这很复杂。通常你需要填写本机在局域网内的IP。在CMD中输入ipconfig找到IPv4 地址比如192.168.1.100。Master Server Port 填写我们在MyGameServer.dll.config中设置的GameServerPort即5055。Protocol 选择与服务器配置一致的协议比如Udp。4.3 编写最简单的连接测试脚本创建一个空的GameObject挂载一个新的C#脚本比如叫NetworkManager。using UnityEngine; using Photon.Realtime; // 使用Realtime命名空间 using UnityEngine.UI; public class NetworkManager : MonoBehaviour, IConnectionCallbacks { [SerializeField] private Text connectionStatusText; private LoadBalancingClient lbc; void Start() { // 1. 创建LoadBalancingClient实例 lbc new LoadBalancingClient(); // 2. 添加回调接口this lbc.AddCallbackTarget(this); // 3. 设置AppId从PhotonServerSettings读取 lbc.AppId PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime; // 4. 设置服务器地址和端口覆盖云设置指向本地 lbc.LoadBalancingPeer.ServerAddress “192.168.1.100”; // 你的本地IP lbc.LoadBalancingPeer.ServerPort 5055; // 你的服务器端口 // 5. 设置协议 lbc.LoadBalancingPeer.TransportProtocol ExitGames.Client.Photon.ConnectionProtocol.Udp; // 6. 开始连接 if (!lbc.ConnectToMasterServer()) { Debug.LogError(“连接初始化失败”); UpdateStatus(“连接初始化失败”); } else { UpdateStatus(“正在连接...”); } } void Update() { // 必须定期调用Service()方法处理网络消息 lbc?.Service(); } void UpdateStatus(string status) { if (connectionStatusText ! null) connectionStatusText.text status; Debug.Log(status); } // 以下是IConnectionCallbacks接口的实现 public void OnConnected() { UpdateStatus(“已连接到服务器”); } public void OnConnectedToMaster() { UpdateStatus(“已连接到Master服务器”); // 连接成功后可以加入或创建房间 // lbc.OpJoinRandomRoom(); } public void OnDisconnected(DisconnectCause cause) { UpdateStatus($“连接断开原因{cause}”); } // 其他接口方法需要空实现否则会报错 public void OnRegionListReceived(RegionHandler regionHandler) {} public void OnCustomAuthenticationResponse(Dictionarystring, object data) {} public void OnCustomAuthenticationFailed(string debugMessage) {} }将这个脚本挂载到场景中的物体上并将一个UI Text组件拖拽赋值给connectionStatusText。运行Unity如果一切顺利你将看到文本显示“已连接到Master服务器”。4.4 连接测试与基础交互验证连接成功只是第一步。我们可以写一个简单的RPC远程过程调用来测试双向通信。在服务器端示例DLL中 我们已经使用了LoadBalancing示例它内置了基本的房间管理和RPC支持。在客户端 修改NetworkManager脚本在OnConnectedToMaster方法后加入创建房间和发送RPC的代码。// 在OnConnectedToMaster方法内 public void OnConnectedToMaster() { UpdateStatus(“已连接到Master服务器”); // 创建房间选项 EnterRoomParams roomParams new EnterRoomParams(); roomParams.RoomOptions new RoomOptions(); roomParams.RoomOptions.MaxPlayers 4; roomParams.RoomOptions.IsVisible true; roomParams.RoomOptions.IsOpen true; // 创建房间 if (lbc.OpCreateRoom(roomParams)) { UpdateStatus(“正在创建房间...”); } } // 实现IMatchmakingCallbacks接口需要让类继承它 public void OnCreatedRoom() { UpdateStatus(“房间创建成功”); // 房间创建成功后可以发送一个测试RPC SendTestRpc(); } void SendTestRpc() { // 使用OpRaiseEvent发送一个自定义事件 Hashtable customEventContent new Hashtable(); customEventContent[“message”] “Hello from Client!”; lbc.OpRaiseEvent(200, customEventContent, new RaiseEventOptions(), SendOptions.SendReliable); UpdateStatus(“已发送测试事件”); }同时你需要在服务器端示例应用中有相应的代码来处理事件码为200的事件。在LoadBalancing示例的GameApplication类中可以找到处理客户端事件的开关语句。通过这样的测试你能确认数据已经从客户端发出并被服务器接收处理。5. 本地联机调试与进阶配置5.1 在同一台机器上运行多个客户端进行测试真正的多人游戏需要多个客户端。在Unity编辑器中你可以使用ParrelSync这个免费资产来克隆项目实现同一台机器上运行多个编辑器实例进行联机测试。这是本地开发的神器。从Asset Store导入ParrelSync。通过它的菜单克隆当前项目。在克隆的项目中修改客户端脚本让玩家有不同的表现比如生成不同颜色的Cube。分别运行原项目和克隆项目它们都能连接到你的本地Photon Server并看到彼此。5.2 局域网内多设备连接测试如果你想用手机或另一台电脑测试就需要确保它们和服务器主机在同一个局域网连接同一个Wi-Fi。关闭防火墙或配置规则 在服务器主机上确保Windows防火墙允许PhotonSocketServer.exe通过公共网络如果你的局域网被识别为公共网络。更稳妥的方法是直接暂时关闭防火墙仅测试时或者创建详细的入站规则开放UDP/TCP的5055端口。获取服务器主机IP 在服务器主机上运行ipconfig记住IPv4地址。修改客户端配置 在测试设备手机或其他电脑的Unity构建版本或编辑器中将Master Server Address修改为服务器主机的IP地址如192.168.1.100端口仍是5055。连接测试 运行客户端应该就能成功连接了。5.3 服务器日志分析与性能监控调试网络问题日志是你的第一手资料。Photon Server的日志默认输出在deploy/log目录下按日期和应用程序分文件。Photon-20240101.log 主服务器日志记录服务启动、停止、应用加载等信息。MyGameServer-20240101.log 你的游戏应用日志记录客户端的连接、断开、房间操作、自定义事件等。当客户端连接失败时打开对应的日志文件搜索错误信息如Error,Exception,Failed。常见的错误会明确告诉你原因比如Address already in use端口被占用、Unable to bind to port权限不足或防火墙阻止。此外在PhotonControl界面你可以看到简单的性能计数器如连接数、消息吞吐量。对于更深入的性能分析可以考虑将日志集成到如Log4Net等框架并输出到更专业的监控工具。6. 常见问题排查与解决方案实录本地搭建过程中90%的问题都出在配置和网络环境上。下面是我总结的“踩坑大全”按从外到内的顺序排查基本能解决所有问题。6.1 连接失败类问题问题现象可能原因排查步骤与解决方案Unity客户端报错Failed to connect to server1. 服务器未启动。2. IP地址或端口错误。3. 防火墙阻止。1.检查服务器状态确认PhotonControl中Photon Socket Server状态为Running且日志显示应用已加载。2.检查端口监听在服务器CMD运行netstat -ano | findstr :5055确认有进程在监听。3.检查客户端配置核对Master Server Address是否为服务器主机的局域网IP非127.0.0.1端口是否为5055。4.关闭防火墙测试临时关闭服务器主机的Windows Defender防火墙重试连接。如果成功则需配置防火墙入站规则。连接超时无任何响应1. 网络不通。2. 客户端协议与服务器不一致。1.Ping测试在客户端设备上ping服务器IP看是否通。2.检查协议确保服务器MyGameServer.dll.config中的Protocol与Unity客户端PhotonServerSettings或代码中设置的TransportProtocol完全一致都是Udp或都是Tcp。能连接Master但无法加入/创建房间1. 服务器端应用逻辑错误或未正确加载。2. 客户端AppId与服务器端不匹配本地模式下通常不校验但自定义逻辑可能校验。1.查看应用日志检查deploy/log/MyGameServer-xxx.log看是否有关于房间操作的错误。2.使用官方示例DLL确保你使用的MyGameServer.dll是来自LoadBalancing示例并正确编译的避免自己写的逻辑有Bug。3.简化测试先只用最基本的连接功能确保网络层通畅再逐步添加房间逻辑。6.2 服务器启动与运行类问题问题现象可能原因排查步骤与解决方案PhotonControl点击Run后立刻停止1. 端口被占用。2. 配置文件有语法错误。3. 依赖的DLL缺失或版本不对。1.检查端口占用用netstat -ano | findstr :5055查看5055端口是否已被其他程序如Skype、IIS、其他游戏服务占用。如果被占修改MyGameServer.dll.config中的端口号并同步修改客户端配置。2.检查配置文件用XML验证工具检查PhotonServer.config和MyGameServer.dll.config的格式是否正确标签是否闭合。3.检查DLL确认deploy/bin和deploy/MyGameServer目录下所有必需的DLL文件都存在特别是ExitGamesLibs.dll是否与MyGameServer.dll版本匹配。日志中报错Could not load file or assembly...服务器应用依赖的某个程序集找不到。1.查看完整错误信息日志会明确指出缺失哪个DLL。2.复制依赖项从src-server对应示例的编译输出目录通常是bin/Debug或bin/Release将所有.dll文件除了MyGameServer.dll复制到deploy/MyGameServer目录下。确保deploy/bin目录下也有Photon核心库。服务器运行一段时间后崩溃1. 内存泄漏自定义逻辑导致。2. 异常未处理。1.分析崩溃日志查看日志最后几行的异常堆栈信息。2.使用示例DLL测试如果使用官方示例也崩溃可能是环境问题。如果只有自定义DLL崩溃需检查自己的服务器端代码特别是循环引用、静态变量、事件订阅未取消等问题。6.3 数据通信与同步类问题问题现象可能原因排查步骤与解决方案客户端发送RPC/事件其他客户端收不到1. 事件代码未在服务器端注册或处理。2. 发送的目标Target设置错误。3. 客户端未正确实现事件接收回调。1.服务器端处理确保在服务器的GameApplication或相关类中有处理对应EventCode的switch-case逻辑并且正确地将事件转发Broadcast给其他玩家。2.检查RaiseEventOptions确认RaiseEventOptions中的Receivers设置正确例如ReceiverGroup.Others或ReceiverGroup.All。3.客户端订阅在客户端确保通过lbc.OpAddCallbackTarget添加了实现了IOnEventCallback接口的对象并在OnEvent方法中处理事件。移动同步延迟高或抖动1. 网络延迟本身。2. 发送频率过高或过低。3. 未使用插值或外推。1.本地测试排除网络问题同一台机器两个客户端测试如果延迟仍高则是逻辑问题。2.优化发送频率不要每帧发送位置可以定时如每秒10-15次或在位置变化超过阈值时发送。3.在客户端实现插值收到其他玩家的位置更新后不是直接transform.position newPosition而是平滑地移动到目标位置。这是客户端预测与平滑的范畴PUN等高级库内置了这些功能。6.4 防火墙与网络配置终极指南这是新手最大的拦路虎。请严格按照以下步骤操作添加入站规则推荐打开“Windows Defender 防火墙与高级安全”。点击“入站规则” - “新建规则”。规则类型选择“程序”。程序路径浏览到deploy\PhotonSocketServer.exe。操作选择“允许连接”。配置文件全选域、专用、公用。名称起一个名字如“Photon Server”。同样步骤为deploy\bin\PhotonSocketServer.exe如果存在也添加规则。开放特定端口备用方案同上新建入站规则。规则类型选择“端口”。协议和端口选择“UDP”或“TCP”特定本地端口填入5055以及你用到的其他端口如9090。后续步骤同上。检查网络类型有时Windows会将家庭网络误识别为“公用网络”而防火墙对公用网络的限制更严格。确保你的网络配置文件是“专用网络”。踩坑实录我最常遇到的情况是在笔记本上开发白天连着公司Wi-Fi公用网络测试正常晚上回家连家里Wi-Fi专用网络反而连不上了。就是因为防火墙规则只允许了“公用网络”而家里是“专用网络”。所以创建规则时一定要“域、专用、公用”三个全勾选。7. 从本地到云下一步的学习路径当你成功在本地搭建并连接Photon Server后你已经掌握了网络游戏开发最核心的基础。接下来可以沿着这几个方向深化深入服务器逻辑开发 不再使用示例DLL尝试用Visual Studio创建自己的Photon服务器端应用项目。学习Photon.SocketServer命名空间下的核心类如PeerBase,ApplicationBase实现你自己的游戏循环、房间管理、自定义协议。学习PUN 2 理解了底层原理后再使用PUN 2进行开发会事半功倍。你会明白PhotonView,RPC,OnPhotonSerializeView这些高级抽象背后到底在做什么能更高效地使用它们也能更好地调试问题。部署到Linux服务器 实际项目上线通常会使用Linux服务器。研究如何在Linux上通过Mono或 .NET Core运行Photon Server学习基本的运维命令和监控。集成数据库与后端服务 在服务器端逻辑中接入MySQL、Redis等数据库处理玩家数据持久化、排行榜、邮件系统等。压力测试与优化 使用工具模拟大量客户端连接测试你的服务器逻辑能承受多少并发找出性能瓶颈并进行优化。本地搭建Photon Server的过程就像在学游泳时先在浅水区扑腾。虽然一开始会喝几口水但当你熟悉了水性知道了如何换气、如何划水再进入深水区云端部署、复杂逻辑时你心里是踏实的。这个过程积累的经验和直觉是只看文档和教程无法获得的。希望这篇超详细的指南能帮你顺利渡过新手期少走些弯路。
Photon Server本地部署与Unity客户端连接完整指南
1. 项目概述为什么要在本地折腾Photon Server如果你刚开始接触Unity网络游戏开发可能听过Photon这个名字。它是一个非常流行的实时多人游戏网络引擎很多独立开发者和中小团队都在用。官方提供了云服务直接调用API就能快速搭建联机功能这很方便。但问题来了对于新手来说直接上云很多底层逻辑是黑箱出了问题你根本不知道是代码写错了还是网络配置有问题或者是服务器本身抽风了。调试起来像在抓瞎。所以我强烈建议新手甚至是有一定经验的开发者在项目初期或者学习阶段先在本地把Photon Server搭起来。这就像学开车你不能只在模拟器上练得真车摸一摸知道引擎盖下面是什么结构出了问题才知道该看哪里。本地搭建Photon Server能让你彻底搞清楚一个联机请求从客户端发出到服务器处理再返回客户端的完整生命周期。你会明白配置文件怎么写日志怎么看端口怎么开连接失败到底卡在哪一步。这个过程里踩的每一个坑都是实打实的经验以后项目上线用云服务你心里也有底排查问题快人一步。这次我就带你走一遍Photon Server本地搭建与连接测试的完整流程从下载、配置、运行到Unity客户端连接最后附上我这些年总结的常见问题排查清单。目标很明确让你在自己的电脑上跑通第一个Photon联机Demo并理解背后的每一个环节。2. 核心思路与工具选型解析2.1 Photon Server的核心组件与工作原理在动手之前我们得先搞明白Photon Server是个什么东西。简单来说它不是一个单一的“服务器程序”而是一个服务器端框架。它帮你处理了网络通信中最复杂、最底层的部分比如TCP/UDP连接管理、数据包的序列化与反序列化、线程调度、房间管理等让你可以专注于游戏逻辑本身。Photon Server通常包含以下几个核心部分Photon Socket Server这是通信的核心负责管理客户端连接。Photon Applications你的游戏服务器逻辑就写在这里。比如一个“MMO应用”或者“棋牌游戏应用”。配置文件和日志系统用来定义服务器行为、端口、应用路径以及记录运行状态。本地搭建就是把Photon Server的这套框架运行在你自己的Windows电脑上让你的Unity客户端也运行在同一台或局域网内的电脑上能够连接进来模拟真实的网络环境。2.2 为什么选择Photon PUN/Quantum还是Photon ServerPhoton旗下有几个产品新手容易混淆。这里简单区分一下Photon PUN (Photon Unity Networking)这是一个托管服务。你几乎不需要关心服务器它提供了一个高级别的API专注于房间管理和状态同步非常适合快速原型和中小型实时游戏如休闲竞技、棋牌。你写的逻辑大部分在客户端。Photon Quantum这是一个确定性的锁步模拟框架用于需要极高同步精度和反作弊的竞技游戏如MOBA、RTS。它很强大但学习曲线陡峭。Photon Server (On-Premises)这就是我们今天要弄的自托管服务器。你需要自己部署和运行服务器程序拥有完全的控制权。适合需要深度定制服务器逻辑、处理复杂业务、或对数据安全和延迟有极高要求的项目。学习它你对网络层的理解会深刻得多。对于新手学习网络原理Photon Server是更底层、更彻底的选择。理解了它再去看PUN你会觉得豁然开朗。2.3 本地环境准备清单在开始前请确保你的开发环境满足以下要求操作系统Windows 10 或 Windows 11。Photon Server原生支持Windows。虽然理论上可以在Linux上用Mono运行但对于新手强烈建议用Windows避免不必要的兼容性问题。Unity版本2019.4 LTS 或更新版本推荐2021.3 LTS或2022.3 LTS。LTS版本更稳定社区资源也多。Photon Server SDK你需要从Photon官网下载Photon Server SDK。注意它有免费版支持最多20个并发连接对于学习和测试完全够用。.NET Framework确保你的Windows已安装 .NET Framework 4.7 或更高版本。通常Win10/11已自带但最好检查一下。文本编辑器推荐VS Code或Notepad用于修改配置文件。记事本也行但编码容易出问题。注意下载Photon Server SDK可能需要注册一个Exit Games账户。这是正规的开发者注册过程很简单。3. Photon Server本地部署详解3.1 下载、解压与目录结构解析首先去Photon官网找到“Photon Server SDK”的下载页面。下载完成后你会得到一个类似Photon-OnPremise-Server-SDK_v5-0-xxx.zip的压缩包。把它解压到一个你容易找到的路径切记路径不要包含中文或特殊字符比如D:\PhotonServer。解压后目录结构大致如下PhotonServer/ ├── deploy/ # 这是核心部署目录我们主要操作这里 │ ├── bin/ # 服务器运行所需的核心动态库 │ ├── lib/ # 依赖库 │ ├── log/ # 日志文件输出目录启动后生成 │ ├── PhotonControl.exe # 服务器控制台图形界面 │ └── PhotonSocketServer.exe # 核心Socket服务器进程 ├── src-server/ # 服务器端应用示例源码C# ├── lib/ # 开发依赖库 └── doc/ # 官方文档我们绝大部分工作都在deploy文件夹里。3.2 关键配置文件PhotonServer.configdeploy目录下的PhotonServer.config是服务器的大脑。用文本编辑器打开它。这个XML文件结构清晰我们重点关注几个部分?xml version1.0 encodingutf-8? configuration applicationSettings Photon.SocketServer.PhotonServerSettings !-- 1. 应用根目录 -- setting nameApplicationRootPath serializeAsString value./value !-- 点号代表当前目录deploy也可以设绝对路径 -- /setting !-- 2. 要加载的应用 -- setting nameApplicationsToDeploy serializeAsString !-- 这里列出了服务器启动时要加载的应用对应deploy下的子目录 -- valueMyGameServer/value /setting !-- 3. 性能与日志配置 -- setting nameEnablePerformanceCounters serializeAsString valuetrue/value /setting setting nameLogPath serializeAsString valuelog/value !-- 日志输出到deploy/log目录 -- /setting /Photon.SocketServer.PhotonServerSettings /applicationSettings /configurationApplicationRootPath 指定应用查找的根目录。保持.即可表示应用在deploy目录下寻找。ApplicationsToDeploy 这是最关键的配置。它告诉Photon Server启动时去加载哪个或哪些应用。这里的MyGameServer对应deploy目录下的一个名为MyGameServer的文件夹。一个Photon Server可以同时承载多个不同的游戏应用。LogPath 日志输出目录。出问题时第一时间看这里。3.3 创建你的第一个服务器应用ApplicationPhoton Server的应用是以文件夹形式存在的。在deploy目录下新建一个文件夹名字必须和你在PhotonServer.config的ApplicationsToDeploy里设置的一致比如MyGameServer。然后在这个MyGameServer文件夹里你需要创建几个必要的文件MyGameServer.dll 这是你的服务器端游戏逻辑编译后的程序集。对于新手我们可以先用Photon自带的示例应用。在src-server目录里找到LoadBalancing示例用Visual Studio打开并编译将生成的LoadBalancing.dll和ExitGamesLibs.dll复制到MyGameServer文件夹并把LoadBalancing.dll改名为MyGameServer.dll。这是最快上手的办法。MyGameServer.dll.config 这是你的应用的配置文件通常从示例中复制过来修改。它定义了应用监听的端口和协议。让我们重点看一下这个MyGameServer.dll.config?xml version1.0 encodingutf-8? configuration configSections section namePhoton typePhoton.SocketServer.PhotonSettings, Photon.SocketServer/ /configSections Photon Application !-- 应用名称用于日志标识 -- NameMyGameServer/Name /Application SocketServer !-- 监听的IP0.0.0.0表示监听所有网络接口 -- ListenIP0.0.0.0/ListenIP !-- 游戏通信端口客户端将连接这个端口 -- GameServerPort5055/GameServerPort GameServerAddress0.0.0.0/GameServerAddress ProtocolUdp/Protocol !-- 也可以是 Tcp -- !-- WebSocket端口用于WebGL等 -- WebSocketPort9090/WebSocketPort /SocketServer /Photon /configurationGameServerPort 这是默认的游戏通信端口记住它比如5055。你的Unity客户端就要连接这个端口。Protocol 协议类型。Udp更快适合实时动作游戏但可能丢包Tcp可靠适合回合制或指令型游戏。新手可以先从Udp开始。WebSocketPort 如果你未来要做WebGL游戏需要用到这个端口。3.4 启动服务器与验证运行状态配置好后回到deploy目录双击运行PhotonControl.exe。你会看到一个控制台窗口弹出这是Photon Server的图形化管理界面。在Photon Control界面你应该能看到一个名为Photon Socket Server的服务。选中它点击右侧的Run按钮。如果一切正常状态会从Stopped变为Running并且下方的日志区域会开始滚动信息显示应用MyGameServer已被加载并在监听端口5055。验证服务器是否真的在监听打开命令提示符CMD输入命令netstat -ano | findstr :5055。如果看到类似TCP 0.0.0.0:5055 0.0.0.0:0 LISTENING的行说明服务器进程已经在5055端口上成功监听这是最关键的一步。实操心得第一次启动时Windows防火墙很可能会弹出警告询问是否允许PhotonSocketServer.exe通过防火墙。务必选择“允许访问”包括私有网络和公共网络。如果错过了弹窗导致连接失败需要手动去Windows防火墙设置里添加入站规则。4. Unity客户端连接配置与测试服务器跑起来了现在我们来让Unity客户端连接它。4.1 导入Photon Unity Networking (PUN) 或 Realtime SDK在Unity中你需要导入Photon的客户端SDK。虽然我们服务器用的是Photon Server但客户端连接通常使用Photon Realtime SDK更底层更灵活或PUN 2更高级更方便。为了理解原理我建议从Photon Realtime SDK开始。在Unity Asset Store中搜索 “Photon Realtime” 或 “PUN 2”下载并导入到你的空项目中。导入后Unity会弹出设置向导。你需要一个Photon AppId。这个Id对于云服务是唯一的但对于我们本地服务器可以随意填写一个比如my-local-test-app。因为本地服务器不验证这个Id它只是客户端配置的一部分。当然你也可以在Photon官网创建一个免费账户获取一个真实的AppId这对于以后过渡到云服务有好处。4.2 配置连接参数AppId、服务器地址、端口关键步骤来了告诉Unity客户端不去连Photon的云服务器而是连我们本地的服务器。找到导入SDK后生成的PhotonServerSettings文件通常在Resources文件夹下。在Inspector面板中你需要修改几个字段AppId Realtime 填写你刚才在向导里设置的AppId或者任意字符串。Server 从默认的Photon Cloud切换到Master Server或Name Server。对于本地服务器我们通常直接指定服务器地址和端口所以这个设置影响不大但为了清晰可以选Master Server。Host Type 选择Self Hosted。这是最重要的设置表明我们要连接自托管服务器。Master Server Address 填写你的本地IP地址。不要填localhost或127.0.0.1除非你的Unity编辑器也和服务器在同一台机器的同一个进程里运行这很复杂。通常你需要填写本机在局域网内的IP。在CMD中输入ipconfig找到IPv4 地址比如192.168.1.100。Master Server Port 填写我们在MyGameServer.dll.config中设置的GameServerPort即5055。Protocol 选择与服务器配置一致的协议比如Udp。4.3 编写最简单的连接测试脚本创建一个空的GameObject挂载一个新的C#脚本比如叫NetworkManager。using UnityEngine; using Photon.Realtime; // 使用Realtime命名空间 using UnityEngine.UI; public class NetworkManager : MonoBehaviour, IConnectionCallbacks { [SerializeField] private Text connectionStatusText; private LoadBalancingClient lbc; void Start() { // 1. 创建LoadBalancingClient实例 lbc new LoadBalancingClient(); // 2. 添加回调接口this lbc.AddCallbackTarget(this); // 3. 设置AppId从PhotonServerSettings读取 lbc.AppId PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime; // 4. 设置服务器地址和端口覆盖云设置指向本地 lbc.LoadBalancingPeer.ServerAddress “192.168.1.100”; // 你的本地IP lbc.LoadBalancingPeer.ServerPort 5055; // 你的服务器端口 // 5. 设置协议 lbc.LoadBalancingPeer.TransportProtocol ExitGames.Client.Photon.ConnectionProtocol.Udp; // 6. 开始连接 if (!lbc.ConnectToMasterServer()) { Debug.LogError(“连接初始化失败”); UpdateStatus(“连接初始化失败”); } else { UpdateStatus(“正在连接...”); } } void Update() { // 必须定期调用Service()方法处理网络消息 lbc?.Service(); } void UpdateStatus(string status) { if (connectionStatusText ! null) connectionStatusText.text status; Debug.Log(status); } // 以下是IConnectionCallbacks接口的实现 public void OnConnected() { UpdateStatus(“已连接到服务器”); } public void OnConnectedToMaster() { UpdateStatus(“已连接到Master服务器”); // 连接成功后可以加入或创建房间 // lbc.OpJoinRandomRoom(); } public void OnDisconnected(DisconnectCause cause) { UpdateStatus($“连接断开原因{cause}”); } // 其他接口方法需要空实现否则会报错 public void OnRegionListReceived(RegionHandler regionHandler) {} public void OnCustomAuthenticationResponse(Dictionarystring, object data) {} public void OnCustomAuthenticationFailed(string debugMessage) {} }将这个脚本挂载到场景中的物体上并将一个UI Text组件拖拽赋值给connectionStatusText。运行Unity如果一切顺利你将看到文本显示“已连接到Master服务器”。4.4 连接测试与基础交互验证连接成功只是第一步。我们可以写一个简单的RPC远程过程调用来测试双向通信。在服务器端示例DLL中 我们已经使用了LoadBalancing示例它内置了基本的房间管理和RPC支持。在客户端 修改NetworkManager脚本在OnConnectedToMaster方法后加入创建房间和发送RPC的代码。// 在OnConnectedToMaster方法内 public void OnConnectedToMaster() { UpdateStatus(“已连接到Master服务器”); // 创建房间选项 EnterRoomParams roomParams new EnterRoomParams(); roomParams.RoomOptions new RoomOptions(); roomParams.RoomOptions.MaxPlayers 4; roomParams.RoomOptions.IsVisible true; roomParams.RoomOptions.IsOpen true; // 创建房间 if (lbc.OpCreateRoom(roomParams)) { UpdateStatus(“正在创建房间...”); } } // 实现IMatchmakingCallbacks接口需要让类继承它 public void OnCreatedRoom() { UpdateStatus(“房间创建成功”); // 房间创建成功后可以发送一个测试RPC SendTestRpc(); } void SendTestRpc() { // 使用OpRaiseEvent发送一个自定义事件 Hashtable customEventContent new Hashtable(); customEventContent[“message”] “Hello from Client!”; lbc.OpRaiseEvent(200, customEventContent, new RaiseEventOptions(), SendOptions.SendReliable); UpdateStatus(“已发送测试事件”); }同时你需要在服务器端示例应用中有相应的代码来处理事件码为200的事件。在LoadBalancing示例的GameApplication类中可以找到处理客户端事件的开关语句。通过这样的测试你能确认数据已经从客户端发出并被服务器接收处理。5. 本地联机调试与进阶配置5.1 在同一台机器上运行多个客户端进行测试真正的多人游戏需要多个客户端。在Unity编辑器中你可以使用ParrelSync这个免费资产来克隆项目实现同一台机器上运行多个编辑器实例进行联机测试。这是本地开发的神器。从Asset Store导入ParrelSync。通过它的菜单克隆当前项目。在克隆的项目中修改客户端脚本让玩家有不同的表现比如生成不同颜色的Cube。分别运行原项目和克隆项目它们都能连接到你的本地Photon Server并看到彼此。5.2 局域网内多设备连接测试如果你想用手机或另一台电脑测试就需要确保它们和服务器主机在同一个局域网连接同一个Wi-Fi。关闭防火墙或配置规则 在服务器主机上确保Windows防火墙允许PhotonSocketServer.exe通过公共网络如果你的局域网被识别为公共网络。更稳妥的方法是直接暂时关闭防火墙仅测试时或者创建详细的入站规则开放UDP/TCP的5055端口。获取服务器主机IP 在服务器主机上运行ipconfig记住IPv4地址。修改客户端配置 在测试设备手机或其他电脑的Unity构建版本或编辑器中将Master Server Address修改为服务器主机的IP地址如192.168.1.100端口仍是5055。连接测试 运行客户端应该就能成功连接了。5.3 服务器日志分析与性能监控调试网络问题日志是你的第一手资料。Photon Server的日志默认输出在deploy/log目录下按日期和应用程序分文件。Photon-20240101.log 主服务器日志记录服务启动、停止、应用加载等信息。MyGameServer-20240101.log 你的游戏应用日志记录客户端的连接、断开、房间操作、自定义事件等。当客户端连接失败时打开对应的日志文件搜索错误信息如Error,Exception,Failed。常见的错误会明确告诉你原因比如Address already in use端口被占用、Unable to bind to port权限不足或防火墙阻止。此外在PhotonControl界面你可以看到简单的性能计数器如连接数、消息吞吐量。对于更深入的性能分析可以考虑将日志集成到如Log4Net等框架并输出到更专业的监控工具。6. 常见问题排查与解决方案实录本地搭建过程中90%的问题都出在配置和网络环境上。下面是我总结的“踩坑大全”按从外到内的顺序排查基本能解决所有问题。6.1 连接失败类问题问题现象可能原因排查步骤与解决方案Unity客户端报错Failed to connect to server1. 服务器未启动。2. IP地址或端口错误。3. 防火墙阻止。1.检查服务器状态确认PhotonControl中Photon Socket Server状态为Running且日志显示应用已加载。2.检查端口监听在服务器CMD运行netstat -ano | findstr :5055确认有进程在监听。3.检查客户端配置核对Master Server Address是否为服务器主机的局域网IP非127.0.0.1端口是否为5055。4.关闭防火墙测试临时关闭服务器主机的Windows Defender防火墙重试连接。如果成功则需配置防火墙入站规则。连接超时无任何响应1. 网络不通。2. 客户端协议与服务器不一致。1.Ping测试在客户端设备上ping服务器IP看是否通。2.检查协议确保服务器MyGameServer.dll.config中的Protocol与Unity客户端PhotonServerSettings或代码中设置的TransportProtocol完全一致都是Udp或都是Tcp。能连接Master但无法加入/创建房间1. 服务器端应用逻辑错误或未正确加载。2. 客户端AppId与服务器端不匹配本地模式下通常不校验但自定义逻辑可能校验。1.查看应用日志检查deploy/log/MyGameServer-xxx.log看是否有关于房间操作的错误。2.使用官方示例DLL确保你使用的MyGameServer.dll是来自LoadBalancing示例并正确编译的避免自己写的逻辑有Bug。3.简化测试先只用最基本的连接功能确保网络层通畅再逐步添加房间逻辑。6.2 服务器启动与运行类问题问题现象可能原因排查步骤与解决方案PhotonControl点击Run后立刻停止1. 端口被占用。2. 配置文件有语法错误。3. 依赖的DLL缺失或版本不对。1.检查端口占用用netstat -ano | findstr :5055查看5055端口是否已被其他程序如Skype、IIS、其他游戏服务占用。如果被占修改MyGameServer.dll.config中的端口号并同步修改客户端配置。2.检查配置文件用XML验证工具检查PhotonServer.config和MyGameServer.dll.config的格式是否正确标签是否闭合。3.检查DLL确认deploy/bin和deploy/MyGameServer目录下所有必需的DLL文件都存在特别是ExitGamesLibs.dll是否与MyGameServer.dll版本匹配。日志中报错Could not load file or assembly...服务器应用依赖的某个程序集找不到。1.查看完整错误信息日志会明确指出缺失哪个DLL。2.复制依赖项从src-server对应示例的编译输出目录通常是bin/Debug或bin/Release将所有.dll文件除了MyGameServer.dll复制到deploy/MyGameServer目录下。确保deploy/bin目录下也有Photon核心库。服务器运行一段时间后崩溃1. 内存泄漏自定义逻辑导致。2. 异常未处理。1.分析崩溃日志查看日志最后几行的异常堆栈信息。2.使用示例DLL测试如果使用官方示例也崩溃可能是环境问题。如果只有自定义DLL崩溃需检查自己的服务器端代码特别是循环引用、静态变量、事件订阅未取消等问题。6.3 数据通信与同步类问题问题现象可能原因排查步骤与解决方案客户端发送RPC/事件其他客户端收不到1. 事件代码未在服务器端注册或处理。2. 发送的目标Target设置错误。3. 客户端未正确实现事件接收回调。1.服务器端处理确保在服务器的GameApplication或相关类中有处理对应EventCode的switch-case逻辑并且正确地将事件转发Broadcast给其他玩家。2.检查RaiseEventOptions确认RaiseEventOptions中的Receivers设置正确例如ReceiverGroup.Others或ReceiverGroup.All。3.客户端订阅在客户端确保通过lbc.OpAddCallbackTarget添加了实现了IOnEventCallback接口的对象并在OnEvent方法中处理事件。移动同步延迟高或抖动1. 网络延迟本身。2. 发送频率过高或过低。3. 未使用插值或外推。1.本地测试排除网络问题同一台机器两个客户端测试如果延迟仍高则是逻辑问题。2.优化发送频率不要每帧发送位置可以定时如每秒10-15次或在位置变化超过阈值时发送。3.在客户端实现插值收到其他玩家的位置更新后不是直接transform.position newPosition而是平滑地移动到目标位置。这是客户端预测与平滑的范畴PUN等高级库内置了这些功能。6.4 防火墙与网络配置终极指南这是新手最大的拦路虎。请严格按照以下步骤操作添加入站规则推荐打开“Windows Defender 防火墙与高级安全”。点击“入站规则” - “新建规则”。规则类型选择“程序”。程序路径浏览到deploy\PhotonSocketServer.exe。操作选择“允许连接”。配置文件全选域、专用、公用。名称起一个名字如“Photon Server”。同样步骤为deploy\bin\PhotonSocketServer.exe如果存在也添加规则。开放特定端口备用方案同上新建入站规则。规则类型选择“端口”。协议和端口选择“UDP”或“TCP”特定本地端口填入5055以及你用到的其他端口如9090。后续步骤同上。检查网络类型有时Windows会将家庭网络误识别为“公用网络”而防火墙对公用网络的限制更严格。确保你的网络配置文件是“专用网络”。踩坑实录我最常遇到的情况是在笔记本上开发白天连着公司Wi-Fi公用网络测试正常晚上回家连家里Wi-Fi专用网络反而连不上了。就是因为防火墙规则只允许了“公用网络”而家里是“专用网络”。所以创建规则时一定要“域、专用、公用”三个全勾选。7. 从本地到云下一步的学习路径当你成功在本地搭建并连接Photon Server后你已经掌握了网络游戏开发最核心的基础。接下来可以沿着这几个方向深化深入服务器逻辑开发 不再使用示例DLL尝试用Visual Studio创建自己的Photon服务器端应用项目。学习Photon.SocketServer命名空间下的核心类如PeerBase,ApplicationBase实现你自己的游戏循环、房间管理、自定义协议。学习PUN 2 理解了底层原理后再使用PUN 2进行开发会事半功倍。你会明白PhotonView,RPC,OnPhotonSerializeView这些高级抽象背后到底在做什么能更高效地使用它们也能更好地调试问题。部署到Linux服务器 实际项目上线通常会使用Linux服务器。研究如何在Linux上通过Mono或 .NET Core运行Photon Server学习基本的运维命令和监控。集成数据库与后端服务 在服务器端逻辑中接入MySQL、Redis等数据库处理玩家数据持久化、排行榜、邮件系统等。压力测试与优化 使用工具模拟大量客户端连接测试你的服务器逻辑能承受多少并发找出性能瓶颈并进行优化。本地搭建Photon Server的过程就像在学游泳时先在浅水区扑腾。虽然一开始会喝几口水但当你熟悉了水性知道了如何换气、如何划水再进入深水区云端部署、复杂逻辑时你心里是踏实的。这个过程积累的经验和直觉是只看文档和教程无法获得的。希望这篇超详细的指南能帮你顺利渡过新手期少走些弯路。