当前位置:   article > 正文

Unity组件开发--长连接webSocket_comfyui websocket

comfyui websocket

1.下载安装UnityWebSocket 插件

https://gitee.com/cambright/UnityWebSocket/

引入unity项目:

2.定义消息体结构:ExternalMessage和包结构Package:

  1. using ProtoBuf;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. namespace UTNET
  7. {
  8. [ProtoContract]
  9. public class ExternalMessage
  10. {
  11. [ProtoMember(1)]
  12. // 请求命令类型: 0 心跳,1 业务
  13. public int cmdCode;
  14. // 协议开关,用于一些协议级别的开关控制,比如 安全加密校验等。 : 0 不校验
  15. [ProtoMember(2)]
  16. public int protocolSwitch;
  17. // 业务路由(高16为主, 低16为子)
  18. [ProtoMember(3)]
  19. public uint cmdMerge;
  20. // 响应码: 0:成功, 其他为有错误
  21. [ProtoMember(4,DataFormat = DataFormat.ZigZag)]
  22. public int responseStatus;
  23. // 验证信息(错误消息、异常消息),通常情况下 responseStatus == -1001 时, 会有值
  24. [ProtoMember(5)]
  25. public string validMsg;
  26. // 业务请求数据
  27. [ProtoMember(6)]
  28. public byte[] data;
  29. // 消息标记号;由前端请求时设置,服务器响应时会携带上;
  30. [ProtoMember(7, DataFormat = DataFormat.ZigZag)]
  31. public int msgId;
  32. }
  33. [ProtoContract]
  34. public class Package
  35. {
  36. [ProtoMember(1)]
  37. public uint packageType;
  38. [ProtoMember(2)]
  39. public string route = null;
  40. [ProtoMember(3)]
  41. public uint packID = 0;
  42. [ProtoMember(4)]
  43. public byte[] buff = null;
  44. [ProtoMember(5)]
  45. public string modelName = null;
  46. }
  47. //[ProtoContract]
  48. //public class Message<T>
  49. //{
  50. // [ProtoMember(1)]
  51. // public uint err;
  52. // [ProtoMember(2)]
  53. // public string errMsg = default;
  54. // [ProtoMember(3)]
  55. // public T data = default;
  56. // public Message() { }
  57. // public Message(uint err, string errMsg, T info)
  58. // {
  59. // this.err = err;
  60. // this.errMsg = errMsg;
  61. // this.data = info;
  62. // }
  63. //}
  64. [ProtoContract]
  65. public class HandShake
  66. {
  67. [ProtoMember(1)]
  68. public string token;
  69. }
  70. [ProtoContract]
  71. public class Heartbeat
  72. {
  73. [ProtoMember(1)]
  74. public uint heartbeat;
  75. }
  76. }

3.定义包协议结构:PackageProtocol

  1. using ProtoBuf;
  2. using System;
  3. using System.IO;
  4. using System.Text;
  5. using UnityEngine.XR;
  6. namespace UTNET
  7. {
  8. public enum PackageType
  9. {
  10. HEARTBEAT = 1,
  11. REQUEST = 2,
  12. PUSH = 3,
  13. KICK = 4,
  14. RESPONSE = 5,
  15. HANDSHAKE = 6,
  16. ERROR = 7,
  17. NOTIFY = 8
  18. }
  19. public class PackageProtocol
  20. {
  21. //获取cmd
  22. public static uint getCmd(uint merge)
  23. {
  24. return merge >> 16;
  25. }
  26. //获取subCmd
  27. public static uint getSubCmd(uint merge)
  28. {
  29. return merge & 0xFFFF;
  30. }
  31. //获取mergeCmd
  32. public static uint getMergeCmd(uint cmd, uint subCmd)
  33. {
  34. return (cmd << 16) + subCmd;
  35. }
  36. public static byte[] Encode(PackageType type)
  37. {
  38. Package sr = new Package()
  39. {
  40. packageType = (uint)type
  41. };
  42. return Serialize(sr);
  43. }
  44. public static byte[] Encode<T>(PackageType type, uint packID, string route, T info, string modelName = null)
  45. {
  46. Package sr = new Package()
  47. {
  48. packageType = (uint)type,
  49. packID = packID,
  50. route = route,
  51. buff = Serialize<T>(info),
  52. modelName = modelName
  53. };
  54. return Serialize(sr);
  55. }
  56. public static byte[] EncodeEx<T>(uint packID, uint cmdMerge, T info)
  57. {
  58. //Package sr = new Package()
  59. //{
  60. // packageType = (uint)type,
  61. // packID = packID,
  62. // route = route,
  63. // buff = Encoding.Default.GetBytes(SerializeEx<T>(info)),
  64. //};
  65. //return SerializeEx(sr);
  66. ExternalMessage sr = new ExternalMessage()
  67. {
  68. cmdCode = 100,
  69. protocolSwitch = 1,
  70. cmdMerge = cmdMerge,
  71. responseStatus = 0,
  72. validMsg = "",
  73. data = Encoding.UTF8.GetBytes(SerializeEx<T>(info)),
  74. };
  75. return Serialize(sr);
  76. }
  77. public static byte[] Encode<T>(uint packID, uint cmdMerge, T info)
  78. {
  79. ExternalMessage sr = new ExternalMessage()
  80. {
  81. cmdCode = 100,
  82. protocolSwitch = 1,
  83. cmdMerge = cmdMerge,
  84. responseStatus = 0,
  85. validMsg = "",
  86. data = Serialize<T>(info),
  87. msgId = (int)packID,
  88. };
  89. return Serialize(sr);
  90. }
  91. public static string SerializeEx<T>(T t)
  92. {
  93. using (MemoryStream ms = new MemoryStream())
  94. {
  95. Serializer.Serialize<T>(ms, t);
  96. return Encoding.UTF8.GetString(ms.ToArray());
  97. }
  98. }
  99. public static byte[] Serialize<T>(T info)
  100. {
  101. if (typeof(T) == typeof(int))
  102. {
  103. int value = (int)Convert.ChangeType(info, typeof(int));
  104. value = (value << 1);
  105. info = (T)Convert.ChangeType(info, typeof(T));
  106. }
  107. MemoryStream ms = new MemoryStream();
  108. Serializer.Serialize(ms, info);
  109. byte[] buff = ms.ToArray();
  110. ms.Close();
  111. return buff;
  112. //try
  113. //{
  114. // //涉及格式转换,需要用到流,将二进制序列化到流中
  115. // using (MemoryStream ms = new MemoryStream())
  116. // {
  117. // //使用ProtoBuf工具的序列化方法
  118. // Serializer.Serialize<T>(ms, info);
  119. // //定义二级制数组,保存序列化后的结果
  120. // byte[] result = new byte[ms.Length];
  121. // //将流的位置设为0,起始点
  122. // ms.Position = 0;
  123. // //将流中的内容读取到二进制数组中
  124. // ms.Read(result, 0, result.Length);
  125. // return result;
  126. // }
  127. //}
  128. //catch (Exception ex)
  129. //{
  130. // return null;
  131. //}
  132. }
  133. public static ExternalMessage Decode(byte[] buff)
  134. {
  135. //protobuf反序列化
  136. MemoryStream mem = new MemoryStream(buff);
  137. ExternalMessage rs = Serializer.Deserialize<ExternalMessage>(mem);
  138. mem.Close();
  139. return rs;
  140. }
  141. public static T DecodeInfo<T>(byte[] buff)
  142. {
  143. if (buff == null) return default;
  144. T rs;
  145. if (typeof(T) == typeof(int))
  146. {
  147. int value;
  148. using (var stream = new MemoryStream(buff))
  149. {
  150. value = Serializer.Deserialize<int>(stream);
  151. }//转zig zag
  152. value = (value >> 1) ^ -(value & 1);
  153. rs = (T)Convert.ChangeType(value, typeof(T));
  154. }
  155. else
  156. {
  157. MemoryStream mem = new MemoryStream(buff);
  158. rs = Serializer.Deserialize<T>(mem);
  159. mem.Close();
  160. }
  161. return rs;
  162. }
  163. //public static T MyMethod<T>(byte[] buff) where T : Object
  164. //{
  165. // return null;
  166. //}
  167. }
  168. }

