Unity 使用Photon Server 创建一个简单聊天室

时间:2021-09-12 23:21:54

Unity 使用Photon Server 创建一个简单聊天室

参考教程:基于PhotonServer单服聊天室
完整Github工程(服务器):MyGameServer
完整Github工程(Unity客户端):PhotonChatRoom
数据库用户列表操作见另一篇:Unity C# 连接SQL Server数据库,实现获取和添加登录注册的用户列表

  初步了解使用Photon插件如何进行通信,按照上面链接的教程走了一遍,掌握了一些简单操作。


MyGameServer服务器配置

工程结构

Unity 使用Photon Server 创建一个简单聊天室


客户端、服务器规定通用操作码与数据结构

项目名、文件夹名、文件名 说明
Common 客户端、服务端共同需要的标准数据结构,同时生成在Unity工程的目录下,作为DLL插件,见下图补充。
Code 操作码。枚举类,用来作为判断条件信息。
OpCode (Operation Code)操作码。先通过判断这个操作码才会进入下面两个操作码的处理。包含两个枚举值:Account(帐号)、Chat(聊天)。
AccountCode 用户子操作码。包含两个枚举值:Register(注册)和 Login(登录)。
RoomCode 聊天室子操作码。包含四个枚举值: Enter(进入)、Add(新的连接)、Talk(聊天)、Leave (离开)。
Dto (Data Transfer Object)数据传输对象。用来作为通信的数据结构,需要加[Serializable]特性才能被序列化传输,这里使用Json作为传输中介。
AccountDto 用户信息结构。包含两个字符串:AccountName(用户名)和 Password(密码)。
RoomDto 房间信息结构。包含一个列表:AccountList(用户列表)。

  将Common生成到Unity工程目录下。方便Untiy直接调用。
Unity 使用Photon Server 创建一个简单聊天室
Unity 使用Photon Server 创建一个简单聊天室

  传输Dto时需要转换成Json,添加LitJson插件。
Unity 使用Photon Server 创建一个简单聊天室
Unity 使用Photon Server 创建一个简单聊天室


服务器结构

项目名、文件夹名、文件名 说明
MyGameServer 服务器,分三层结构,至下而上分别是:Model、Cache、Logic。需要引用Photon的DLL,见下图补充。
Model 模型层。存放基础数据结构,用户模型和房间模型。
AccountModel 用户模型。包含一个整型 ID、两个字符串分别是用户名和密码。
RoomModel 房间模型。包含一个整型 ID、一个字典客户端和用户模型的映射。还有查询、添加、删除用户的基本方法。
Cache 缓存层。用于存放模型列表,对模型的操作等。
Factory 工厂。用来获取AccountCache和RoomCache的单例。
AccountCache 用户缓存。包含所有用户ID和用户模型的映射字典,还有所有在线客户端和用户模型的映射字典,以及相关注册登录的方法。
RoomCache 房间缓存。包含一个房间模型,以及客户端进入离开房间的方法。
Logic 逻辑层。客户端的缓存的数据 和 服务器之间逻辑处理。
Handler 处理抽象类。包含两个抽象方法 OnRequest 和 OnDisconnect ,分别是处理客户端发来的请求,以及当客户端下线时的处理。还有一个发送数据到客户端的方法。
AccountHandler 用户处理。继承于Handler,用户处理当客户端发来请求时的处理(注册、登录),并回复响应处理结果。
RoomHandler 房间处理。继承于Handler,处理当用户进入房间、离开房间、以及用户聊天的信息处理。
log4net.config log for net。从别的Photon样例工程复制过来,拿来输出自定义日志用的配置。
MyApplication 整个服务器的入口。继承至ApplicationBase。当有客户端连接时调用CreatePeer,连接客户端。
MyClientPeer 连接的进来的客户端。通过它接收、处理、发送客户端的信息。

  服务器所需要添加的引用,添加在服务器工程lib目录下,从Photon的lib目录下找到下面这些DLL。
Unity 使用Photon Server 创建一个简单聊天室

  配置到Photon,便于启动服务器。
配置文件点我:PhotonServer.config
Unity 使用Photon Server 创建一个简单聊天室
Unity 使用Photon Server 创建一个简单聊天室


客户端结构

Unity 使用Photon Server 创建一个简单聊天室

UI介绍

对象名 说明
Photon Manager 包含PhotonManager类,用于处理客户端与服务端通信的桥梁。
LoginPanel 登录UI界面。两个按钮分别是登录到聊天房间,以及进入注册界面。
Unity 使用Photon Server 创建一个简单聊天室
RegisterPanel 注册UI界面。用于注册帐号。
Unity 使用Photon Server 创建一个简单聊天室
ChatCanvas 聊天UI界面。上部分分别是显示聊天内容,以及用户列表。下部分分别是聊天信息输入和发送信息。
Unity 使用Photon Server 创建一个简单聊天室

客户端脚本介绍

