用Unity同时开发【微信小游戏】【安卓】【IOS】游
家电修理 2023-07-16 19:17www.caominkang.com电器维修
【系列文章目录】
文章目录
- 【系列文章目录】
- 前言
- 一、导入UnityWebSocket插件
- 二、在TS中使用
前言
本篇来实现WebSocket通信
一、导入UnityWebSocket插件
要在Unity中使用WebSocket我查看了官方文档
我一直觉得Unity是一个把所有东西都为开发者准备好的引擎
这次我错了,它摆烂了,Unity并没有为我们提供WebScoket的内容
所以只好使用插件了,这里我使用的是UnityWebSocket
网上也有很多教程用的是BestHttp
我也心动过,它好贵,坐等打折好了
言归正传,我们先在UnityWebSocket的Release页面下载插件
然后将它导入到我们的项目中
这个插件提供的Demo来供我们参考
这个插件的使用是在C#中的,我们需要封装一层来让它能被TS使用
这里我定义了一个WebSocketClient
public class WebSocketClient { private string connectAddress; protected IWebSocket _socket; public ActionJSOnOpen; public Action JSOnMessage; public Action JSOnClose; public Action JSOnError; public ushort State { get { if (_socket == null) { return 0; } else { return (ushort)(_socket.ReadyState + 1); } } } //连接 public void Connect(string address) { connectAddress = address; if (_socket == null) { _socket = ne WebSocket(address); _socket.OnOpen += Socket_OnOpen; _socket.OnMessage += Socket_OnMessage; _socket.OnClose += Socket_OnClose; _socket.OnError += Socket_OnError; _socket.ConnectAsync(); } } //发送string public void SendStr(string str) { try { _socket.SendAsync(str); } catch (Exception e) { Debug.LogError(e); } } //发送byte public void SendByte(string data) { try { var bytes = System.Text.Encoding.UTF8.GetBytes(data); _socket.SendAsync(bytes); } catch (Exception e) { Debug.LogError(e); } } //关闭 public void Close() { _socket.CloseAsync(); } private void Socket_OnOpen(object sender, OpenEventArgs e) { JSOnOpen?.Invoke(connectAddress); } private void Socket_OnMessage(object sender, MessageEventArgs e) { try { if (e.IsBinary) { JSOnMessage?.Invoke(e.Data); //Debug.Log("WebSocket:" + string.Format("Receive Bytes ({1}): {0}", e.Data, e.RaData.Length)); } else if (e.IsText) { JSOnMessage?.Invoke(e.Data); //Debug.Log("WebSocket:" + string.Format("Receive: {0}", e.Data)); } } catch (Exception err) { Debug.LogError(err); } } private void Socket_OnClose(object sender, CloseEventArgs e) { JSOnClose?.Invoke(e.StatusCode, e.Reason); //Debug.Log("WebSocket:" + string.Format("Closed: StatusCode: {0}, Reason: {1}", e.StatusCode, e.Reason)); } private void Socket_OnError(object sender, ErrorEventArgs e) { JSOnError?.Invoke(e.Message); //Debug.Log("WebSocket:" + string.Format("Error: {0}", e.Message)); } }
需要注意的是,我们需要声明使用的Action类型,才能正常使用
_jsEnv.UsingAction(); _jsEnv.UsingAction ();
别忘了为它生成一下胶水代码
接下来我们来在TS中继续工作
import { UnityWebSocket, WebSocketClient } from "csharp"; import { TSLog } from "../../CustomLog/TSLog"; import { IBaseMessageData, SocketMessageType, WebSocketState } from "../NetDefine"; //C#中我增加了一个Null类型 export enum WebSocketState { Null = 0, Connecting = 1, Open = 2, Closing = 3, Closed = 4 } export interface IWebSocket { Connect(address: string): void; Send(data: IBaseMessageData, droppable?: boolean): void; Close(): void; ListenMessage(state: SocketMessageType, fun: Function): void; RemoveListen(state: SocketMessageType, fun: Function): void; } export class JSWebSocket extends WebSocketClient implements IWebSocket { private _aitSendCash: Array= ne Array (); private _messageHandler: Map > = ne Map >(); constructor() { super(); this.JSOnOpen = this.Socket_OnOpen.bind(this); this.JSOnMessage = this.Socket_OnMessage.bind(this); this.JSOnClose = this.Socket_OnClose.bind(this); this.JSOnError = this.Socket_OnError.bind(this); } RemoveListen(state: SocketMessageType, fun: Function): void { if (this._messageHandler.has(state)) { let array = this._messageHandler.get(state); let neArray = ne Array (); array.forEach(v => { if (v != fun) { neArray.push(v); } }); this._messageHandler.set(state, neArray); array.length = 0; array = null; } } ListenMessage(state: SocketMessageType, fun: Function): void { if (!this._messageHandler.has(state)) { this._messageHandler.set(state, ne Array ()); } this._messageHandler.get(state).push(fun); } public Send(data: IBaseMessageData, droppable: boolean = true): void { let jstr = JSON.stringify(data); TSLog.Log("stringify:" + jstr) //判断连接 if (this.State != WebSocketState.Open) { //未连接且非可抛弃数据加入待发送池 if (!droppable) { this._aitSendCash.push(jstr); } } else { //已连接直接发送 this.SendByte(jstr); } } private Socket_OnOpen(address: string) { TSLog.Log("OnConnect---->" + address); if (this._aitSendCash.length > 0) { TSLog.Log("sendcash") this._aitSendCash.forEach(jstr => { this.SendByte(jstr); }); } this._aitSendCash.length = 0; } private Socket_OnMessage(jstr: string) { TSLog.Log("OnMessage---->" + jstr); if (jstr == "echo.ebsocket.events sponsored by Lob.") return; let jsdata: IBaseMessageData = JSON.parse(jstr) as IBaseMessageData; //解析Json根据类型分发Action if (this._messageHandler.has(jsdata.type)) { let handlers = this._messageHandler.get(jsdata.type); for (let i = 0; i < handlers.length; i++) { if (handlers[i] != null) { try { handlers[i](jsdata); } catch (e) { TSLog.Error(e); } } } } } private Socket_OnClose(errCode: UnityWebSocket.CloseStatusCode, reason: string) { TSLog.Log("OnClose---->" + reason); } private Socket_OnError(message: string) { TSLog.Log("Connect---->" + message); } }
这样我们在TS中就可以使用WebSocket了
这里我定义了一个全局的mainSocket
export const mainSocket:IWebSocket = ne JSWebSocket();
以及一些配置和数据接口
export let mainSocketAddress: string = "ss://echo.ebsocket.events"; export let httpAddress: string = ""; export interface IBaseMessageData { type: SocketMessageType; } export enum SocketMessageType { Null = 0, Test = 1 } export enum WebSocketState { Null = 0, Connecting = 1, Open = 2, Closing = 3, Closed = 4 }
在游戏中我们会有很多个功能使用到Socket
我不想在Socket中去为每个功能写处理
而是在每个功能的Hanlder中去处理
这里我写了一个TestHanlder来测试
export interface Req_Test_MessageData extends IBaseMessageData { data: { str: number, str2: number } } export interface Resp_Test_MessageData extends IBaseMessageData { data: { str: number, str2: number } } export interface ITestHandler{ Connect(): ITestHandler; ReqTest(n1: number, n2: number): ITestHandler; Close(time: number): ITestHandler; } export class TestHanler extends Singletonimplements ITestHandler { constructor() { super(); mainSocket.ListenMessage(SocketMessageType.Test, this.OnRespTest.bind(this)) } public OnRespTest(resp: Resp_Test_MessageData): void { TSLog.Log(resp.data.str) TSLog.Log(resp.data.str2) } public ReqTest(n1: number, n2: number): ITestHandler { let req: Req_Test_MessageData = { type: SocketMessageType.Test, data: { str: n1, str2: n2 } } mainSocket.Send(req, false); return this; } public Connect(): ITestHandler { mainSocket.Connect(mainSocketAddress); return this; } public Close(time: number = 5000): ITestHandler { setTimeout(() => { mainSocket.Close(); }, time) return this; } }
然后我们就可以调用了
ne TestHandler() .Connect() //连接服务器 .ReqTest(5, 1) //请求数据 .Close(5000); //关闭连接
嗯,挺简洁的,测试了也没有什么问题
具体内容还需要与服务端联调,目前以及实现了功能
空调维修
- 温岭冰箱全国统一服务热线-全国统一人工【7X2
- 荆州速热热水器维修(荆州热水器维修)
- 昆山热水器故障码5ER-昆山热水器故障码26
- 温岭洗衣机24小时服务电话—(7X24小时)登记报
- 统帅热水器售后维修服务电话—— (7X24小时)登
- 阳江中央空调统一电话热线-阳江空调官方售后电
- 乌鲁木齐阳春燃气灶厂家服务热线
- 珠海许昌集成灶售后服务电话-全国统一人工【
- 乌鲁木齐中央空调维修服务专线-乌鲁木齐中央空
- 新沂热水器故障电话码维修-新沂热水器常见故障
- 诸城壁挂炉24小时服务热线电话
- 靖江空调24小时服务电话-——售后维修中心电话
- 空调室外滴水管维修(空调室外排水管维修)
- 九江壁挂炉400全国服务电话-(7X24小时)登记报修
- 热水器故障码f.22怎么解决-热水器f0故障解决方法
- 营口热水器售后维修服务电话—— 全国统一人工