4.引入UniTask插件:UniTask中文使用指南(一) - 知乎

UniTask保姆级教程_unitask安装-CSDN博客

项目地址:GitHub - Cysharp/UniTask: Provides an efficient allocation free async/await integration for Unity.

5.定义协议索引管理,添加长连接的协议:ProtoMaps

  1. using System;
  2. using System.Collections.Generic;
  3. namespace UTNET
  4. {
  5. public interface IProto
  6. {
  7. }
  8. //R ��������, S ��������
  9. //public class Proto<R, S> : IProto
  10. public class Proto : IProto
  11. {
  12. public string name; //������
  13. public uint mid { get; set; } //��id
  14. public uint sid { get; set; } //��id
  15. public uint mergeid;
  16. public int typ; //������
  17. //public R r;
  18. //public S s;
  19. public Proto(string name, uint mid, uint sid, int typ)
  20. {
  21. this.name = name;
  22. this.mid = mid;
  23. this.sid = sid;
  24. this.typ = typ;
  25. }
  26. }
  27. public class ProtoMaps
  28. {
  29. private static readonly ProtoMaps instance = new ProtoMaps();
  30. public static ProtoMaps Instance
  31. {
  32. get { return instance; }
  33. }
  34. //public Dictionary<string, IProto> protos = new Dictionary<string, IProto>();
  35. public Dictionary<string, Proto> protos = new Dictionary<string, Proto>();
  36. public Dictionary<uint, Proto> id2proto = new Dictionary<uint, Proto>();
  37. public void Add(string name, Proto pb)
  38. {
  39. protos.Add(name, pb);
  40. }
  41. public void SortById()
  42. {
  43. foreach (var item in protos)
  44. {
  45. var pb = item.Value;
  46. uint mergeid = PackageProtocol.getMergeCmd(pb.mid, pb.sid);
  47. pb.mergeid = mergeid;
  48. id2proto.Add(mergeid, pb);
  49. }
  50. }
  51. public ProtoMaps()
  52. {
  53. this.Add("login", new Proto("login", 1, 2, 1));
  54. this.Add("registerInfo", new Proto("registerInfo", 1, 1, 1));
  55. this.Add("enterRoom", new Proto("enterRoom", 1, 13, 3));
  56. this.Add("roleMove", new Proto("roleMove", 4, 3, 3));
  57. //this.Add("onNewRoleEnter", new Proto("onNewRoleEnter", 7, 1, 2));
  58. //服务器主动广播的角色退出
  59. this.Add("roleExitRoom", new Proto("roleExitRoom", 7, 2, 2));
  60. this.Add("talkMrg", new Proto("talkMrg", 1, 9, 3));
  61. //玩家点击的角色退出
  62. this.Add("playerExitRoom", new Proto("playerExitRoom", 1, 5, 3));
  63. this.Add("gameFrame", new Proto("gameFrame", 4, 2, 1));
  64. this.Add("gameObjUsed", new Proto("gameObjUsed", 4, 4, 3));
  65. this.Add("getOtherInfo", new Proto("getOtherInfo", 1, 23, 1));
  66. this.Add("heatBeat", new Proto("heatBeat", 1, 120, 1));
  67. SortById();
  68. }
  69. public Proto Name2Pb(string name)
  70. {
  71. //Proto pb = ProtoMaps.Instance.protos[name];
  72. if (protos.ContainsKey(name))
  73. {
  74. return protos[name];
  75. }
  76. return null;
  77. }
  78. internal Proto GetByMergeId(uint cmdMerge)
  79. {
  80. if (id2proto.ContainsKey(cmdMerge))
  81. {
  82. return id2proto[cmdMerge];
  83. }
  84. return null;
  85. }
  86. }
  87. }

6.定义心跳协议类:HeartBeatServiceGameObject

  1. using System;
  2. using UnityEngine;
  3. using UnityWebSocket;
  4. namespace UTNET
  5. {
  6. public class HeartBeatServiceGameObject : MonoBehaviour
  7. {
  8. public Action OnServerTimeout;
  9. private WebSocket socket;
  10. public float interval = 0;
  11. public long lastReceiveHeartbeatTime;
  12. void Start()
  13. {
  14. }
  15. static DateTime dt = new DateTime(1970, 1, 1);
  16. public static long GetTimestamp()
  17. {
  18. TimeSpan ts = DateTime.Now.ToUniversalTime() - dt;
  19. return (long)ts.TotalSeconds;
  20. }
  21. public float t;
  22. void Update()
  23. {
  24. t += Time.deltaTime;
  25. if (t > interval)
  26. {
  27. CheckAndSendHearbeat();
  28. t = 0;
  29. }
  30. }
  31. private void CheckAndSendHearbeat()
  32. {
  33. //檢查最後一次取得心跳包的時間是否小於客戶端心跳間隔時間
  34. long curTime = GetTimestamp();
  35. long intervalSec = curTime - lastReceiveHeartbeatTime;
  36. if (intervalSec > interval)
  37. {
  38. //Debug.Log(string.Format("XXXX CheckAndSendHearbeat:s1:{0} l:{1} s:{2}", curTime, lastReceiveHeartbeatTime, intervalSec));
  39. this.enabled = false;
  40. OnServerTimeout?.Invoke();
  41. }
  42. else
  43. {
  44. //Debug.Log(string.Format(" CheckAndSendHearbeat:s1:{0} l:{1} s:{2}", curTime, lastReceiveHeartbeatTime, intervalSec));
  45. this.enabled = true;
  46. SendHeartbeatPack();
  47. }
  48. }
  49. public void HitHole()
  50. {
  51. lastReceiveHeartbeatTime = GetTimestamp();
  52. }
  53. private void SendHeartbeatPack()
  54. {
  55. //lastSendHeartbeatPackTime = DateTime.Now;
  56. byte[] package = PackageProtocol.Encode(
  57. PackageType.HEARTBEAT);
  58. socket.SendAsync(package);//*/
  59. }
  60. internal void Setup(uint interval, Action onServerTimeout, WebSocket socket)
  61. {
  62. this.socket = socket;
  63. this.interval = (interval / 1000 )/2;
  64. this.OnServerTimeout = onServerTimeout;
  65. this.enabled = true;
  66. SendHeartbeatPack();
  67. }
  68. internal void ResetTimeout(uint interval)
  69. {
  70. this.enabled = true;
  71. this.interval = (interval / 1000) / 2;
  72. t = 0;
  73. //long s1 = GetTimestamp();
  74. //long s = (s1 - lastReceiveHeartbeatTime);
  75. //Debug.Log(string.Format("ResetTimeout: s1:{0} l:{1} s:{2} s > interval:{3}", s1, lastReceiveHeartbeatTime, s, s > interval));
  76. lastReceiveHeartbeatTime = GetTimestamp();
  77. SendHeartbeatPack();
  78. }
  79. internal void Stop()
  80. {
  81. this.enabled = false;
  82. t = 0;
  83. }
  84. }
  85. }

