服务器Chat通信协定
修改服务器的GameMsg
,添加聊天需要的类:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #region 聊天相关 [System.Serializable] public class SndChat { public string chat; } [System.Serializable] public class PshChat { public string name; public string chat; } #endregion
|
服务器ChatSys
首先给CacheSvc
添加获取所有在线客户端的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| using PEProtocol; using System.Collections.Generic;
public class ChatSys:SingletonPattern<ChatSys> { private CacheSvc _cacheSvc; public void Init() { _cacheSvc = CacheSvc.Instance; PECommon.Log("StrongSys Init Done"); }
public void SendChat(MsgPack msgPack) { SndChat data = msgPack.msg.sndChat; PlayerData pd = _cacheSvc.GetPalyerDataBySession(msgPack.session);
GameMsg msg = new GameMsg { cmd = (int)CMD.PshChat,
pshChat = new PshChat { name = pd.name, chat = data.chat, } }; List<ServerSession> serverSessions = _cacheSvc.GetOnlineServerSessions(); byte[] bytes = PENet.PETool.PackNetMsg(msg); serverSessions.ForEach(session => { session.SendMsg(bytes); }); } }
|
这里使用session.SendMsg(bytes)
而不是session.SendMsg(msg)
session.SendMsg(msg)
每个session发送一次消息都要进行一次序列化,假设服务器有3000个客户端,则需要3000次序列化,但是每个客户端的世界广播消息都是一样的
session.SendMsg(bytes)
将相同的广播消息提前序列化,再发送,节省CPU。使用PENet.PETool.PackNetMsg(msg)
来序列化。
BuyWnd窗口复用
在游戏内点击购买体力和金币的按钮,都会弹出一样的确认窗口,但是会显示不同的确认文字,我们使用一个int值来确定每次RefreshUI时要显示的内容
BuyWnd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| using UnityEngine; using UnityEngine.UI; using TMPro;
namespace DarknessWarGodLearning { public class BuyWnd : WindowRoot { [SerializeField] private Button btnClose, btnSure; [SerializeField] private TextMeshProUGUI txtInfo; private int buyType; protected override void InitWnd() { btnClose.onClick.AddListener(ClickCloseBtn); btnSure.onClick.AddListener(ClickSureBtn); base.InitWnd(); RefreshUI(); } public void SetBuyType(int buyType) { this.buyType = buyType; } private void RefreshUI() { switch(buyType) { case 0: SetText(txtInfo, "是否花费" + Constants.Color("10钻石",TxtColor.Red) + "购买" + Constants.Color("100体力",TxtColor.Green)+"?"); break; case 1: SetText(txtInfo, "是否花费" + Constants.Color("10钻石",TxtColor.Red) + "购买" + Constants.Color("1000金币",TxtColor.Green)+"?"); break; } } private void ClickCloseBtn() { audioSvc.PlayUIAudio(Constants.UIClickBtn); SetWndState(false); } private void ClickSureBtn() { audioSvc.PlayUIAudio(Constants.UIClickBtn); } private void OnDisable() { btnClose.onClick.RemoveAllListeners(); btnSure.onClick.RemoveAllListeners(); } } }
|
服务器Buy通信协定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #region 资源交易相关 [System.Serializable] public class ReqBuy { public int buytype; public int cost; } [System.Serializable] public class RspBuy { public int buytype; public int diamond; public int coin; public int power; } #endregion
|
防止客户端重复购买
如果客户端购买时服务器没有及时回应,可能会导致购买窗口无法及时关闭,玩家可能会重复点击购买。我们需要在客户端进行一些保护
BuyWnd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| using UnityEngine; using UnityEngine.UI; using TMPro; using PEProtocol;
namespace DarknessWarGodLearning { public class BuyWnd : WindowRoot { [SerializeField] private Button btnClose, btnSure; protected override void InitWnd() { base.InitWnd(); btnSure.interactable = true; RefreshUI(); } private void ClickSureBtn() { btnSure.interactable = false; } private void OnDisable() { btnClose.onClick.RemoveAllListeners(); btnSure.onClick.RemoveAllListeners(); } } }
|