Unity
: 2021.3
stomp.js 2.3.3
:下载地址
:https://www.jsdelivr.com/package/npm/stompjs
这篇博客的主要内容是记录将一个Unity
项目打包成WebGL
项目,并集成MQTT
进行json
数据传输的过程。
UI
界面
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
.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 update
void 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;
}
}
WebGL
MQTT
功能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 Demotitle>
<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 Demodiv>
div>
div>
<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还是queue
function checkMessageType(name) {
// 检查订阅类型是topic还是queue
if (name.search(/^\/topic\/.*/gm) >= 0) {
// topic
return 1
} else if (name.search(/^\/queue\/.*/gm) >= 0) {
// queue
return 0
} else {
// stomp默认是queue
return -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) {
// topic
if (name in mqttClient[clientId]['subscribe']['topic']) {
mqttClient[clientId]['subscribe']['topic'][name].unsubscribe();
} else {
alert(`未订阅此消息 ${name}`)
}
} else if (messageType === 0) {
// queue
if (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
})
// 删除clientId
delete 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 = unityInstance
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
script>
body>
html>
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还是queue
checkMessageType: function(name) {
// 检查订阅类型是topic还是queue
if (name.search(/^\/topic\/.*/gm) >= 0) {
// topic
return 1
} else if (name.search(/^\/queue\/.*/gm) >= 0) {
// queue
return 0
} else {
// stomp默认是queue
return -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) {
// topic
if (name in this.mqttClient[clientId]['subscribe']['topic']) {
this.mqttClient[clientId]['subscribe']['topic'][name].unsubscribe();
} else {
console.log(`未订阅此消息 ${name}`)
}
} else if (messageType === 0) {
// queue
if (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} 断开连接`
})
// 删除clientId
delete 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 Demotitle>
<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 Demodiv>
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 = unityInstance
iceMqtt.unityInstance = unityInstance
console.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 = iceMqtt
console.log("module iceMqtt", window.iceMqtt)
}
// window.iceMqtt = iceMqtt
script>
<script>
// 连接
function mqttConnect(clientId, host, port, username, password, objName, objFunc) {
// 创建一个mqttClient
iceMqtt.mqttCreateClient(clientId, host, port, username, password, objName, objFunc)
// 检查clientId
if (!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>
后,.jslib
文件无法发现内部的函数考虑将module
中的内容挂载到window
......
<script type="module">
// 先执行
import { iceMqtt } from './Plugins/iceMqtt.js'
window.onload = () => {
window.iceMqtt = iceMqtt
console.log("module iceMqtt", window.iceMqtt)
}
// window.iceMqtt = iceMqtt
script>
......
查找物体和组件
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)