7.定义协议类Protocol:

  1. using Cysharp.Threading.Tasks;
  2. using ProtoBuf;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Net;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using UnityEditor;
  10. using UnityEngine;
  11. using UnityWebSocket;
  12. namespace UTNET
  13. {
  14. public class Protocol
  15. {
  16. Dictionary<uint, Action<ExternalMessage>> packAction = new Dictionary<uint, Action<ExternalMessage>>();
  17. UniTaskCompletionSource<bool> handshakeTcs;
  18. Dictionary<uint, UniTaskCompletionSource<ExternalMessage>> packTcs = new Dictionary<uint, UniTaskCompletionSource<ExternalMessage>>();
  19. //Dictionary<uint, Action<T>> attention = new Dictionary<uint, Action<T>>();
  20. WebSocket socket;
  21. public HeartBeatServiceGameObject heartBeatServiceGo;
  22. public Action OnReconected;
  23. public Action<string> OnError;
  24. public void SetSocket(WebSocket socket)
  25. {
  26. this.socket = socket;
  27. }
  28. public UniTask<bool> HandsharkAsync(string token)
  29. {
  30. handshakeTcs = new UniTaskCompletionSource<bool>();
  31. return handshakeTcs.Task;
  32. }
  33. internal void Notify<T>(string route, T info)
  34. {
  35. byte[] packBuff = PackageProtocol.Encode<T>(
  36. PackageType.NOTIFY,
  37. 0,
  38. route,
  39. info);
  40. socket.SendAsync(packBuff);
  41. }
  42. public UniTask<ExternalMessage> RequestAsync<T>(uint packID, uint route, T info = default, string modelName = null)
  43. {
  44. lock (packTcs)
  45. {
  46. UniTaskCompletionSource<ExternalMessage> pack = new UniTaskCompletionSource<ExternalMessage>();
  47. byte[] packBuff = PackageProtocol.Encode<T>(packID, route, info);
  48. packTcs.Add(packID, pack);
  49. //packTcs.Add(route, pack); //暂不支持,同一协议多次发送
  50. //byte[] ints = System.BitConverter.GetBytes(IPAddress.HostToNetworkOrder(testInt));
  51. //ByteBuffer bbBuffer = ByteBuffer.wrap(bs);
  52. //bbBuffer.order(ByteOrder.BIG_ENDIAN);
  53. socket.SendAsync(packBuff);
  54. return pack.Task;
  55. }
  56. }
  57. public void CanceledAllUTcs()
  58. {
  59. lock (packTcs)
  60. {
  61. foreach (var tcs in packTcs)
  62. {
  63. tcs.Value.TrySetCanceled();
  64. }
  65. packTcs.Clear();
  66. if(handshakeTcs!=null) handshakeTcs.TrySetCanceled();
  67. }
  68. }
  69. public async void OnReceive(byte[] bytes)
  70. {
  71. try
  72. {
  73. await UniTask.SwitchToMainThread();
  74. ExternalMessage package = PackageProtocol.Decode(bytes);
  75. uint mId = PackageProtocol.getCmd(package.cmdMerge);
  76. uint subId = PackageProtocol.getSubCmd(package.cmdMerge);
  77. Proto pb = ProtoMaps.Instance.GetByMergeId(package.cmdMerge);
  78. if (package.responseStatus != 0)
  79. {
  80. Debug.LogError("收到 cmd:" + mId + " &subcmd:" + subId);
  81. Debug.LogError("收到网络消息 " + package.cmdMerge);
  82. Debug.LogError("协议返回错误信息,查询errcode,后面可能根据弹窗处理: Errmsg->" + package.validMsg + " & Errcode->" + package.responseStatus );
  83. onShowNetError(package.responseStatus, mId, subId);
  84. return;
  85. }
  86. if (pb == null)
  87. {
  88. Debug.Log("收到未在 ProtoMaps 注册的 网络消息 " + package.cmdCode);
  89. return;
  90. }
  91. if (PackageProtocol.getCmd(package.cmdMerge) == 0)
  92. {
  93. Debug.Log("心跳数据 ");
  94. return;
  95. }
  96. ResponseHandler(package);
  97. PushHandler(package);
  98. //if (pb.typ == 1)
  99. //{
  100. //}
  101. //else if (pb.typ == 2)
  102. //{
  103. // PushHandler(package);
  104. //}
  105. //else
  106. //{
  107. // if (!ResponseHandler(package))
  108. // PushHandler(package);
  109. //}
  110. //Package package = PackageProtocol.Decode(bytes);
  111. //Debug.Log(package.packageType);
  112. //switch ((PackageType)package.packageType)
  113. //{
  114. // case PackageType.HEARTBEAT:
  115. // //Debug.LogWarning("get HEARTBEAT");
  116. // heartBeatServiceGo.HitHole();
  117. // break;
  118. // case PackageType.RESPONSE:
  119. // ResponseHandler(package);
  120. // break;
  121. // case PackageType.PUSH:
  122. // PushHandler(package);
  123. // break;
  124. // case PackageType.HANDSHAKE:
  125. // HandshakeHandler(package);
  126. // break;
  127. // case PackageType.KICK:
  128. // //HandleKick(package);
  129. // break;
  130. // case PackageType.ERROR:
  131. // ErrorHandler(package);
  132. // break;
  133. // default:
  134. // Debug.Log("No match packageType::" + package.packageType);
  135. // break;
  136. //}
  137. }
  138. catch (Exception e)
  139. {
  140. ExternalMessage package = PackageProtocol.Decode(bytes);
  141. Proto pb = ProtoMaps.Instance.GetByMergeId(package.cmdMerge);
  142. Debug.Log("错误协议-----" + JsonUtility.ToJson(pb));
  143. await UniTask.SwitchToMainThread();
  144. Debug.LogError(e);
  145. throw e;
  146. }
  147. }
  148. public void StopHeartbeat()
  149. {
  150. if (heartBeatServiceGo != null)
  151. {
  152. Debug.Log("Stop Heartbeat");
  153. heartBeatServiceGo.Stop();
  154. //heartBeatServiceGo = null;
  155. }
  156. }
  157. public void onShowNetError(int responseStatus,uint mid,uint subid) {
  158. }
  159. public void SetOnNet(uint route, Action<ExternalMessage> ac)
  160. {
  161. lock (packAction)
  162. {
  163. if (!packAction.ContainsKey(route))
  164. {
  165. packAction.Add(route, ac);
  166. }
  167. }
  168. }
  169. private void PushHandler(ExternalMessage pack)
  170. {
  171. lock (packAction)
  172. {
  173. uint route = pack.cmdMerge;
  174. if (packAction.ContainsKey(route))
  175. {
  176. #if SOCKET_DEBUG
  177. Debug.Log(string.Format("[Push] <<-- [{0}] {1}", pack.route, JsonUtility.ToJson(pack)));
  178. #endif
  179. packAction[route]?.Invoke(pack);
  180. //packAction.Remove(route); //监听事件不考虑删除由netmanager代理
  181. }
  182. }
  183. }
  184. private bool ResponseHandler(ExternalMessage package)
  185. {
  186. lock (packTcs)
  187. {
  188. uint msgId = (uint)package.msgId;
  189. //Debug.LogError("响应消息id" + msgId);
  190. if (packTcs.ContainsKey(msgId))
  191. {
  192. packTcs[msgId].TrySetResult(package);
  193. packTcs.Remove(msgId);
  194. return true;
  195. //if (packTcs.ContainsKey(package.cmdMerge))
  196. //{
  197. // packTcs.Remove(package.cmdMerge);
  198. // return true;
  199. //}
  200. }
  201. }
  202. return false;
  203. }
  204. //private void ResponseHandler(ExternalMessage package)
  205. //{
  206. // lock (packTcs)
  207. // {
  208. // packTcs[package.packID].TrySetResult(package);
  209. // if (packTcs.ContainsKey(package.packID))
  210. // {
  211. // packTcs.Remove(package.packID);
  212. // }
  213. // }
  214. //}
  215. private void HandshakeHandler(Package package)
  216. {
  217. Heartbeat msg = PackageProtocol.DecodeInfo<Heartbeat>(package.buff);
  218. if (msg.heartbeat > 0)
  219. {
  220. handshakeTcs.TrySetResult(false);
  221. return;
  222. }
  223. if (heartBeatServiceGo == null)
  224. {
  225. }
  226. else
  227. {
  228. OnReconected?.Invoke();
  229. heartBeatServiceGo.ResetTimeout(msg.heartbeat);
  230. }//*/
  231. handshakeTcs.TrySetResult(true);
  232. }
  233. private void ErrorHandler(Package package)
  234. {
  235. }
  236. private void OnServerTimeout()
  237. {
  238. if (socket.ReadyState == WebSocketState.Connecting)
  239. {
  240. socket.CloseAsync();
  241. }
  242. if (heartBeatServiceGo != null && socket.ReadyState != WebSocketState.Connecting && socket.ReadyState != WebSocketState.Open)
  243. {
  244. heartBeatServiceGo.Stop();
  245. }
  246. }
  247. }
  248. }

