1. 项目概述:为什么要在本地搭建Photon Server?
如果你正在用Unity做联网游戏,尤其是那种需要实时同步的多人对战或者MMO,那你肯定绕不开一个词:服务器。市面上成熟的解决方案很多,Photon Server就是其中非常经典的一个。它基于C#,和Unity的契合度很高,性能也不错,很多中小团队甚至大厂的一些项目都在用。
但问题来了,很多教程一上来就让你去租云服务器,或者直接用Photon Cloud的免费套餐。对于还在原型验证、功能调试阶段的你来说,这其实挺麻烦的。每次改点代码,想看看网络同步效果,都得打包、上传、部署到远程服务器,再让测试客户端连上去。这个反馈循环太长了,严重拖慢开发效率。而且,Photon Cloud的免费版有并发和CCU限制,测试时一不小心就超了。
所以,把Photon Server搭在你自己的开发机上,就成了一个非常刚需的环节。本地服务器意味着:零延迟、无限测试、完全掌控。你可以随时启动服务,用编辑器或者打包出来的客户端直连本机IP,瞬间看到网络逻辑的运行结果。所有数据包都在你眼皮底下,用Wireshark抓包分析、用日志追踪问题,都变得无比方便。这不仅仅是“搭建”一个服务,更是为你自己构建一个高效的、闭环的联机开发与调试环境。今天要聊的,就是把这个环境从零到一建起来,并且把过程中那些最容易让你卡住的“坑”提前标出来。
2. 核心思路与工具选型解析
2.1 为什么选择Photon Server On-Premises?
首先得明确,Photon Server有两个主要产品线:Photon Cloud(云端托管服务)和Photon Server On-Premises(本地部署版)。我们这里搞的是后者。选择它的理由很充分:
- 开发与调试友好:如前所述,本地服务器提供了最快的迭代速度。你可以在Unity编辑器中运行游戏,同时连接本地服务器,实现“编辑-运行-调试”的无缝衔接。
- 成本可控:在开发阶段,完全不需要为服务器资源付费。即使是后期,对于小规模项目或特定区域部署,自建服务器的长期成本可能低于云服务。
- 数据安全与隐私:所有游戏逻辑和玩家数据都在你自己的机器或内网中,对于涉及敏感逻辑或需要高度定制的项目来说,这是必须的。
- 深度定制:你可以完全访问服务器端源代码(C#),根据游戏需求任意修改业务逻辑、通信协议、甚至底层网络库。
当然,它也有代价,就是你需要自己负责服务器的运维、更新、扩展和监控。但对于核心开发阶段,利远大于弊。
2.2 环境准备清单与版本选择要点
在动手之前,先把“弹药”备齐。这里的选择会直接影响后续步骤的顺利程度。
1. 操作系统 (OS):Photon Server原生支持Windows。虽然理论上可以通过Mono在Linux上运行,但官方支持有限,且很多配套工具(如控制台PhotonControl)是Windows专用的。为了减少不必要的麻烦,强烈建议在Windows 10或Windows Server 2016及以上版本的系统上进行搭建。这也是绝大多数Unity开发者的主力环境。
2. .NET Framework:Photon Server的运行依赖于.NET Framework。你需要确保系统上安装了正确版本。通常,Photon Server SDK会要求.NET Framework 4.6 或更高版本。你可以在“控制面板 -> 程序和功能 -> 启用或关闭Windows功能”中查看和安装。
注意:如果你电脑上只装了.NET Core或.NET 5/6/7/8,那是不行的。Photon Server(尤其是我们常用的版本)是基于传统的.NET Framework构建的,必须安装对应的运行时。
3. Photon Server SDK:这是主角。你需要去Photon Engine官网的下载页面,找到“Photon Server SDK”。注册一个账号(免费)就能下载。这里有个关键点:版本匹配。
- 查看你Unity项目中使用的
Photon Unity Networking (PUN)或Photon Realtime等客户端SDK的版本。 - 尽量选择与客户端SDK版本兼容的Server SDK。如果官网有版本说明,务必阅读。通常,大版本号一致会比较安全(例如,客户端用PUN 2,服务器端也用Photon Server SDK v4.x或v5.x的某个兼容版本)。下载下来是一个压缩包,比如
PhotonServer-4-0-29-11263.zip。
4. Unity项目准备:你的Unity项目里应该已经导入了Photon的客户端SDK(PUN或Realtime)。确保它基本配置正确,至少知道怎么设置AppId。我们搭建本地服务器的目的,就是为了让这个客户端能连上来。
5. 可选工具:
- 文本编辑器:推荐VS Code或Notepad++,用于修改配置文件。千万别用Windows自带的记事本,它可能会破坏文件编码。
- 命令行工具:熟悉基本的Windows CMD或PowerShell操作,用于运行一些批处理命令。
- 网络诊断工具:如
ping,telnet(需要先在Windows功能中启用“Telnet客户端”),用于测试端口连通性。
3. 服务器安装与核心配置详解
3.1 解压与目录结构初探
把下载的PhotonServer-XXX.zip解压到一个你容易找到的路径,强烈建议路径中不要包含中文或空格,比如解压到D:\PhotonServer。解压后的目录结构大致如下:
PhotonServer/ ├── deploy/ # 这是核心!我们后续部署的应用都放在这里 │ ├── bin/ # 各个应用的可执行文件和依赖库 │ ├── log/ # 运行时生成的日志文件 │ └── ... # 其他应用相关文件 ├── lib/ # Photon Server的核心库文件 ├── src-server/ # 服务器端示例源码(学习宝库) ├── PhotonControl.exe # 服务器管理控制台(图形界面) ├── PhotonServer.config # 主配置文件 └── ... (其他文档和工具)对开发者来说,最重要的两个地方是deploy文件夹和src-server文件夹。deploy是我们运行服务器的“沙盒”,src-server则提供了如何编写自定义游戏逻辑的范例。
3.2 关键配置文件修改实战
Photon Server的配置主要通过XML文件完成。我们需要修改两个关键文件。
1. 修改PhotonServer.config(主配置文件):这个文件定义了Photon Server运行的基本参数,比如监听哪些IP和端口。用你的文本编辑器打开它。
找到<UDPListeners>和<TCPListeners>节点。对于本地开发,我们通常关注TCP。你会看到类似下面的配置:
<UDPListeners> <!-- UDP配置,某些协议会用到 --> </UDPListeners> <TCPListeners> <TCPListener IPAddress="0.0.0.0" Port="4530" InactivityTimeout="10000" OverrideApplication="Master"> <Protocol Type="Photon.SocketServer.Rpc.Protocols.GpBinaryV162, Photon.SocketServer" /> </TCPListener> </TCPListeners>IPAddress="0.0.0.0": 这表示监听本机所有网络接口。对于本地开发,这样设置没问题,服务器会接受来自本机回环地址(127.0.0.1)和局域网IP的连接。如果你想限制只允许本机连接,可以改为127.0.0.1。Port="4530": 这是Photon默认的端口。确保这个端口没有被其他程序占用(如某些VPN软件、Skype等)。你可以使用netstat -ano | findstr :4530命令来检查。OverrideApplication="Master": 这表示连接到4530端口的客户端,默认会被路由到名为“Master”的应用程序(Application)。这个“Master”应用定义在另一个配置里。
2. 创建并配置你的游戏应用 (Application):Photon Server支持同时运行多个“应用”,每个应用相当于一个独立的游戏服务器逻辑。我们需要在deploy目录下创建自己的应用。
- 第一步:复制示例。进入
deploy目录,你会发现一些已有的应用文件夹,如Counter(一个简单的计数器示例)。把它复制一份,重命名为你的游戏名,例如MyGame。 - 第二步:修改应用配置。进入
MyGame\bin目录,找到PhotonServer.config(这是应用级别的配置,和根目录的那个是两回事)。打开它。- 找到
<Application>节点,其Name属性必须与根配置中OverrideApplication指定的名字一致,这里就是Name="Master"。 - 找到
<Peers>节点下的<Peer>,其PeerType通常指向一个DLL文件,这个DLL包含了你的游戏服务器逻辑。在示例中,它可能指向Counter.dll。你需要把它改成你自己编译的服务器逻辑DLL名(稍后我们会讲到如何生成这个DLL)。例如:PeerType="MyGameServer.dll"。 - 检查
Port和Protocol设置,通常保持默认即可,它会使用根配置中4530端口传过来的连接。
- 找到
3. 配置日志级别 (可选但重要):在应用级别的PhotonServer.config中,你还可以找到日志配置。对于调试阶段,建议将日志级别调低,比如设为Debug或Info,这样能在deploy\MyGame\log目录下看到更详细的运行信息,方便排查问题。
<Logging> <Logger Name="Photon" Severity="Info" /> <!-- 改为 Debug 可看到更多细节 --> </Logging>3.3 启动服务器与验证服务状态
配置完成后,就可以启动服务器了。有两种主要方式:
方式一:使用 PhotonControl (图形界面 - 推荐新手)直接双击根目录下的PhotonControl.exe。它会打开一个控制台窗口,并加载一个系统托盘图标。在系统托盘图标上右键,你可以看到所有已配置的应用(如Master)。
- 右键点击
Master->Start。如果配置正确,状态会变成绿色或显示“Running”。 - 此时,控制台窗口也会输出启动日志,显示
Master应用正在监听4530端口。
方式二:使用命令行 (适合自动化)打开命令行,切换到Photon Server根目录,执行:
PhotonSocketServer.exe /debug PhotonServer.config这个命令会以前台调试模式启动服务器,所有日志直接输出到当前控制台。按Ctrl+C可以停止服务。
验证服务是否启动成功:
- 查看日志:到
deploy\MyGame\log目录下,查看最新的日志文件,搜索是否有“started”、“listening on”等成功信息,以及是否有“ERROR”级别的错误。 - 使用Telnet测试端口:打开命令行,输入
telnet 127.0.0.1 4530。如果端口是开放的且服务正常,光标会停在一个空行(连接建立),或者立即断开(服务不接受Telnet这种原始连接)。如果显示“无法打开到主机的连接...”,则说明端口未监听,服务启动失败。 - 观察PhotonControl状态:在PhotonControl界面中,应用应显示为运行状态。
4. Unity客户端连接配置与联调
服务器跑起来了,现在让Unity客户端连接它。
4.1 客户端SDK设置关键步骤
在你的Unity项目中,确保已导入Photon客户端SDK(例如PUN 2)。然后进行以下设置:
- 找到Photon服务器设置:在Unity编辑器中,通常可以通过菜单
Window -> Photon Unity Networking -> PUN Wizard打开设置向导。或者,在Resources文件夹下找到PhotonServerSettings文件。 - 配置服务器地址:这是最关键的一步。在设置界面,你会看到“Server Settings”。
- Host Type: 选择
Self Hosted。这告诉客户端我们将连接自己部署的服务器,而不是Photon Cloud。 - Server Address: 填写你的服务器IP。对于本地连接,填
127.0.0.1或localhost。 - Server Port: 填写你在
PhotonServer.config中配置的端口,默认是4530。 - App Id: 当使用Self Hosted时,这个字段通常可以留空或填写任意字符串。因为本地服务器的应用验证逻辑是由你自定义的,不像Photon Cloud那样需要严格的AppId匹配。但是,有些自定义的服务器逻辑可能会检查这个值,所以最好和你的服务器端代码约定一个值并填上,比如“MyLocalGame”。
- Host Type: 选择
- 应用设置:点击“Setup Project”或直接保存
PhotonServerSettings文件。
4.2 编写一个简单的连接测试脚本
为了验证连接,我们创建一个最简单的脚本。在Unity中创建一个C#脚本,例如NetworkManager.cs,挂载到场景中的某个GameObject上。
using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.UI; public class NetworkManager : MonoBehaviourPunCallbacks { [SerializeField] private Text connectionStatusText; void Start() { // 设置连接参数(可选,如果PhotonServerSettings已配置好) // PhotonNetwork.PhotonServerSettings.AppSettings.Server = "127.0.0.1"; // PhotonNetwork.PhotonServerSettings.AppSettings.Port = 4530; // PhotonNetwork.PhotonServerSettings.AppSettings.AppIdRealtime = "MyLocalGame"; PhotonNetwork.GameVersion = "1.0"; // 设置游戏版本,用于隔离不同版本的客户端 PhotonNetwork.ConnectUsingSettings(); // 使用PhotonServerSettings中的配置进行连接 } public override void OnConnectedToMaster() { Debug.Log("成功连接到 Photon Server Master 服务器!"); if (connectionStatusText != null) connectionStatusText.text = "已连接到本地服务器"; // 连接成功后,可以加入或创建房间 // PhotonNetwork.JoinRandomRoom(); } public override void OnDisconnected(DisconnectCause cause) { Debug.LogWarning($"与服务器断开连接,原因: {cause}"); if (connectionStatusText != null) connectionStatusText.text = $"连接断开: {cause}"; } }运行Unity,查看控制台输出。如果看到“成功连接到 Photon Server Master 服务器!”,恭喜你,客户端到服务器的通路已经打通了!
4.3 基础通信测试:从客户端到服务器
连接成功只是第一步。我们还需要验证数据能否正确收发。这里可以利用Photon Server SDK自带的示例代码。
- 理解服务器端逻辑:回到Photon Server的
src-server目录,找到Counter示例项目。用Visual Studio打开Counter.sln。这个示例演示了如何处理客户端请求、维护房间状态。花点时间阅读一下CounterPeer.cs和CounterApplication.cs,了解基本的OperationRequest和OperationResponse处理流程。 - 编译服务器端DLL:在VS中编译
Counter项目(选择Release配置)。编译成功后,在项目的bin\Release目录下会生成Counter.dll。 - 部署DLL:将这个
Counter.dll复制到deploy\MyGame\bin目录下,并确保MyGame应用配置中的PeerType指向它(PeerType="Counter.dll")。 - 修改客户端测试脚本:在Unity客户端,我们可以在连接成功后,发送一个示例操作。在
OnConnectedToMaster方法后添加:
// 加入一个随机房间(Counter示例默认创建了一个房间) PhotonNetwork.JoinRandomRoom(); public override void OnJoinedRoom() { Debug.Log($"加入了房间: {PhotonNetwork.CurrentRoom.Name}"); // 发送一个增加计数的操作(对应Counter示例的Operation Code 1) PhotonNetwork.RaiseEvent(1, null, new RaiseEventOptions { Receivers = ReceiverGroup.MasterClient }, SendOptions.SendReliable); }- 观察结果:重启Photon Server和Unity客户端。当客户端加入房间并发送事件后,查看服务器端
deploy\MyGame\log下的日志。你应该能看到服务器接收到操作码为1的请求,并进行了处理的日志条目。同时,服务器可能会将更新后的计数广播给客户端(取决于示例逻辑)。这就完成了一次最简单的客户端-服务器-客户端的完整通信验证。
5. 开发自定义游戏逻辑服务器
使用示例DLL只是开始,真正的目标是运行你自己写的游戏服务器逻辑。
5.1 创建你的第一个Photon Server应用项目
- 新建类库项目:打开Visual Studio,新建一个“类库(.NET Framework)”项目,命名为
MyGameServer。确保目标框架选择.NET Framework 4.6或与你Photon Server SDK兼容的版本。 - 添加引用:在项目中,添加对Photon Server核心库的引用。通常需要引用
PhotonServer根目录\lib下的这几个DLL:Photon.SocketServer.dll(核心)PhotonHostRuntimeInterfaces.dllExitGamesLibs.dll(包含日志等工具)
- 设置输出路径:为了方便,将项目的输出路径直接设置为
PhotonServer根目录\deploy\MyGame\bin\。这样每次编译,生成的MyGameServer.dll会自动覆盖到部署目录。
5.2 核心类解析:Peer, Application 与 Operation
Photon Server应用通常由三个核心部分组成:
- Application(
MyGameApplication):继承自ApplicationBase。它是应用的入口点,负责创建Peer实例、管理应用级别的生命周期和资源。一个应用对应一个监听端口(通过根配置路由而来)。 - Peer(
MyGamePeer):继承自PeerBase或ClientPeer。每个连接到服务器的客户端都会对应一个Peer对象实例。它处理该客户端的所有请求和响应,是游戏逻辑的主要承载者。你需要在这里重写OnOperationRequest方法来处理客户端发来的各种操作。 - Operation:客户端和服务器之间通信的基本单位。每个操作都有一个唯一的操作码(Operation Code)和一个参数字典(Dictionary)。服务器在
OnOperationRequest中根据操作码来执行不同的游戏逻辑。
一个极简的代码框架:
MyGameApplication.cs:
using Photon.SocketServer; namespace MyGameServer { public class MyGameApplication : ApplicationBase { // 当新的客户端连接时调用 protected override PeerBase CreatePeer(InitRequest initRequest) { // 为这个新连接创建一个Peer实例 return new MyGamePeer(initRequest); } // 应用启动时调用 protected override void Setup() { Log.Info("MyGame 服务器应用启动!"); } // 应用停止时调用 protected override void TearDown() { Log.Info("MyGame 服务器应用停止。"); } } }MyGamePeer.cs:
using Photon.SocketServer; using Photon.SocketServer.Rpc; using System.Collections.Generic; namespace MyGameServer { public class MyGamePeer : PeerBase { public MyGamePeer(InitRequest initRequest) : base(initRequest) { } // 处理客户端发来的请求 protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters) { switch (operationRequest.OperationCode) { case 1: // 假设操作码1是“玩家移动” HandlePlayerMove(operationRequest); break; case 2: // 操作码2是“发送聊天” HandleChatMessage(operationRequest); break; default: // 发送错误响应 var response = new OperationResponse(operationRequest.OperationCode) { ReturnCode = (short)ErrorCode.OperationInvalid, DebugMessage = "未知的操作码" }; SendOperationResponse(response, sendParameters); break; } } private void HandlePlayerMove(OperationRequest request) { // 1. 从request.Parameters字典中解析出位置、速度等参数 // 2. 验证移动合法性(防外挂) // 3. 更新服务器端游戏状态 // 4. 广播移动信息给房间内其他玩家 Log.Info($"处理玩家移动请求"); // ... 具体逻辑 var response = new OperationResponse(request.OperationCode) { ReturnCode = 0 }; // 0表示成功 SendOperationResponse(response, new SendParameters()); } // 客户端断开连接时调用 protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail) { Log.Info($"客户端断开连接: {reasonDetail}"); } } }5.3 编译、部署与热重载技巧
- 编译:在VS中编译
MyGameServer项目。 - 部署:由于我们设置了输出路径,
MyGameServer.dll会自动复制到deploy\MyGame\bin。同时,需要将项目依赖的Photon的那些DLL(Photon.SocketServer.dll等)也复制到同一个目录,或者确保它们在服务器的全局程序集缓存(GAC)中。最简单的方法就是把它们也复制到bin目录。 - 更新应用配置:确保
deploy\MyGame\bin\PhotonServer.config中的PeerType指向MyGameServer.dll。 - 重启应用:在PhotonControl中,右键点击
Master应用,选择Restart。这样就会加载新的DLL。
实操心得:调试与热重载直接附加调试器到Photon Server进程比较麻烦。一个高效的开发方式是:日志驱动调试。在你的服务器代码中大量使用
Log.Info()、Log.Warn()、Log.Error()。日志会实时写入deploy\MyGame\log目录下的文件。你可以用文本编辑器(如VS Code)保持日志文件打开,并启用“自动刷新”功能,这样就能实时看到服务器输出的日志,相当于一个简单的控制台。 对于逻辑修改,你需要重启应用(Restart)才能生效。重启通常很快,不会影响其他正在运行的应用(如果你有多个的话)。这比关闭整个Photon Server再启动要方便。
6. 联调环境搭建与高效工作流
现在你有了一个可运行的本地服务器和懂得连接它的客户端。如何将两者结合起来,形成一个流畅的开发调试循环?
6.1 同时启动服务器与客户端的自动化
每次开发都要手动点开PhotonControl,再点开Unity编辑器,很繁琐。我们可以用批处理脚本简化。
创建一个start_dev.bat文件,放在你的项目根目录:
@echo off echo 启动 Photon Server... start "" /D "D:\PhotonServer" PhotonControl.exe timeout /t 3 /nobreak > nul echo 启动 Unity 编辑器... start "" "C:\Program Files\Unity\Hub\Editor\2022.3.XXf1\Editor\Unity.exe" -projectPath "D:\YourUnityProject" echo 开发环境启动完毕。这个脚本会先启动Photon Server,等待3秒确保服务启动,再打开Unity项目。你可以根据实际路径修改。双击这个.bat文件,就能一键进入开发状态。
6.2 在Unity编辑器中实现“编辑-运行-调试”循环
这是本地服务器最大的优势所在。
- 运行模式:在Unity编辑器中按下Play按钮。你的游戏脚本(如
NetworkManager)会执行,连接到127.0.0.1:4530的本地服务器。 - 实时修改与测试:你可以在游戏运行期间,修改某些参数(非网络核心逻辑),甚至修改UI,并立即看到效果。对于网络逻辑,如果你修改了客户端发送的数据格式,需要停止运行,修改服务器端
MyGamePeer.cs中对应的解析逻辑,重新编译DLL,然后在PhotonControl中重启Master应用,最后在Unity中再次运行测试。虽然比纯客户端修改多一步,但远比部署到远程服务器快得多。 - 断点调试(客户端):在Unity的C#脚本中设断点是常规操作。你可以清晰地看到网络事件回调(如
OnConnectedToMaster)的触发、发送数据的构造过程。 - 日志联动:将Unity的Debug.Log输出和Photon Server的日志输出同时监控。你可以给每次请求和响应加上唯一的请求ID或时间戳,这样就能在两边日志中对应起来,完整追踪一次网络交互的全程。
6.3 性能与网络模拟测试初步
本地环境也可以做初步的负载和网络条件模拟。
- 多客户端测试:你可以同时运行多个Unity编辑器实例,或者打包出多个独立的游戏客户端,让它们同时连接你的本地服务器。观察服务器CPU、内存占用,以及日志中是否有处理延迟。这能帮你发现一些简单的并发问题。
- 网络延迟模拟:Windows有一个内置工具叫
Windows Filtering Platform (WFP),但配置复杂。更简单的方法是使用第三方工具,如Clumsy。它可以很方便地模拟网络延迟(Lag)、丢包(Loss)、节流(Throttling)。在本地机器上运行Clumsy,设置100ms的延迟和5%的丢包,然后运行你的游戏,体验一下在不良网络下的表现,测试你的网络代码是否健壮。
7. 常见错误排查与解决方案实录
搭建和联调过程中,你几乎一定会遇到下面这些问题。我把它们和解决方案整理成了表格,方便你快速对照排查。
| 错误现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| PhotonControl启动失败,或应用启动后立即停止 | 1. 端口被占用。 2. 配置文件语法错误。 3. 依赖的.NET Framework版本未安装或版本不对。 4. 应用配置中指定的DLL不存在或无法加载。 | 1.检查端口:`netstat -ano |
| Unity客户端连接失败,提示“无法连接”或超时 | 1. 服务器未运行。 2. 客户端IP/端口配置错误。 3. 防火墙阻止了连接。 4. 服务器绑定IP不是 0.0.0.0或127.0.0.1。 | 1.确认服务状态:PhotonControl中应用是否为“Running”? 2.核对配置:检查Unity中 PhotonServerSettings的Server Address和Port是否与服务器配置一致。本地连接务必用127.0.0.1,而不是局域网IP。3.关闭防火墙:临时关闭Windows防火墙进行测试。如果成功,则需要为PhotonServer.exe添加入站规则。 4.检查服务器IP绑定:确认 PhotonServer.config中TCPListener的IPAddress是0.0.0.0或127.0.0.1。 |
| 连接成功,但很快断开,或无法加入房间 | 1. 服务器端应用(Application)配置错误,未正确初始化。 2. 客户端AppId与服务器端预期不匹配(如果服务器端有校验)。 3. 服务器端Peer逻辑抛出未处理异常。 | 1.查看服务器日志:这是最重要的线索!打开deploy\MyGame\log最新的日志文件,搜索“ERROR”或“Exception”。异常堆栈会直接指出问题所在,比如某个依赖项找不到,或者OnOperationRequest中代码有bug。2.检查AppId:确认Unity客户端设置的AppId是否与服务器端校验的逻辑一致。对于简单测试,可以在服务器端 CreatePeer或OnOperationRequest中暂时注释掉AppId检查代码。3.调试服务器代码:在 MyGamePeer的构造函数、OnOperationRequest等方法开始处加日志,确认客户端连接后是否正常创建了Peer,以及请求是否送达。 |
| 服务器日志中出现“无法加载DLL”或“找不到类型”错误 | 1. 自定义的MyGameServer.dll编译目标框架与Photon Server不兼容。2. 缺少必要的依赖DLL。 3. DLL文件被锁定(如上一次运行未完全释放)。 | 1.检查项目属性:确保MyGameServer类库项目目标框架是.NET Framework 4.6(或服务器SDK要求的版本),而不是.NET Core或.NET Standard。2.复制所有依赖:将 MyGameServer.dll所有引用的DLL(特别是Photon.SocketServer.dll,ExitGamesLibs.dll等)都复制到deploy\MyGame\bin目录下。3.重启PhotonControl:完全关闭PhotonControl,再重新打开启动应用,确保旧DLL被释放。 |
| 客户端能连接,但发送操作后服务器无响应 | 1. 服务器端OnOperationRequest方法中的switch语句没有处理客户端的操作码。2. 客户端发送的操作参数格式与服务器端解析代码不匹配。 3. 服务器端处理逻辑中有异常被静默吞没。 | 1.检查操作码:在客户端和服务器端打印或日志记录发送和接收到的操作码,确保它们一致。 2.检查参数字典:在服务器端 OnOperationRequest开始处,将operationRequest.Parameters的内容完整地日志记录下来,对比客户端发送的Dictionary的Key和Value类型。3.添加Try-Catch:在 OnOperationRequest和每个操作处理函数外包一层try-catch,将异常详细信息记录到日志,避免进程崩溃但问题被隐藏。 |
| 性能问题:连接数稍多就卡顿或延迟高 | 1. 服务器端逻辑处理效率低下(如频繁GC、同步阻塞操作)。 2. 开发机本身性能不足。 3. 网络广播优化不足。 | 1.优化代码:避免在频繁调用的网络方法中分配大量临时对象(如new Dictionary)。使用对象池。避免进行同步的IO操作(如读写文件、访问数据库),应使用异步方式。2.监控资源:使用任务管理器监控PhotonServer进程的CPU和内存占用。本地开发机同时运行Unity、VS、PhotonServer,资源可能紧张。 3.减少广播频率:对于移动同步,不要每帧广播,可以采用状态同步或降低同步频率。使用Photon的 EventCaching和Interest Groups进行优化。 |
我个人在实际搭建和教学过程中发现,90%的问题都能通过查看服务器日志文件找到直接原因。所以,当你遇到任何问题时,第一个动作就应该是打开对应的log文件。Photon的日志通常很详细,会告诉你配置文件哪一行出错、哪个DLL加载失败、哪个操作抛出了什么异常。养成看日志的习惯,能节省你大量盲目搜索的时间。
最后,本地Photon Server是你联机游戏开发的强大沙盒。它让你能专注于游戏逻辑本身,而不是环境问题。当你在本地把核心的同步、状态管理、房间逻辑都调试稳定后,再迁移到正式的Linux生产服务器上,就会顺利得多。那时,你要面对的更多是部署、运维和网络架构的问题,而最复杂的游戏业务逻辑,已经在你的本地机器上被反复锤炼过了。