Unity3D打包WebGL并使用MQTT(二):使用json
Unity3D打包WebGL并使用MQTT(二):使用json
1. 软件环境
Unity
:2021.3
stomp.js 2.3.3
:
下载地址
:https://www.jsdelivr.com/package/npm/stompjs
2. 内容介绍
这篇博客的主要内容是记录将一个Unity
项目打包成WebGL
项目,并集成MQTT
进行json
数据传输的过程。
3. 项目搭建
3.1 UI
界面
3.2 添加插件
- 添加
WebGLInput
插件
用于解决
WebGL
中输入框无法输入/显示中文的问题
详情参考:
Unity WebGL 输入框(InputField)接受中文输入
unity在webgl端 输入框无法输入中文和中文显示问题的解决
下载地址: 使用github包【WebGLInput】:
https://github.com/kou-yeung/WebGLInput
2. 添加系统中文字体
将系统中的字体文件导入
Unity
详情参考:Unity3D添加使用系统中的字体
- 修改
InputField
中文显示和字体
- 添加
Pathfinding.JsonFx.dll
用于进行
json
数据的序列化和反序列化
JsonFX Unity3D 如何使用JsonFX
3.3 添加脚本
.jslib文件
详细内容参考:Unity(WebGL)与JS通讯2022最新姿势
mergeInto(LibraryManager.library, {Hello: function () {window.alert("Hello, world!");},HelloString: function (str) {// window.alert(Pointer_stringify(str));window.alert(UTF8ToString(str));},PrintFloatArray: function (array, size) {for(var i = 0; i < size; i++)console.log(HEAPF32[(array >> 2) + i]);},AddNumbers: function (x, y) {return x + y;},StringReturnValueFunction: function () {var returnStr = "bla";var bufferSize = lengthBytesUTF8(returnStr) + 1;var buffer = _malloc(bufferSize);stringToUTF8(returnStr, buffer, bufferSize);return buffer;},BindWebGLTexture: function (texture) {GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);},JsConnect: function (clientId, host, port, username, password, objName, objFunc) {mqttConnect(UTF8ToString(clientId), UTF8ToString(host), UTF8ToString(port), UTF8ToString(username), UTF8ToString(password), UTF8ToString(objName), UTF8ToString(objFunc));},JsSubscribe: function (clientId, name, objName, objFunc) {mqttSubscribe(UTF8ToString(clientId), UTF8ToString(name), UTF8ToString(objName), UTF8ToString(objFunc))},JsSend: function (clientId, name, payload) {mqttSend(UTF8ToString(clientId), UTF8ToString(name), UTF8ToString(payload))},JsUnsubscribe: function(clientId, name) {mqttUnsubscribe(UTF8ToString(clientId), UTF8ToString(name));},JsDisconnect: function(clientId) {mqttDisconnect(UTF8ToString(clientId), UTF8ToString(clientId));}
});
- 给
Cube
添加脚本Cube.cs
用于显示基本函数功能
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;public class Cube : MonoBehaviour
{[DllImport("__Internal")]private static extern void Hello();[DllImport("__Internal")]private static extern void HelloString(string str);[DllImport("__Internal")]private static extern void PrintFloatArray(float[] array, int size);[DllImport("__Internal")]private static extern int AddNumbers(int x, int y);[DllImport("__Internal")]private static extern string StringReturnValueFunction();[DllImport("__Internal")]private static extern void BindWebGLTexture(int texture);[System.Obsolete]void Start() {Hello();HelloString("This is a string.");float[] myArray = new float[10];PrintFloatArray(myArray, myArray.Length);int result = AddNumbers(5, 7);Debug.Log(result);Debug.Log(StringReturnValueFunction());var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false);BindWebGLTexture(texture.GetNativeTextureID());}
}
- 数据类
Result.cs
用于
json
数据的序列化和反序列化
[System.Serializable]
public class Result {public int errCode;public string errInfo;public object data;
}
- 数据类
Mqtt.cs
用于配置
MQTT
相关内容
using System.Collections.Generic;
using System.Runtime.InteropServices;[System.Serializable]
public class Mqtt {public string host;public string port;public string clientId;public string username;public string password;public string objName;public string objFunc;public List<Result> resultList;[DllImport("__Internal")]private static extern void JsConnect(string clientId, string host, string port, string username, string password, string objName, string objFunc);[DllImport("__Internal")]private static extern void JsSubscribe(string clientId, string topic, string objName, string objFunc);[DllImport("__Internal")]private static extern void JsSend(string clientId, string topic, string payload);[DllImport("__Internal")]private static extern void JsUnsubscribe(string clientId, string topic);[DllImport("__Internal")]private static extern void JsDisconnect(string clientId);public void Connect() {JsConnect(clientId, host, port, username, password, objName, objFunc);}public void SubscribeTopic(string topic) {topic = "/topic/" + topic;JsSubscribe(clientId, topic, objName, objFunc);}public void UnscbscribeTopic(string topic) {topic = "/topic/" + topic;JsUnsubscribe(clientId, topic);}public void SendTopic(string topic, string payload) {topic = "/topic/" + topic;JsSend(clientId, topic, payload);}public void SubscriveQueue(string queue) {queue = "/queue/" + queue;JsSubscribe(clientId, queue, objName, objFunc);}public void UnsubscribeQueue(string queue) {queue = "/queue/" + queue;JsUnsubscribe(clientId, queue);}public void SendQueue(string queue, string payload) {queue = "/queue/" + queue;JsSend(clientId, queue, payload);}public void Disconnect() {JsDisconnect(clientId);}
}
- 给
Canvas
添加脚本PanelController_2.cs
用于测试
mqtt
相关函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using Newtonsoft.Json;public class PanelController_2 : MonoBehaviour
{public Button connectBtn;public Button subscribeBtn;public Button sendBtn;public Button unsubscribeBtn;public Button disconnectBtn;private InputField hostInput;private InputField portInput;private InputField clientIdInput;private InputField usernameInput;private InputField passwordInput;private InputField destinationInput;private InputField topicInput;private InputField messageInput;private Text scrollLogText;private Mqtt mqtt;// Start is called before the first frame updatevoid Start(){connectBtn.onClick.AddListener(HandleConnect);subscribeBtn.onClick.AddListener(HandleSubscribe);sendBtn.onClick.AddListener(HandleSend);unsubscribeBtn.onClick.AddListener(HandleUnsubscribe);disconnectBtn.onClick.AddListener(HandleDisconnect);foreach (UnityEngine.UI.InputField textInput in GetComponentsInChildren<UnityEngine.UI.InputField>()) {// Debug.Log(textInput.name);switch (textInput.name) {case "host_input": {hostInput = textInput;break;}case "port_input": {portInput = textInput;break;}case "client_id_input": {clientIdInput = textInput;break;}case "username_input": {usernameInput = textInput;break;}case "password_input": {passwordInput = textInput;break;}case "destination_input": {destinationInput = textInput;break;}case "topic_input": {topicInput = textInput;break;}case "message_input": {messageInput = textInput;break;}}}foreach (Text textItem in GetComponentsInChildren<Text>()) {switch (textItem.name) {case "scroll_log_text": {scrollLogText = textItem;break;}}}mqtt = new Mqtt();}void HandleConnect() {Debug.Log("unity: connect");mqtt.host = hostInput.text;mqtt.port = portInput.text;mqtt.clientId = clientIdInput.text;mqtt.username = usernameInput.text;mqtt.password = passwordInput.text;mqtt.resultList = new List<Result>();mqtt.objName = name;mqtt.objFunc = "HandleMqttMessage";mqtt.Connect();}void HandleSubscribe() {Debug.Log("unity: subscribe");string topic = topicInput.text;mqtt.SubscribeTopic(topic);}void HandleSend() {Debug.Log("unity: send");string topic = topicInput.text;string payload = messageInput.text;mqtt.SendTopic(topic, payload);}void HandleUnsubscribe() {Debug.Log("unity: unsubscribe");string topic = topicInput.text;mqtt.UnscbscribeTopic(topic);}void HandleDisconnect() {Debug.Log("unity: disconnect");mqtt.Disconnect();}void HandleMqttMessage(string message) {Debug.Log("unity: get message");SetLogScroll(message);Result result = JsonConvert.DeserializeObject<Result>(message);mqtt.resultList.Add(result);}void SetLogScroll(string log) {scrollLogText.text += "\\n" + log;}
}
3.4 构建WebGL
- 选择平台
- 配置
- 分辨率设置
- image设置
- 其他设置
- 发布设置
- 构建
3.5 集成MQTT
功能
3.5.1 版本一: 单文件实现
- 在
index.html
中实现
<!DOCTYPE html>
<html lang="en-us"><head><meta charset="utf-8"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Unity WebGL Player | Web Demo</title><link rel="shortcut icon" href="TemplateData/favicon.ico"><link rel="stylesheet" href="TemplateData/style.css"></head><body><div id="unity-container" class="unity-desktop"><canvas id="unity-canvas" width=960 height=600></canvas><div id="unity-loading-bar"><div id="unity-logo"></div><div id="unity-progress-bar-empty"><div id="unity-progress-bar-full"></div></div></div><div id="unity-warning"> </div><div id="unity-footer"><div id="unity-webgl-logo"></div><div id="unity-fullscreen-button"></div><div id="unity-build-title">Web Demo</div></div></div><!-- 引入stomp.min.js --><script src="Plugins/stomp.min.js"></script><script>var mqttClient = {}var subscribeIdObj = {}function mqttConnect(clientId, host, port, username, password, objName, objFunc) {// clientId不能重复if (checkClientIdExists(clientId)) {console.log('html: clientId重复, 不能连接');alert('clientId重复, 不能连接')return}let url = 'ws://' + host + ':' + port + '/stomp'console.log("html: connect " + url);// 创建一个client实例mqttClient[clientId] = {host: host,port: port,username: username,password: password,objName: objName,objFunc: objFunc,client: null,subscribe: {topic: {},queue: {}}}mqttClient[clientId]['client'] = Stomp.client(url)console.log(mqttClient)let headers = {login: username,passcode: password,'client-id': clientId}mqttClient[clientId]['client'].connect(headers, () => {console.log('connect success');sendMessage(clientId, {errCode: 0,errInfo: 'connect success'})})}// 检查clientId 是否已存在function checkClientIdExists(clientId) {if (clientId in mqttClient) {return true} else {return false}}// 检查订阅类型是topic还是queuefunction checkMessageType(name) {// 检查订阅类型是topic还是queueif (name.search(/^\\/topic\\/.*/gm) >= 0) {// topicreturn 1} else if (name.search(/^\\/queue\\/.*/gm) >= 0) {// queuereturn 0} else {// stomp默认是queuereturn -1}}// 订阅消息function mqttSubscribe(clientId, name, objName, objFunc) {if (!checkClientIdExists(clientId)) {alert('clientId 不存在, 无法订阅')return}let messageType = checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');alert('消息类型不符合要求, /topic/* 或者 /queue/*')return}console.log("html: subscribe " + name);sendMessage(clientId, {errCode: 0,errInfo: "html: subscribe " + name})// 订阅let subscribeId = mqttClient[clientId]['client'].subscribe(name, message => {if (message.body) {console.log('message body: ' + message.body)// 将接收到的消息发送给unity对象sendMessage(clientId, {errCode: 0,errInfo: 'message body: ' + message.body})} else {console.log('empty message')sendMessage(clientId, {errCode: 0,errInfo: 'empty message'})}})// 保存if (messageType === 1) {mqttClient[clientId]['subscribe']['topic'][name] = subscribeId} else if (messageType === 0) {mqttClient[clientId]['subscribe']['queue'][name] = subscribeId}}// 发送消息function mqttSend(clientId, name, payload) {if (!checkClientIdExists(clientId)) {alert('clientId 不存在, 无法发送')return}let messageType = checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');alert('消息类型不符合要求, /topic/* 或者 /queue/*')return}console.log("html: send " + name + ", " + payload);sendMessage(clientId, {errCode: 0,errInfo: "html: send " + name + ", " + payload})let headers = {}mqttClient[clientId]['client'].send(name, headers, payload)}// 取消订阅function mqttUnsubscribe(clientId, name) {if (!checkClientIdExists(clientId)) {alert('clientId 不存在, 无法取消订阅')return}let messageType = checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');alert('消息类型不符合要求, /topic/* 或者 /queue/*')return}if (messageType === 1) {// topicif (name in mqttClient[clientId]['subscribe']['topic']) {mqttClient[clientId]['subscribe']['topic'][name].unsubscribe();} else {alert(`未订阅此消息 ${name}`)}} else if (messageType === 0) {// queueif (name in mqttClient[clientId]['subscribe']['queue']) {mqttClient[clientId]['subscribe']['queue'][name].unsubscribe();} else {alert(`未订阅此消息 ${name}`)}}console.log("html: unsubscribe " + name);sendMessage(clientId, {errCode: 0,errInfo: "html: unsubscribe " + name})}// 断开连接function mqttDisconnect(clientId) {if (!checkClientIdExists(clientId)) {alert('clientId 不存在')return}mqttClient[clientId]['client'].disconnect(() => {console.log("html: disconnect " + clientId);// unityInstance.SendMessage('Canvas', 'SetLogScroll', 'html: disconnect ' + clientId)sendMessage(clientId, {errCode: 0,errInfo: 'html: disconnect ' + clientId})// 删除clientIddelete mqttClient[clientId]})}// 发送消息function sendMessage(clientId, data) {unityInstance.SendMessage(mqttClient[clientId]['objName'], mqttClient[clientId]['objFunc'], JSON.stringify(data))}var container = document.querySelector("#unity-container");var canvas = document.querySelector("#unity-canvas");var loadingBar = document.querySelector("#unity-loading-bar");var progressBarFull = document.querySelector("#unity-progress-bar-full");var fullscreenButton = document.querySelector("#unity-fullscreen-button");var warningBanner = document.querySelector("#unity-warning");// Shows a temporary message banner/ribbon for a few seconds, or// a permanent error message on top of the canvas if type=='error'.// If type=='warning', a yellow highlight color is used.// Modify or remove this function to customize the visually presented// way that non-critical warnings and error messages are presented to the// user.function unityShowBanner(msg, type) {function updateBannerVisibility() {warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';}var div = document.createElement('div');div.innerHTML = msg;warningBanner.appendChild(div);if (type == 'error') div.style = 'background: red; padding: 10px;';else {if (type == 'warning') div.style = 'background: yellow; padding: 10px;';setTimeout(function() {warningBanner.removeChild(div);updateBannerVisibility();}, 5000);}updateBannerVisibility();}var buildUrl = "Build";var loaderUrl = buildUrl + "/Web2.loader.js";var config = {dataUrl: buildUrl + "/Web2.data",frameworkUrl: buildUrl + "/Web2.framework.js",codeUrl: buildUrl + "/Web2.wasm",streamingAssetsUrl: "StreamingAssets",companyName: "DefaultCompany",productName: "Web Demo",productVersion: "0.1",showBanner: unityShowBanner,};// By default Unity keeps WebGL canvas render target size matched with// the DOM size of the canvas element (scaled by window.devicePixelRatio)// Set this to false if you want to decouple this synchronization from// happening inside the engine, and you would instead like to size up// the canvas DOM size and WebGL render target sizes yourself.// config.matchWebGLToCanvasSize = false;if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {// Mobile device style: fill the whole browser client area with the game canvas:var meta = document.createElement('meta');meta.name = 'viewport';meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';document.getElementsByTagName('head')[0].appendChild(meta);container.className = "unity-mobile";canvas.className = "unity-mobile";// To lower canvas resolution on mobile devices to gain some// performance, uncomment the following line:// config.devicePixelRatio = 1;unityShowBanner('WebGL builds are not supported on mobile devices.');} else {// Desktop style: Render the game canvas in a window that can be maximized to fullscreen:canvas.style.width = "960px";canvas.style.height = "600px";}loadingBar.style.display = "block";var script = document.createElement("script");script.src = loaderUrl;script.onload = () => {createUnityInstance(canvas, config, (progress) => {progressBarFull.style.width = 100 * progress + "%";}).then((unityInstance) => {loadingBar.style.display = "none";window.unityInstance = unityInstancefullscreenButton.onclick = () => {unityInstance.SetFullscreen(1);};}).catch((message) => {alert(message);});};document.body.appendChild(script);</script></body>
</html>
3.5.2 版本二: 多文件实现
- 添加
iceMqtt.js
文件
抽象
MQTT
功能
import './stomp.min.js'
var iceMqtt = {mqttClient: {},unityInstance: null,// 创建一个对象mqttCreateClient: function(clientId, host, port, username, password, objName, objFunc) {// clientId不能重复if (this.checkClientIdExists(clientId)) {console.log(`clientId重复, 不能创建 ${clientId}`);return}// 创建一个client实例this.mqttClient[clientId] = {host: host,port: port,username: username,password: password,client: null,subscribe: {topic: {},queue: {}},objName: objName,objFunc: objFunc}console.log('iceMqtt.js : ', this.mqttClient)},// 进行连接mqttConnect: function(clientId) {// clientId需要存在if (!this.checkClientIdExists(clientId)) {console.log(`clientId不存在, 不能连接 ${clientId}, 请创建client实例`);return}let url = 'ws://' + this.mqttClient[clientId]['host'] + ':' + this.mqttClient[clientId]['port'] + '/stomp'console.log(`connect url is ${url}`);this.mqttClient[clientId]['client'] = Stomp.client(url)let headers = {login: this.mqttClient[clientId]['username'],passcode: this.mqttClient[clientId]['password'],'client-id': clientId}this.mqttClient[clientId]['client'].connect(headers, () => {console.log('connect success');this.sendMessage(clientId, {errCode: 0,errInfo: `${clientId} connect success`})})},// 检查clientId 是否已存在checkClientIdExists: function(clientId) {if (clientId in this.mqttClient) {return true} else {return false}},// 检查订阅类型是topic还是queuecheckMessageType: function(name) {// 检查订阅类型是topic还是queueif (name.search(/^\\/topic\\/.*/gm) >= 0) {// topicreturn 1} else if (name.search(/^\\/queue\\/.*/gm) >= 0) {// queuereturn 0} else {// stomp默认是queuereturn -1}},// 订阅消息mqttSubscribe: function(clientId, name, messageCallback) {if (!this.checkClientIdExists(clientId)) {console.log(`clientId 不存在, 没有连接服务器, 请连接`)return}let messageType = this.checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');return}// 订阅let subscribeId = this.mqttClient[clientId]['client'].subscribe(name, messageCallback)// 保存if (messageType === 1) {this.mqttClient[clientId]['subscribe']['topic'][name] = subscribeId} else if (messageType === 0) {this.mqttClient[clientId]['subscribe']['queue'][name] = subscribeId}console.log(`${clientId} 订阅了 ${name}`)this.sendMessage(clientId, {errCode: 0,errInfo: `${clientId} 订阅了 ${name}`})},// 发送消息mqttSend: function(clientId, name, payload) {if (!this.checkClientIdExists(clientId)) {console.log('clientId 不存在, 无法发送')return}let messageType = this.checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');return}let headers = {}this.mqttClient[clientId]['client'].send(name, headers, payload)console.log(`${clientId} 向 ${name} 发送了 ${payload}`)this.sendMessage(clientId, {errCode: 0,errInfo: `${clientId} 向 ${name} 发送了 ${payload}`})},// 取消订阅mqttUnsubscribe: function(clientId, name) {if (!this.checkClientIdExists(clientId)) {console.log(`clientId 不存在, 无法取消订阅 ${name}`)return}let messageType = this.checkMessageType(name)if (messageType < 0) {console.log('消息类型不符合要求, /topic/* 或者 /queue/*');return}if (messageType === 1) {// topicif (name in this.mqttClient[clientId]['subscribe']['topic']) {this.mqttClient[clientId]['subscribe']['topic'][name].unsubscribe();} else {console.log(`未订阅此消息 ${name}`)}} else if (messageType === 0) {// queueif (name in this.mqttClient[clientId]['subscribe']['queue']) {this.mqttClient[clientId]['subscribe']['queue'][name].unsubscribe();} else {console.log(`未订阅此消息 ${name}`)}}console.log(`${clientId} 取消订阅 ${name}`)this.sendMessage(clientId, {errCode: 0,errInfo: `${clientId} 取消订阅 ${name}`})},// 断开连接mqttDisconnect: function(clientId) {if (!this.checkClientIdExists(clientId)) {console.log('clientId 不存在')return}this.mqttClient[clientId]['client'].disconnect(() => {console.log(`${clientId} 断开连接`);this.sendMessage(clientId, {errCode: 0,errInfo: `${clientId} 断开连接`})// 删除clientIddelete this.mqttClient[clientId]})},// 执行unity默认对象的默认方法sendMessage: function(clientId, data) {this.unityInstance.SendMessage(this.mqttClient[clientId]['objName'], this.mqttClient[clientId]['objFunc'], JSON.stringify(data))}
}export { iceMqtt }
index.html
文件
测试
MQTT
功能
在html
文件引入其他js
文件的格式,
具体参考: webGl使用jsLib与Js交互
<!DOCTYPE html>
<html lang="en-us"><head><meta charset="utf-8"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Unity WebGL Player | Web Demo</title><link rel="shortcut icon" href="TemplateData/favicon.ico"><link rel="stylesheet" href="TemplateData/style.css"></head><body><div id="unity-container" class="unity-desktop"><canvas id="unity-canvas" width=960 height=600></canvas><div id="unity-loading-bar"><div id="unity-logo"></div><div id="unity-progress-bar-empty"><div id="unity-progress-bar-full"></div></div></div><div id="unity-warning"> </div><div id="unity-footer"><div id="unity-webgl-logo"></div><div id="unity-fullscreen-button"></div><div id="unity-build-title">Web Demo</div></div></div><script>var container = document.querySelector("#unity-container");var canvas = document.querySelector("#unity-canvas");var loadingBar = document.querySelector("#unity-loading-bar");var progressBarFull = document.querySelector("#unity-progress-bar-full");var fullscreenButton = document.querySelector("#unity-fullscreen-button");var warningBanner = document.querySelector("#unity-warning");// Shows a temporary message banner/ribbon for a few seconds, or// a permanent error message on top of the canvas if type=='error'.// If type=='warning', a yellow highlight color is used.// Modify or remove this function to customize the visually presented// way that non-critical warnings and error messages are presented to the// user.function unityShowBanner(msg, type) {function updateBannerVisibility() {warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';}var div = document.createElement('div');div.innerHTML = msg;warningBanner.appendChild(div);if (type == 'error') div.style = 'background: red; padding: 10px;';else {if (type == 'warning') div.style = 'background: yellow; padding: 10px;';setTimeout(function() {warningBanner.removeChild(div);updateBannerVisibility();}, 5000);}updateBannerVisibility();}var buildUrl = "Build";var loaderUrl = buildUrl + "/Web2.loader.js";var config = {dataUrl: buildUrl + "/Web2.data",frameworkUrl: buildUrl + "/Web2.framework.js",codeUrl: buildUrl + "/Web2.wasm",streamingAssetsUrl: "StreamingAssets",companyName: "DefaultCompany",productName: "Web Demo",productVersion: "0.1",showBanner: unityShowBanner,};// By default Unity keeps WebGL canvas render target size matched with// the DOM size of the canvas element (scaled by window.devicePixelRatio)// Set this to false if you want to decouple this synchronization from// happening inside the engine, and you would instead like to size up// the canvas DOM size and WebGL render target sizes yourself.// config.matchWebGLToCanvasSize = false;if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {// Mobile device style: fill the whole browser client area with the game canvas:var meta = document.createElement('meta');meta.name = 'viewport';meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';document.getElementsByTagName('head')[0].appendChild(meta);container.className = "unity-mobile";canvas.className = "unity-mobile";// To lower canvas resolution on mobile devices to gain some// performance, uncomment the following line:// config.devicePixelRatio = 1;unityShowBanner('WebGL builds are not supported on mobile devices.');} else {// Desktop style: Render the game canvas in a window that can be maximized to fullscreen:canvas.style.width = "960px";canvas.style.height = "600px";}loadingBar.style.display = "block";var script = document.createElement("script");script.src = loaderUrl;script.onload = () => {createUnityInstance(canvas, config, (progress) => {progressBarFull.style.width = 100 * progress + "%";}).then((unityInstance) => {loadingBar.style.display = "none";// 挂载unityInstance对象window.unityInstance = unityInstanceiceMqtt.unityInstance = unityInstanceconsole.log("unity load", window.iceMqtt)console.log('iceMqtt : ', iceMqtt)fullscreenButton.onclick = () => {unityInstance.SetFullscreen(1);};}).catch((message) => {alert(message);});};document.body.appendChild(script);</script><script type="module">// 先执行import { iceMqtt } from './Plugins/iceMqtt.js'window.onload = () => {window.iceMqtt = iceMqttconsole.log("module iceMqtt", window.iceMqtt)}// window.iceMqtt = iceMqtt</script><script>// 连接function mqttConnect(clientId, host, port, username, password, objName, objFunc) {// 创建一个mqttClienticeMqtt.mqttCreateClient(clientId, host, port, username, password, objName, objFunc)// 检查clientIdif (!iceMqtt.checkClientIdExists(clientId)) {console.log(`clientId ${clientId} 创建失败`)return}console.log('iceMqtt mqttClient: ', iceMqtt.mqttClient)// 进行连接, 创建一个client实例iceMqtt.mqttConnect(clientId)}// 订阅消息function mqttSubscribe(clientId, name, objName, objFunc) {iceMqtt.mqttSubscribe(clientId, name, message => {if (message.body) {console.log(`get message : ${message.body}`)unityInstance.SendMessage(objName, objFunc, JSON.stringify({errCode: 0,errInfo: `get message : ${message.body}`}))} else {console.log(`get empty message ...`)unityInstance.SendMessage(objName, objFunc, JSON.stringify({errCode: 0,errInfo: `get empty message ...`}))}})}// 发送消息function mqttSend(clientId, name, payload) {iceMqtt.mqttSend(clientId, name, payload)}// 取消订阅function mqttUnsubscribe(clientId, name) {iceMqtt.mqttUnsubscribe(clientId, name)}// 断开连接function mqttDisconnect(clientId) {iceMqtt.mqttDisconnect(clientId)}</script></body>
</html>
4. 测试
4.1 版本一:
-
连接
-
订阅
-
发送消息
-
取消订阅
-
断开连接
4.2 版本二:
-
连接
-
订阅
-
发送消息
-
取消订阅
-
断开连接
5. 问题
- 使用
<script type="module"></script>
后,.jslib
文件无法发现内部的函数
解决办法:
参考:
不同js的加载顺序
js文件模块化引用问题(JavaScript modules)
考虑将module
中的内容挂载到window
......<script type="module">// 先执行import { iceMqtt } from './Plugins/iceMqtt.js'window.onload = () => {window.iceMqtt = iceMqttconsole.log("module iceMqtt", window.iceMqtt)}// window.iceMqtt = iceMqtt</script>......
X. 参考
-
查找物体和组件
Unity 之 查找游戏物体的几种方式解析
Unity 常用API之Component,GameObject获取组件 -
Unity与Js互相调用
Unity WebGL C#调用JS脚本
unity开发webGL,引用js功能。
Unity(WebGL)与JS通讯2022最新姿势
webGl使用jsLib与Js交互 -
Unity在WebGL中InputField无法输入中文
Unity WebGL 输入框(InputField)接受中文输入
unity在webgl端 输入框无法输入中文和中文显示问题的解决
Unity3D添加使用系统中的字体 -
unityInstance is not defined
[Unity转小游戏]微信开发者工具/微信小游戏中找不到unityInstance.(unityInstance is not defined) -
其他
2021-09-29 Unity WebGL平台开发遇到的坑 -
Unity构建WebGL
Unity-WebGL-打包流程以及遇到的各种坑
unity打包webgl 部署到本地Web服务器
【Unity】打包WebGL项目遇到的问题及解决记录 -
Unity使用JsonFx
JsonFX Unity3D 如何使用JsonFX -
Unity WebGL常见错误
unity webgl踩坑指南 -
This value was evaluated upon firstexpanding. It may have changed since then…
This value was evaluated upon firstexpanding. It may have changed since then… -
JS export
JS 之export、export default和module.exports -
scritp 使用type=“module”
在index.html中直接调用import,export需要注意的事项
js文件模块化引用问题(JavaScript modules)