8.定义服务器对应的协议消息:TestProto.cs

  1. using ProtoBuf;
  2. using ProtoBuf.Meta;
  3. using System.Collections.Generic;
  4. [ProtoContract]
  5. public class RegisterInfo
  6. {
  7. [ProtoMember(1)]
  8. public string phoneNum;
  9. [ProtoMember(2)]
  10. public string account;
  11. [ProtoMember(3)]
  12. public string pwd;
  13. }
  14. [ProtoContract]
  15. public class LoginVerify
  16. {
  17. [ProtoMember(1)]
  18. public string account;
  19. [ProtoMember(2)]
  20. public string pwd;
  21. [ProtoMember(3, DataFormat = DataFormat.ZigZag)]
  22. public int loginBizCode;
  23. [ProtoMember(4, DataFormat = DataFormat.ZigZag)]
  24. public int spaceId;
  25. }
  26. [ProtoContract]
  27. public class LobbyTalkMsg
  28. {
  29. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  30. public long id;
  31. [ProtoMember(2, DataFormat = DataFormat.ZigZag)]
  32. public long usrId;
  33. [ProtoMember(3)]
  34. public string nickName;
  35. [ProtoMember(4, DataFormat = DataFormat.ZigZag)]
  36. public int to_usrId;
  37. [ProtoMember(5)]
  38. public string msg;
  39. [ProtoMember(6, DataFormat = DataFormat.ZigZag)]
  40. public int msg_type;
  41. }
  42. [ProtoContract]
  43. public class RequestSuccess
  44. {
  45. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  46. public int success;
  47. }
  48. [ProtoContract]
  49. public class GameFrame {
  50. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  51. public long frameId;
  52. [ProtoMember(2)]
  53. public string opc;
  54. [ProtoMember(3)]
  55. public string world;
  56. [ProtoMember(4)]
  57. public TankLocation location;
  58. }
  59. [ProtoContract]
  60. public class UserInfo {
  61. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  62. public long id;
  63. [ProtoMember(2)]
  64. public string nickName;
  65. [ProtoMember(3)]
  66. public string account;
  67. [ProtoMember(4)]
  68. public string gender;
  69. [ProtoMember(5)]
  70. public string headImgUrl;
  71. [ProtoMember(6, DataFormat = DataFormat.ZigZag)]
  72. public long avatarId;
  73. [ProtoMember(7)]
  74. public string avatar;
  75. [ProtoMember(8)]
  76. public string hold;
  77. [ProtoMember(9)]
  78. public string mtk;
  79. [ProtoMember(10)]
  80. public string ltk;
  81. [ProtoMember(11, DataFormat = DataFormat.ZigZag)]
  82. public long roomId;
  83. [ProtoMember(12, DataFormat = DataFormat.ZigZag)]
  84. public long team;
  85. [ProtoMember(13)]
  86. public TankLocation tankLocation;
  87. [ProtoMember(14, DataFormat = DataFormat.ZigZag)]
  88. public int speed;
  89. }
  90. [ProtoContract]
  91. public class TankLocation {
  92. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  93. public float x;
  94. [ProtoMember(2, DataFormat = DataFormat.ZigZag)]
  95. public float y;
  96. [ProtoMember(3, DataFormat = DataFormat.ZigZag)]
  97. public float z;
  98. [ProtoMember(4, DataFormat = DataFormat.ZigZag)]
  99. public float dx;
  100. [ProtoMember(5, DataFormat = DataFormat.ZigZag)]
  101. public float dy;
  102. [ProtoMember(6, DataFormat = DataFormat.ZigZag)]
  103. public float dz;
  104. [ProtoMember(7, DataFormat = DataFormat.ZigZag)]
  105. public long playerId;
  106. [ProtoMember(8, DataFormat = DataFormat.ZigZag)]
  107. public long time;
  108. }
  109. [ProtoContract]
  110. public class TankPlayer {
  111. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  112. public long id;
  113. [ProtoMember(2, DataFormat = DataFormat.ZigZag)]
  114. public int speed;
  115. [ProtoMember(3)]
  116. public TankLocation tankLocation;
  117. [ProtoMember(4)]
  118. public string nickname;
  119. [ProtoMember(5)]
  120. public string hold;
  121. // 其他属性: key: 子弹 id 1 玩具弹, 2 雪弹; value : 数量
  122. [ProtoMember(6)]
  123. public Dictionary<int, int> tankBulletMap;
  124. }
  125. [ProtoContract]
  126. public class TankEnterRoom {
  127. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  128. public long roomId;
  129. [ProtoMember(2, DataFormat = DataFormat.ZigZag)]
  130. public long time;
  131. [ProtoMember(3, DataFormat = DataFormat.ZigZag)]
  132. public long team;
  133. [ProtoMember(4, DataFormat = DataFormat.ZigZag)]
  134. public long playerId;
  135. [ProtoMember(5)]
  136. public string sharetoken;
  137. [ProtoMember(6)]
  138. public string usertoken;
  139. [ProtoMember(7)]
  140. public string world;
  141. [ProtoMember(8)]
  142. public List<UserInfo> tankPlayerList;
  143. }
  144. [ProtoContract]
  145. public class UserIds {
  146. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  147. public long[] userIds;
  148. }
  149. [ProtoContract]
  150. public class UserInfos
  151. {
  152. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  153. public UserInfo[] users;
  154. }
  155. [ProtoContract]
  156. public class HeartBeat
  157. {
  158. [ProtoMember(1, DataFormat = DataFormat.ZigZag)]
  159. public int beat;
  160. }

