Unity客户端与服务端交互之Event

功能:

客户端1,2都连接了服务器;

客户端1给服务器发了消息“asdasd”

服务器做Event事件发给所有客户端

客户端1,2全都收到了消息“asdasd”

 

注意点:MyGameServer里面,一个peer就是一个连接,所以我们每次有一个客户端连接,就要把其peer添加到一个list中。服务器然后在发送Event的时候,遍历List,群发就ok。

———————————————————————————————————————————

服务端

ChatHandler.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using Photon.SocketServer;

namespace RRGameServer.Handler
{
    class ChatHandler : BaseHandler
    {
        public ChatHandler()
        {
            OpCode = Common.OperationCode.Chat;
        }

        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer)
        {
            string hello = DicTool.GetValue<byte, object>(operationRequest.Parameters, (byte)ParaCode.Chat) as string;
            MyGameServer.log.Info("收到客户端发来的聊天内容:" + hello);

            //返回:已经收到消息
            OperationResponse response = new OperationResponse(operationRequest.OperationCode);
            response.ReturnCode = (short)Common.ReturnCode.Success;
            peer.SendOperationResponse(response, sendParameters);

            //发送给其他的客户端 OnEvent
            //发给自己
            //推送一个Event
            EventData ed = new EventData((byte)OperationCode.Chat);//操作码
            var data2 = new Dictionary<byte, object>();
            data2.Add((byte)ParaCode.Chat, hello);//参数码
            ed.Parameters = data2;
            //peer.SendEvent(ed, new SendParameters());
            foreach (var peerItem in MyGameServer.Instance.PeerList)
            {
                peerItem.SendEvent(ed, new SendParameters());
            }
        }
    }
}

MyGameServer.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using Photon.SocketServer;
using RRGameServer.Handler;
using RRGameServer.Manager;

namespace RRGameServer
{
    //所有的Server,都要继承ApplicationBase,然后实现ApplicationBase的三个方法
    public class MyGameServer : ApplicationBase
    {
        public static MyGameServer Instance;
        public static readonly ILogger log = LogManager.GetCurrentClassLogger();
        public List<PeerBase> PeerList = new List<PeerBase>();//用户保存所有的peer,一个客户端连接就会有一个peer

        //当有一个客户端连接上以后,就会执行此方法
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            log.Info("一个客户端连接");
            var p = new ClientPeer(initRequest);
            PeerList.Add(p);
            return p;
        }

        //服务器初始化函数
        protected override void Setup()
        {
            Instance = this;
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(
                Path.Combine(this.ApplicationRootPath, "bin_Win64"), "log");
            FileInfo configFileInfo = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));

            if (configFileInfo.Exists)
            {
                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);//photon知道日志输出
                XmlConfigurator.ConfigureAndWatch(configFileInfo);//读取配置
            }
            log.Info("服务器启动啦");

            //log.Info(UserManager.Instance.GetUserById(7).Username);
            InitHandler();//初始化
        }

        //服务器关闭函数
        protected override void TearDown()
        {
            log.Info("服务器关闭啦");
        }

        public Dictionary<OperationCode, BaseHandler> HandlerDic = new Dictionary<OperationCode, BaseHandler>();

        public void InitHandler()
        {
            //一开始就全部初始化
            LoginHandler LH = new LoginHandler();
            //log.Info("初始化操作码:" + LH.OpCode);
            HandlerDic.Add(LH.OpCode, LH);
            SignHandler handler = new SignHandler();
            HandlerDic.Add(handler.OpCode, handler);
            ChatHandler chathandler = new ChatHandler();
            HandlerDic.Add(chathandler.OpCode, chathandler);
        }

    }
}

———————————————————————————————————————————

客户端

ChatRequest.cs:

using System.Collections;
using System.Collections.Generic;
using Common;
using ExitGames.Client.Photon;
using UnityEngine;
using UnityEngine.UI;

public class ChatRequest : Request
{
    public InputField input;
    [HideInInspector]
    public string Hello;
    public override void DefaultRequest()
    {
        //构造参数
        var data = new Dictionary<byte, object>();
        //构造参数
        data.Add((byte)ParaCode.Chat, Hello);
        //发送
        PhotonEngine.peer.OpCustom((byte)OpCode, data, true);
    }


    public override void OnOprationRespionse(OperationResponse operationResponse)
    {
        if (operationResponse.ReturnCode == (byte)ReturnCode.Success)
        {
            Debug.Log("发送成功");
        }
        else
        {
            Debug.Log("发送失败");
        }
    }

    public void OnChatBtn()
    {
        Hello = input.text;
        DefaultRequest();
    }
}

PhotonEngine.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;
using Common;

