之前文章说到Unity制作的三维场景和可视化大屏图表结合有三种方式,这篇文章讲的是第三种方式的实现方法,Unity发布WebGL程序,嵌入到网页中和图表一同展示。
unity引擎本身是支持跨平台的,因此导出WebGL这个过程并不难
切换到WebGL平台
WebGL平台有以下几点设置需要注意:
1.如果要使用线性色彩空间,需要强制选择WebGL2
2.代码裁剪需要谨慎
代码裁剪可以减少打包文件的大小,这对于Web端来说还是很重要的,因为这节省了整个场景下载的时间,让客户等待时间减少了。
代码裁剪分为4个等级,选择不同等级,裁剪程度不一样,建议可以多打包测试几次,尽量选择高等级的裁剪。还有一些方式可以强制保留部分代码,让Unity有选择裁剪。
具体内容可以看官方文档:
https://docs.unity3d.com/Manual/ManagedCodeStripping.htmlhttps://docs.unity3d.com/Manual/ManagedCodeStripping.html3.压缩模式
尽量选择Disable,因为不能保证客户的前端和服务端对压缩格式进行了支持,如果不支持,还使用了压缩格式,会导致程序报错
4.浏览器调试
打包之后谷歌浏览器不能打开本地文件,但是火狐浏览器是可以的,安装浏览器后进行以下设置:
这部分内容官方文档也有具体说明:
https://docs.unity3d.com/2021.2/Documentation/Manual/webgl-interactingwithbrowserscripting.htmlhttps://docs.unity3d.com/2021.2/Documentation/Manual/webgl-interactingwithbrowserscripting.html
我们可以在Unity中自定义.jslib 扩展名的 JavaScript脚本,这个脚本需要放到Plugins文件夹里面
mergeInto(LibraryManager.library, { //固定格式
Hello: function () { //自定义函数
window.alert("Hello, world!");
},
UnityCallJS : function (str) {
window.UnityCallJS (UTF8ToString(str));
},
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]);
},
});
通信的目的是为了Unity能通知前端并传递数据,同时前端也能通知Unity并传递数据
所以我们只需要发送字符串就行了,字符串我们可以自定义一个json格式来保存不同内容。
这个脚本中的函数是可以直接调用js前端的内容的,因此我们可以前端定义一个接受Unity调用的函数,我们把这个函数挂在window节点下,然后可以通过UnityCallJs调用这个函数并传入字符串。
using UnityEngine;
using System.Runtime.InteropServices;
public class NewBehaviourScript : MonoBehaviour {
[DllImport("__Internal")]
private static extern void UnityCallJs(string str);
void Start() {
UnityCallJs("里面放入Json数据");
}
}
然后我们可以在Unity的C#代码中调用写好的JavaScript代码,这样就实现了Unity通知前端并传递数据
MyGameInstance.SendMessage('MyGameObject', 'MyFunction', 'MyString');
Js调用Unity就更简单了,只有SendMessage这一种用法,MyGameObject是场景中定义一个这个名字的物体,MyFunction是这个物体上挂载了一个脚本的函数名是这个,MyString就是函数的传参
Js调用Unity需要注意:
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";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
window.munityInstance= unityInstance;
}).catch((message) => {
alert(message);
});
};
查看打包出来的html文件,可以看到加载是需要时间的,只有加载完成后,才能完成通信。
上面代码的MyGameInstance就是这里的unityInstance,所以加载完成后,获取到unityInstance需要保存下来,然后就可以使用unityInstance.SendMessage进行通信了。
我这里存在了window节点下,为了方便调试。
打包完成后使用火狐浏览器打开html后,按下f12进入控制台
然后就可以在控制台直接调用Unity的函数进行通信测试了
Unity打包WebGL,嵌入前端使用,在可视化大屏业务中使用的比较多,通信部分可以封装成一个工具反复使用。之前在袋鼠云的时候,封装了EasyV的Unity容器,作用就是加载Unity的打包文件并通信。