9.定义客户端处理消息类:Client:

  1. using System;
  2. using UnityEngine;
  3. using Cysharp.Threading.Tasks;
  4. using System.Threading;
  5. using System.Collections;
  6. using UnityWebSocket;
  7. namespace UTNET
  8. {
  9. public enum NetWorkState
  10. {
  11. CONNECTING,
  12. CONNECTED,
  13. DISCONNECTED,
  14. TIMEOUT,
  15. ERROR,
  16. KICK
  17. }
  18. public class Client
  19. {
  20. private static int RqID = 0;
  21. //public NetWorkState state;
  22. public Action OnReconected, OnDisconnect, OnConnected;
  23. public Action<string> OnError;
  24. public uint retry;
  25. public bool isConnect = false;
  26. Protocol protocol;
  27. WebSocket socket;
  28. UniTaskCompletionSource<bool> utcs;
  29. private bool isForce;
  30. private bool isHeardbeat = false;
  31. private string host;
  32. public Client(string host)
  33. {
  34. Debug.Log("Client" + host);
  35. this.host = host;
  36. this.createSocket();
  37. }
  38. private void createSocket()
  39. {
  40. if (socket != null) {
  41. }
  42. Debug.Log("createSocket host=" + this.host);
  43. utcs = new UniTaskCompletionSource<bool>();
  44. if (socket != null) {
  45. socket.CloseAsync();
  46. socket.OnClose += ReCreateSocket;
  47. }
  48. else {
  49. socket = new WebSocket(this.host);
  50. socket.OnOpen += OnOpen;
  51. socket.OnMessage += OnMessage;
  52. socket.OnClose += OnClose;
  53. socket.OnError += OnErr;
  54. }
  55. }
  56. private void ReCreateSocket(object sender, CloseEventArgs e) {
  57. socket = new WebSocket(this.host);
  58. socket.OnOpen += OnOpen;
  59. socket.OnMessage += OnMessage;
  60. socket.OnClose += OnClose;
  61. socket.OnError += OnErr;
  62. }
  63. //断线重连逻辑
  64. public IEnumerator ReconectScoektAsync()
  65. {
  66. while (true)
  67. {
  68. yield return new WaitForSeconds(2);
  69. Debug.Log(" client : reconectScoekt");
  70. if (socket.ReadyState == WebSocketState.Connecting || socket.ReadyState == WebSocketState.Open) break;
  71. socket.ConnectAsync();
  72. }
  73. }
  74. //开始心跳逻辑
  75. public IEnumerator StartHeardBeat()
  76. {
  77. isHeardbeat = true;
  78. while (true)
  79. {
  80. Debug.Log("开始发送心跳");
  81. if (isHeardbeat == false) continue;
  82. yield return new WaitForSeconds(2);
  83. //发送心跳
  84. this.sendHeardbeat();
  85. }
  86. }
  87. private async void sendHeardbeat()
  88. {
  89. int u1 = await this.RequestAsync<int, int>("heartbeat", 21);
  90. }
  91. public UniTask<bool> ConnectAsync()
  92. {
  93. socket.ConnectAsync();
  94. return utcs.Task;
  95. }
  96. private void OnOpen(object sender, OpenEventArgs e)
  97. {
  98. if (protocol == null)
  99. protocol = new Protocol();
  100. protocol.SetSocket(socket);
  101. protocol.OnReconected = OnReconected;
  102. protocol.OnError = OnError;
  103. //bool isOK = await protocol.HandsharkAsync(this.token);
  104. Debug.Log("open:" + e);
  105. isConnect = true;
  106. utcs.TrySetResult(true);
  107. OnConnected?.Invoke();
  108. }
  109. private async void OnClose(object sender, CloseEventArgs e)
  110. {
  111. if (socket.ReadyState == UnityWebSocket.WebSocketState.Connecting || socket.ReadyState == UnityWebSocket.WebSocketState.Open) return;
  112. await UniTask.SwitchToMainThread();
  113. isConnect = false;
  114. Cancel();
  115. if (!isForce)
  116. {
  117. await UniTask.Delay(1000);
  118. //socket.Open();
  119. }
  120. OnDisconnect?.Invoke();
  121. }
  122. public void OnErr(object sender, ErrorEventArgs e)
  123. {
  124. utcs.TrySetResult(false);
  125. isConnect = false;
  126. //Debug.LogError(e.Exception.Message);
  127. }
  128. private void OnMessage(object sender, MessageEventArgs e)
  129. {
  130. protocol.OnReceive(e.RawData);
  131. isConnect = true;
  132. }
  133. public void OnNet(uint mid, uint sid, Action<ExternalMessage> cb)
  134. {
  135. uint merge = PackageProtocol.getMergeCmd(mid, sid);
  136. protocol.SetOnNet(merge, cb);
  137. }
  138. public void OnNetEx(string name, Action<ExternalMessage> cb)
  139. {
  140. Proto pb = ProtoMaps.Instance.protos[name] as Proto;
  141. uint merge = PackageProtocol.getMergeCmd(pb.mid, pb.sid);
  142. protocol.SetOnNet(merge, cb);
  143. }
  144. public void Notify<T>(string route, T info = default)
  145. {
  146. //uint rqID = (uint)Interlocked.Increment(ref RqID);
  147. try
  148. {
  149. #if SOCKET_DEBUG
  150. Debug.Log(string.Format("[Notify] -->> [{0}] {1}", route, JsonUtility.ToJson(info)));
  151. #endif
  152. protocol.Notify<T>(route, info);
  153. }
  154. catch (Exception e)
  155. {
  156. Debug.Log(string.Format("[Notify Exception]{0}", e.Message));
  157. throw e;
  158. }
  159. }
  160. public async UniTask<S> RequestAsyncEx<T, S>(uint mid, uint sid, T info = default, string modelName = null)
  161. {
  162. uint cmdMerge = PackageProtocol.getMergeCmd(mid, sid);
  163. uint rqID = (uint)Interlocked.Increment(ref RqID);
  164. try
  165. {
  166. #if SOCKET_DEBUG
  167. Debug.Log(string.Format("[{0}][Request] -->> [{1}] {2}", rqID, route, JsonUtility.ToJson(info)));
  168. #endif
  169. ExternalMessage pack = await protocol.RequestAsync<T>(rqID, cmdMerge, info, modelName);
  170. S msg = PackageProtocol.DecodeInfo<S>(pack.data);
  171. #if SOCKET_DEBUG
  172. Debug.Log(string.Format("[{0}][Request] <<-- [{1}] {2} {3}", rqID, route, JsonUtility.ToJson(msg), JsonUtility.ToJson(msg.info)));
  173. #endif
  174. return msg;
  175. }
  176. catch (Exception e)
  177. {
  178. //Debug.Log(string.Format("[{0}][RequestAsync Exception]{1}", rqID, e.Message));
  179. throw e;
  180. }
  181. }
  182. public async UniTask<S> RequestAsync<T, S>(string name, T info = default, string modelName = null)
  183. {
  184. // #if UNITY_WEBGL && !UNITY_EDITOR //只在WebGl下生效
  185. if (PlayerData.Instance.IsEditorMode) {
  186. S msg = PackageProtocol.DecodeInfo<S>(null);
  187. return msg;
  188. }
  189. //#endif
  190. //Debug.Log($"sendMsg {name}");
  191. Proto pb = ProtoMaps.Instance.Name2Pb(name);
  192. uint cmdMerge = PackageProtocol.getMergeCmd(pb.mid, pb.sid);
  193. uint rqID = (uint)Interlocked.Increment(ref RqID);
  194. //Debug.LogError("调试消息id" + rqID);
  195. try
  196. {
  197. #if SOCKET_DEBUG
  198. Debug.Log(string.Format("[{0}][Request] -->> [{1}] {2}", rqID, route, JsonUtility.ToJson(info)));
  199. #endif
  200. ExternalMessage pack = await protocol.RequestAsync<T>(rqID, cmdMerge, info, modelName);
  201. S msg = PackageProtocol.DecodeInfo<S>(pack.data);
  202. #if SOCKET_DEBUG
  203. Debug.Log(string.Format("[{0}][Request] <<-- [{1}] {2} {3}", rqID, route, JsonUtility.ToJson(msg), JsonUtility.ToJson(msg.info)));
  204. #endif
  205. return msg;
  206. }
  207. catch (Exception e)
  208. {
  209. //Debug.Log(string.Format("[{0}][RequestAsync Exception]{1}", rqID, e.Message));
  210. //Debug.Log("房间网络连接断开.......");
  211. S msg = PackageProtocol.DecodeInfo<S>(null);
  212. return msg;
  213. throw e;
  214. }
  215. }
  216. public void Cancel(bool isForce = false)
  217. {
  218. this.isForce = isForce;
  219. utcs.TrySetCanceled();
  220. if (socket.ReadyState != UnityWebSocket.WebSocketState.Closed)
  221. {
  222. socket.CloseAsync();
  223. }
  224. if (protocol != null)
  225. {
  226. protocol.StopHeartbeat();
  227. protocol.CanceledAllUTcs();
  228. }
  229. }
  230. public UnityWebSocket.WebSocketState getSocketState() {
  231. if (socket != null) {
  232. return socket.ReadyState;
  233. }
  234. return 0;
  235. }
  236. public void Close() {
  237. Debug.Log("UnityWebSocket......" + socket);
  238. Debug.Log("UnityWebSocket状态......"+ socket.ReadyState);
  239. if (socket!=null && socket.ReadyState == UnityWebSocket.WebSocketState.Open) {
  240. socket.CloseAsync();
  241. Debug.Log("强制玩家关闭连接......");
  242. }
  243. }
  244. void OnDestroy()
  245. {
  246. socket.CloseAsync();
  247. }
  248. }
  249. }