PhotonManager

  Photon客户端管理。实现了IPhotonPeerListener接口。

    //
// PhotonManager
//

private void Awake()
{
instance = this; //客户端单例
peer = new PhotonPeer(this, protocol); //创建客户端,协议是UDP

DontDestroyOnLoad(accountReceiver);
}

private void Update()
{
if (!connected)
peer.Connect(serverAddress, applicationName); //连接服务器
if(Time.time > currentTime)
{
peer.Service(); //获取服务,并不需要每帧获取,简单优化
currentTime += updateIntervalTime;
}
}

private void OnDestroy()
{
peer.Disconnect(); //断开连接
}

//向服务器发请求,参数:操作码,参数数据字典,子操作码
public void OnOperationRequest(byte opCode, Dictionary<byte, object> parameters = null, byte SubCode = 0)
{
//规定键'80'对应的是子操作码
parameters[80] = SubCode;
peer.OpCustom(opCode, parameters, true);
}

//服务端发送过来的响应
public void OnOperationResponse(OperationResponse response)
{
Debug.Log(response.ToStringFull());
byte subCode = (byte)response.Parameters[80];

switch ((OpCode)response.OperationCode) //判断发过来操作码,做出响应。
{
case OpCode.Account:
accountReceiver.OnReceive(subCode, response);
break;
case OpCode.Room:
chatRceiver.OnReceive(subCode,response);
break;
}
}

IReceiver

  接收响应接口。

interface IReceiver
{

//接受服务器响应,参数:子操作码,响应信息。
void OnReceive(byte subCode, OperationResponse response);
}

AccountReceiver

  接收操作用户登录注册的信息响应。实现 IReceiver接口。

    public AccountView accountView;

public void OnReceive(byte subCode, OperationResponse response)
{
switch ((AccountCode)subCode)
{
case AccountCode.Register:
if (response.ReturnCode == 0) //返回码正确时
{
accountView.OnHideRegisterPanel(); //关闭注册面板。
}
break;
case AccountCode.Login:
if (response.ReturnCode == 0) //返回码正确时
{
//告诉服务器可以将进入房间了
PhotonManager.Instance.OnOperationRequest((byte)OpCode.Room, new Dictionary<byte, object>(), (byte)RoomCode.Enter);
}
break;
}
}

ChatReceiver

  接收操作聊天房间的信息响应。实现 IReceiver接口。

    public void OnReceive(byte subCode, OperationResponse response)
{
switch ((RoomCode)subCode)
{
case RoomCode.Enter: //本人进入房间处理
if (response.ReturnCode == 0)
{
loginCanvas.SetActive(false); //隐藏登录面板
chatCanvas.SetActive(true); //显示聊天面板

//获取房间信息并初始化
chatView.Init(GetResponseFromJson<RoomDto>(response));
}
break;
case RoomCode.Add: //房间有新用户处理
chatView.AddAccount(GetResponseFromJson<AccountDto>(response));
break;
case RoomCode.Talk: //房间有人说话处理
string text = response.Parameters[0].ToString();
chatView.Append(text);
break;
case RoomCode.Leave: //房间有人离开处理
chatView.LeaveRoom(GetResponseFromJson<AccountDto>(response));
break;
default:
break;
}
}

//从获取到的Json信息中提取出Dto
private Dto GetResponseFromJson<Dto>(OperationResponse response)
{
return JsonUtility.FromJson<Dto>(response.Parameters[0].ToString());
}

AccountView

  用户登录和注册界面UI响应。


//登录和注册发送用户信息,子操作码分别是:AccountCode.Login和AccountCode.Register
public void SendAccountRequest(string accountName,string password,byte subCode)
{
AccountDto dto = new AccountDto();
dto.AccountName = accountName;
dto.Password = password;
Dictionary<byte, object> parameters = new Dictionary<byte, object>();
parameters[0] = JsonUtility.ToJson(dto);
PhotonManager.Instance.OnOperationRequest((byte)OpCode.Account, parameters, subCode);
}

ChatView

  聊天房间界面UI响应,包括一个用户名(字符串)和对应Perfab的字典。用户的进入和离开都操作这个字典。


测试结果

1. 运行测试。

Unity 使用Photon Server 创建一个简单聊天室

2. 登录一个没注册的号,登录失败。

Unity 使用Photon Server 创建一个简单聊天室

3. 注册一个充满优秀品质的帐号。

Unity 使用Photon Server 创建一个简单聊天室

4. 登录该账户并发送一条惊人的信息。

Unity 使用Photon Server 创建一个简单聊天室

5. 在另一个客户端登录另一个帐号,并发送信息。

Unity 使用Photon Server 创建一个简单聊天室

6. 回到原来的客户端查看。

Unity 使用Photon Server 创建一个简单聊天室


数据库用户列表操作见另一篇:Unity C# 连接SQL Server数据库,实现获取和添加登录注册的用户列表