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

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

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

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


MyGameServer服务器配置

工程结构


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

项目名、文件夹名、文件名说明
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直接调用。

  传输Dto时需要转换成Json,添加LitJson插件。


服务器结构

项目名、文件夹名、文件名说明
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.configlog for net。从别的Photon样例工程复制过来,拿来输出自定义日志用的配置。
MyApplication整个服务器的入口。继承至ApplicationBase。当有客户端连接时调用CreatePeer,连接客户端。
MyClientPeer连接的进来的客户端。通过它接收、处理、发送客户端的信息。

  服务器所需要添加的引用,添加在服务器工程lib目录下,从Photon的lib目录下找到下面这些DLL。

  配置到Photon,便于启动服务器。
配置文件点我:PhotonServer.config


客户端结构

UI介绍

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

客户端脚本介绍

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. 运行测试。

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

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

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

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

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


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

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值