10.最终定义网络管理器:NetManager.cs

  1. using Cysharp.Threading.Tasks;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using UnityEngine;
  6. using UnityEngine.Networking;
  7. using UTNET;
  8. public class NetMessage<T> {
  9. public uint mergeid;
  10. delegate void Message(object sender, T msg);
  11. }
  12. public class NetManager : MonoBehaviour {
  13. private NetManager() { }
  14. public static NetManager Instance;
  15. public string token, version;
  16. public Client client;
  17. public bool isConeccet = false;
  18. public string HaiMetaSpaceUrl = "*****";
  19. //192.144.138.221 /game.icewhale.net
  20. Dictionary<string, List<Action<ExternalMessage>>> actions = new Dictionary<string, List<Action<ExternalMessage>>>();
  21. private Coroutine rec;
  22. private void Awake() {
  23. Instance = this;
  24. }
  25. async void Start() {
  26. DontDestroyOnLoad(this);
  27. Screen.sleepTimeout = SleepTimeout.NeverSleep;
  28. pushBtn();
  29. }
  30. //public Client getNewClient() {
  31. // return newClient;
  32. //}
  33. //public void setNewClient(Client vNewClient) {
  34. // newClient = vNewClient;
  35. //}
  36. public void webOpenHaiMetaUrl(string param = null) {
  37. //string url = this.HaiMetaSpaceUrl+param;
  38. //UnityEngine.Application.ExternalEval("window.location.href = \"" + url + "\";");
  39. }
  40. public void webOpenNewSpace(string spaceUrl,string spaceId)
  41. {
  42. string url = spaceUrl + "?param={\"spaceId\":"+ spaceId + ",\"userName\":"+PlayerData.Instance.Name+",\"templateId\":"+ PlayerData.Instance.TemplateId + "}" + "&token=" + PlayerData.Instance.ltk + "&type=4"+ "&state=1";
  43. UnityEngine.Application.ExternalEval("window.location.href = \"" + url + "\";");
  44. }
  45. private void Update() {
  46. //if (client == null && newClient != null) {
  47. // client = getNewClient();
  48. //}
  49. }
  50. public async void CreateConeccetionBtn()
  51. {
  52. //string host = string.Format("wss://*****");
  53. Debug.Log("CreateConeccetionBtn" +Host.gameServer);
  54. client = new Client(Host.gameServer);
  55. client.OnDisconnect = OnDisconnect;
  56. client.OnReconected = OnReconected;
  57. client.OnError = OnError;
  58. client.OnConnected = OnConnected;
  59. bool isConeccet = await client.ConnectAsync();
  60. if (isConeccet)
  61. {
  62. Debug.Log("网络链接成功");
  63. }
  64. }
  65. //public void resetClient() {
  66. // setNewClient(client);
  67. //}
  68. private void OnConnected() {
  69. Debug.Log("OnConnected");
  70. if (rec != null)
  71. StopCoroutine(rec);
  72. this.TriggerEvent(EventName.SocketOpen, null);
  73. }
  74. private void OnError(string msg) {
  75. Debug.LogError(string.Format("err msg:{0}", msg));
  76. }
  77. private void OnReconected() {
  78. Debug.Log("OnReconect");
  79. }
  80. private void OnDisconnect() {
  81. Debug.Log("OnDisconnect");
  82. //client = null;
  83. rec = StartCoroutine(client.ReconectScoektAsync()); //断线重连逻辑
  84. }
  85. public void pushBtn() {
  86. LoadNetCofig();
  87. }
  88. void LoadNetCofig() {
  89. var configPath = Application.dataPath;
  90. #if UNITY_EDITOR
  91. var filepath = Path.Combine(Application.dataPath.Replace("Assets", ""), "config.txt");
  92. #else
  93. var filepath = Path.Combine(Application.dataPath, "config.txt");
  94. #endif
  95. Debug.Log("configPath" + filepath);
  96. filepath = filepath.Replace("\\", "/");
  97. LoadFileSetNetwork(filepath);
  98. }
  99. async void LoadFileSetNetwork(string filepath) {
  100. UnityWebRequest www = UnityWebRequest.Get(filepath);
  101. await www.SendWebRequest();
  102. if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
  103. Debug.LogError(www.error);
  104. }
  105. else {
  106. string json = www.downloadHandler.text;
  107. var data = LitJson.JsonMapper.ToObject(json);
  108. if ((string)data["AssetBundleIP"] != string.Empty) {
  109. Host.AssetBundleIP = (string)data["AssetBundleIP"];
  110. }
  111. #if UNITY_EDITOR
  112. var serverMode = AppConst.serverMode;
  113. #else
  114. var serverMode = (ServerMode)int.Parse(HttpHelper.GetUrlParam("severAPI"));
  115. #endif
  116. AppConst.serverMode = serverMode;
  117. switch (serverMode) {
  118. case ServerMode.preview:
  119. Host.ApiHost = (string)data["preview"];
  120. break;
  121. case ServerMode.dev:
  122. Host.ApiHost = (string)data["dev"];
  123. break;
  124. }
  125. #if !UNITY_EDITOR
  126. var paramUrl = HttpHelper.GetUrlParam("param");
  127. JsonData paramdata = JsonMapper.ToObject(UtilsFunc.UnicodeToString(paramUrl));
  128. try {
  129. string spaceId = paramdata["spaceId"].ToJson();
  130. PlayerData.Instance.SpaceId = spaceId;
  131. PlayerData.Instance.ltk = HttpHelper.GetUrlParam("token");
  132. }
  133. catch (Exception e) {
  134. Debug.LogError(e.Message + '\n' + e.StackTrace);
  135. }
  136. #endif
  137. Debug.Log("LoadFileSetNetwork SpaceId" + PlayerData.Instance.SpaceId);
  138. //如果在编辑器下面,并且不填sapceId,那么则进入发布模式
  139. if (string.IsNullOrEmpty(PlayerData.Instance.SpaceId) == false) {
  140. await HttpHelper.Instance.GetSceneConfig();
  141. }
  142. #if !UNITY_EDITOR
  143. if (paramdata.ContainsKey("templateId")) {
  144. if (paramdata["templateId"] != null) {
  145. string tempStr = (string)paramdata["templateId"];
  146. bool isExist = int.TryParse(tempStr,out var tempId);
  147. if (isExist) PlayerData.Instance.TemplateId = tempId;
  148. }
  149. }
  150. string stateUrl = HttpHelper.GetUrlParam("state");
  151. #else
  152. string stateUrl = string.IsNullOrEmpty(PlayerData.Instance.SpaceId) == true ? AppConst.PublicMode : AppConst.ViewMode;
  153. #endif
  154. var arg = new SceneLoadActionArgs();
  155. arg.state = stateUrl;
  156. EventManager.Instance.TriggerEvent(EventName.LoadSceneAction, arg);
  157. if (stateUrl == AppConst.PublicMode) {
  158. PlayerData.Instance.IsEditorMode = true;
  159. PlayerData.Instance.IsPublicMode = true;
  160. EventManager.Instance.TriggerEvent(EventName.OnPublishEnter);
  161. HttpHelper.Instance.GetDefaultSpaceImg();
  162. return;
  163. }
  164. #if !UNITY_EDITOR
  165. await HttpHelper.Instance.GetServerConfig();
  166. #else
  167. Host.gameServer = (string)data["local"];
  168. #endif
  169. CreateConeccetionBtn();
  170. }
  171. }
  172. private async UniTaskVoid CreateConeccetion() {
  173. Debug.Log("开始...");
  174. bool isConeccet = await client.ConnectAsync();
  175. if (isConeccet) {
  176. Debug.Log("网络链接成功");
  177. // this.Register<RegisterInfo>("test", (int code) =>
  178. // {
  179. // Debug.Log("网络事件" +code);
  180. // });
  181. if (client != null) client.isConnect = true;
  182. //this.SendAPI();
  183. }
  184. else
  185. Debug.Log("多次链接仍让未成功");
  186. }
  187. public void AddSyncHandler(string name, Action<SyncWrapData> call) {
  188. NetManager.Instance.Register<GameFrame>("gameFrame", (ExternalMessage pack) => {
  189. GameFrame info = PackageProtocol.DecodeInfo<GameFrame>(pack.data);
  190. //if (info.location.playerId == PlayerData.Instance.PlayerId) {
  191. // return; //自己不用给自己同步
  192. //}
  193. var opc = info.opc;
  194. SyncWrapData dataBase = null;
  195. try {
  196. dataBase = JsonUtility.FromJson<SyncWrapData>(opc);
  197. if (dataBase.playerId != PlayerData.Instance.PlayerId.ToString()) { //只接受不同playerId的数据
  198. call.Invoke(dataBase);
  199. }
  200. }
  201. catch (Exception e) {
  202. //Debug.LogError(e);
  203. }
  204. });
  205. }
  206. public async void SendSyncData(SyncWrapData syncBase) {
  207. string jsonData = JsonUtility.ToJson(syncBase);
  208. if (NetManager.Instance.client == null) {
  209. Debug.LogError("NetManager.Instance.client == null");
  210. return;
  211. }
  212. var gameFrame = new GameFrame();
  213. gameFrame.opc = jsonData;
  214. await NetManager.Instance.client.RequestAsync<GameFrame, GameFrame>("gameFrame", gameFrame);
  215. }
  216. public async void SendSyncWorldData(SyncWorldData worldData) {
  217. string jsonData = LitJson.JsonMapper.ToJson(worldData);
  218. if (NetManager.Instance.client == null) {
  219. Debug.LogError("NetManager.Instance.client == null");
  220. return;
  221. }
  222. //Debug.Log("SendSyncWorldData worldData:" + jsonData);
  223. var gameFrame = new GameFrame();
  224. gameFrame.world = jsonData;
  225. await NetManager.Instance.client.RequestAsync<GameFrame, GameFrame>("gameFrame", gameFrame);
  226. }
  227. public async void SendFrameLocationData(SyncTransfomData syncPos,SyncWrapData wrap) {
  228. if (NetManager.Instance.client == null) {
  229. Debug.LogError("NetManager.Instance.client == null");
  230. return;
  231. }
  232. var gameFrame = new GameFrame();
  233. gameFrame.opc = JsonUtility.ToJson(wrap);
  234. gameFrame.location = new TankLocation();
  235. SyncTransfomUtil.ToTankLocation(ref gameFrame.location, syncPos);
  236. gameFrame.location.playerId = PlayerData.Instance.PlayerId;
  237. await NetManager.Instance.client.RequestAsync<GameFrame, GameFrame>("gameFrame", gameFrame);
  238. }
  239. public void Register<T>(string name, Action<ExternalMessage> ac) {
  240. //#if UNITY_WEBGL && !UNITY_EDITOR //只在WebGl下生效
  241. if (PlayerData.Instance.IsEditorMode) return;
  242. //#endif
  243. //加入事件列表
  244. Proto pb = ProtoMaps.Instance.Name2Pb(name);
  245. List<Action<ExternalMessage>> list = null;
  246. if (actions.ContainsKey(name)) {
  247. list = actions[name];
  248. }
  249. else {
  250. list = new List<Action<ExternalMessage>>();
  251. actions.Add(name, list);
  252. }
  253. list.Add(ac);
  254. client.OnNetEx(name, (ExternalMessage pack) => {
  255. T info = PackageProtocol.DecodeInfo<T>(pack.data);
  256. //Debug.Log("网络事件" + JsonUtility.ToJson(info));
  257. //遍历事件列表依次回调
  258. foreach (Action<ExternalMessage> cb in list) {
  259. cb?.Invoke(pack);
  260. }
  261. });
  262. }
  263. public async void SendAPI() {
  264. //请求注册
  265. //RegisterInfo register = new RegisterInfo();
  266. //register.account = "abc";
  267. //register.phoneNum = "abc";
  268. //register.pwd = "abc";
  269. //RegisterInfo a = await client.RequestAsync<RegisterInfo, RegisterInfo>("test", register);
  270. //Debug.Log(a.phoneNum);
  271. client.OnNetEx("login", (ExternalMessage pack) => {
  272. Debug.LogError("回调返回");
  273. //T info = PackageProtocol.DecodeInfo<T>(pack.data);
  274. Debug.Log("网络事件" + JsonUtility.ToJson(info));
  275. 遍历事件列表依次回调
  276. //foreach (Action<ExternalMessage> cb in list)
  277. //{
  278. // cb?.Invoke(pack);
  279. //}
  280. });
  281. LoginVerify loginVerify = new LoginVerify();
  282. loginVerify.account = "18060974935";
  283. loginVerify.pwd = "123456ab";
  284. loginVerify.loginBizCode = 1;
  285. UserInfo ret = await NetManager.Instance.client.RequestAsync<LoginVerify, UserInfo>("login", loginVerify);
  286. Debug.Log(ret.nickName);
  287. TankEnterRoom myEnterRoom = new TankEnterRoom();
  288. myEnterRoom.roomId = 1002;
  289. myEnterRoom.team = 1;
  290. TankEnterRoom ret2 = await NetManager.Instance.client.RequestAsync<TankEnterRoom, TankEnterRoom>("enterRoom", myEnterRoom);
  291. Debug.Log(ret2.time);
  292. //int code = await client.RequestAsync<String, int>("gameObjUsed", "ok");
  293. }
  294. public bool isConnected() {
  295. return isConeccet;
  296. }
  297. private void OnDestroy() {
  298. if (client != null) {
  299. client.Cancel();
  300. }
  301. }
  302. }