public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {
    public static PhotonEngine Instance;

    //用字典来缓存每次的请求和码
    //这里就能体现出来我们Request抽象类的好处了,不然每次这边都是不同的类型,使用抽象类就统一了
    private Dictionary<OperationCode, Request> RequestDic = new Dictionary<OperationCode, Request>();

    public static PhotonPeer peer;
    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            //当前Gameobject不会随场景的销毁而销毁
            DontDestroyOnLoad(this.gameObject);
        }
    }

    void Start () {
        peer = new PhotonPeer(this,ConnectionProtocol.Udp);
        peer.Connect("127.0.0.1:5055", "MyGame6");//通过ip连接到到对应的我们config中配置的Allpication
	}
	
	void Update () {
        peer.Service();//开启服务
	}

    private void OnDestroy()//销毁的时候
    {
        if(peer!=null&&peer.PeerState == PeerStateValue.Connected)//如果存在且保持连接状态
        {
            peer.Disconnect();//就断开连接
        }
    }

    public void DebugReturn(DebugLevel level, string message)
    {
    }

    public void OnEvent(EventData eventData)
    {
        if ((byte)OperationCode.Chat == eventData.Code)
        {
            var data = eventData.Parameters;
            object intValue;
            data.TryGetValue((byte)ParaCode.Chat, out intValue);
            Debug.Log("收到服务器:"+intValue);
        }
        return;
        switch (eventData.Code)
        {
            //case 1:
            //    //解析数据
            //    var data = eventData.Parameters;
            //    object intValue, StringValue;
            //    data.TryGetValue(1, out intValue);
            //    data.TryGetValue(2, out StringValue);
            //    Debug.Log("收到服务器的响应Event推送,OpCode:1" + intValue.ToString() + ":" + StringValue.ToString());
            //    break;

            default:
                break;
        }
    }

    public void OnOperationResponse(OperationResponse operationResponse)
    {
        Request request = null;
        //此处就是工具类
        DicTool.GetValue(RequestDic, (OperationCode)operationResponse.OperationCode)
            .OnOprationRespionse(operationResponse);

        //下面注释的代码可以用上方工具类代替
        //bool b =RequestDic.TryGetValue((OperationCode)operationResponse.OperationCode, out request);
        //if (b)
        //{
        //    request.OnOprationRespionse(operationResponse);
        //}
        //else
        //{
        //    Debug.LogError("未找到对应code的请求request");
        //}

        return;
        //switch (operationResponse.OperationCode)
        //{
        //    case 1:
        //        Debug.Log("收到服务器的响应,OpCode:1");

        //        //解析数据
        //        var data = operationResponse.Parameters;
        //        object intValue;
        //        data.TryGetValue(1, out intValue);
        //        object StringValue;
        //        data.TryGetValue(2, out StringValue);
        //        Debug.Log("收到客户端的请求,OpCode:1" + intValue.ToString() + ":" + StringValue.ToString());
        //        break;
        //            default:
        //                break;
        //        }
        }

    public void OnStatusChanged(StatusCode statusCode)
    {
        Debug.LogError(statusCode);
    }

    //private Dictionary<OperationCode, Request> RequestDic = new Dictionary<OperationCode, Request>();

    public void AddRequest(Request r)
    {
        RequestDic.Add(r.OpCode, r);
    }
    public void RemoveRequest(Request r)
    {
        RequestDic.Remove(r.OpCode);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Unity中实现本地客户端服务端之间发送图片,可以使用Unity自带的网络库UNET。具体步骤如下: 1. 创建一个空的Unity项目,然后在Unity编辑器中选择“Assets”->“Import Package”->“Custom Package”,导入UNET网络库。 2. 创建一个新的场景,并在场景中创建一个空对象,命名为“NetworkManager”。 3. 在“NetworkManager”对象上添加“NetworkManager”组件,并设置“Network Address”为“LocalHost”(表示连接到本地服务器)。 4. 在“NetworkManager”对象上添加“NetworkManagerHUD”组件,这将允许你在游戏运行时连接到本地服务器,并显示连接状态。 5. 在场景中创建一个新的空对象,命名为“MyNetworkManager”。 6. 在“MyNetworkManager”对象上添加以下脚本: ```csharp using UnityEngine; using UnityEngine.Networking; public class MyNetworkManager : NetworkManager { public void SendImage(byte[] data) { // 创建一个网络消息对象,用于发送图片数据 ImageMessage msg = new ImageMessage(); msg.imageData = data; // 向所有客户端发送消息 NetworkServer.SendToAll(MsgType.Custom, msg); } } // 自定义网络消息类型,用于发送图片数据 public class ImageMessage : MessageBase { public byte[] imageData; } ``` 7. 在场景中创建一个新的空对象,命名为“ImageSender”。 8. 在“ImageSender”对象上添加以下脚本: ```csharp using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System.IO; public class ImageSender : MonoBehaviour { public MyNetworkManager networkManager; public RawImage image; public Button sendButton; // Start is called before the first frame update void Start() { sendButton.onClick.AddListener(OnSendButtonClick); } // 发送按钮点击事件 void OnSendButtonClick() { // 将RawImage中的图片数据转换为PNG格式 Texture2D tex = (Texture2D)image.texture; byte[] data = tex.EncodeToPNG(); // 调用网络管理器发送图片数据 networkManager.SendImage(data); } } ``` 9. 在场景中创建一个新的空对象,命名为“ImageReceiver”。 10. 在“ImageReceiver”对象上添加以下脚本: ```csharp using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System.IO; public class ImageReceiver : NetworkBehaviour { public RawImage image; // 启动时注册网络消息类型 void Start() { NetworkManager.singleton.client.RegisterHandler(MsgType.Custom, OnReceiveImage); } // 接收到图片数据后的处理函数 void OnReceiveImage(NetworkMessage netMsg) { // 解析网络消息,获取图片数据 ImageMessage msg = netMsg.ReadMessage<ImageMessage>(); byte[] data = msg.imageData; // 创建Texture2D对象,并从数据中加载图片 Texture2D tex = new Texture2D(1, 1); tex.LoadImage(data); // 将图片显示在RawImage组件中 image.texture = tex; } } ``` 现在你已经完成了客户端服务端的代码编写。在场景中添加一个RawImage组件,用于显示图片。然后将“ImageSender”和“ImageReceiver”对象拖到场景中,并将“NetworkManager”对象拖到“ImageSender”的“networkManager”属性中。 运行游戏,并点击“ImageSender”对象上的“sendButton”按钮,你将看到RawImage组件中显示了发送的图片。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值