11.发送网络消息的应用:

UserInfo ret = await NetManager.Instance.client.RequestAsync<LoginVerify, UserInfo>("login", loginVer);

12.监听网络消息:

  1. NetManager.Instance.Register<TankEnterRoom>("enterRoom", (ExternalMessage pack) =>
  2. {
  3. Debug.Log("新玩家进去");
  4. this.onNewRoleEnter2(pack);
  5. });
  1. public void onNewRoleEnter2(ExternalMessage pack) {
  2. TankEnterRoom info = PackageProtocol.DecodeInfo<TankEnterRoom>(pack.data);
  3. List<UserInfo> roleList = info.tankPlayerList;
  4. Debug.Log("新进入房间玩家列表" + roleList.ToString());
  5. long roleId = info.playerId;
  6. Debug.Log("新进入房间玩家id" + roleId);
  7. foreach (UserInfo vRole in roleList)
  8. {
  9. Debug.Log("新进入房间玩家" + JsonUtility.ToJson(vRole));
  10. if (vRole.id == roleId && vRole.id!=PlayerData.Instance.PlayerId)
  11. {
  12. if (!RolesManager.Instance.isExistRoleById(vRole.id)) {
  13. GuestinfoDataModel.Instance.OnNewRoleIntoRoom(vRole);
  14. RolesManager.Instance.synPlayer(vRole, true);
  15. }
  16. }
  17. }
  18. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/107323
推荐阅读
相关标签
  

闽ICP备14008679号