Unity3D开发之WebGL平台上 unity和js前端通信交互 您所在的位置:网站首页 unity绑定脚本至camera Unity3D开发之WebGL平台上 unity和js前端通信交互

Unity3D开发之WebGL平台上 unity和js前端通信交互

2023-12-30 13:20| 来源: 网络整理| 查看: 265

自己虽然最开始弄的就是webgl但是一直比ios和安卓记录的都要晚,因为一直没想到,所以这里结合某个博客加上自己的经历记录一下

关于Unity在WebGL平台的特性和交互 可以参考官方文档 以及 Unity(WebGL)与JS通讯2022最新姿势

一.老版方法

unity发布webplayer平台后会输出html和unity3d文件。我们的程序主要被打包在unity3d文件里,而html则是网页的界面显示,webPlayer已经被弃用了,鉴于一些公司可能旧项目依然使用这个平台,这里就保留这部分解释。

1.Unity发送消息给JS

unity想要和js交互,提供了一个函数:Application.ExternalCall();此函数仅限于webplayer平台下。我们编辑发布的html文件,在里面加入我们的js脚本如下:

function GetID(id) { alert("传入id:"+id); }

在unity里我们在start函数里调用

Application.ExternalCall("GetID","吴彦祖");

使用浏览器打开html文件,就会出现如下弹窗:

在这里插入图片描述

2.JS发送消息给unity

我们在刚才的js函数里添加一句代码:

function GetID(id) { alert("传入id:"+id); //发送消息给unity 第一个参数:挂在脚本的物体 第二个参数:unity被调用的函数 第三个参数:函数传入的参数 u.getUnity().SendMessage("Main Camera","GetIDInfo","JayW") }

在unity里创建一个函数用来接收处理:

public void GetIDInfo(string id) { text.text = id; }

运行效果如下: 在这里插入图片描述

二.新版方法

最近在使用webgl方面,2018.2.9版本弃用了Application.ExternalCall方法。选择添加一个jslb文件作为中间层。我们搜官方文档可以看到使用方式如下,官方文档 WebGL:与浏览器脚本交互

Unity主动发起调用js函数

首先创建一个文本,文件格式保持为.jslib。这个文件存放的是c#主动通信前端的中间方法,我们在里面增加我们要接受c#传来的数据和js要调用的函数。 代码如下:

mergeInto(LibraryManager.library, { //这里是代码1 JSLog: function (str) { var strs=Pointer_stringify(str); //这个Log方法是前端那边写的方法 Log(strs); }, //这里可以添加若干个方法,方法之间记得用逗号隔开, //否则WebGL平台打包的时候会报错 });

注意:这里一定要用unity内置函数Pointer_stringify将传进来的str转换成字符串。如果不转换str存储的是内存地址位。传到js就是一堆数字。最后保存文件,将文件放到unity工程下的Plugins文件夹内。

然后在c#代码块里,我们加上我们要调用的方法:

[DllImport("__Internal")] private static extern void JSLog(string str);//此处传入的类型和调用时候传入的数据类型一定要一致 void Start() { //如果有返回值,可以定义变量接收返回值 JSLog("666"); }

这里我们在C#里面调用了工程中的jslib文件的函数。

最后使我们打包出来的html文件里,在scrip块内加入jslib的JSLog里面被调用的函数Log:

function Log(str) { console.log(str);; gameInstance.SendMessage('Main Camera','GetStr',String(str)); }

在jslib的方法里面,如果调用前端的方法后有字符串返回 则需要这样写,字符串才能返回到c#里面

//获取服务器访问的认证 getServerAuth: function(){ var token = window.THREE_TOKEN(); console.log("jslib getServerAuth token " + token); //这样写 var bufferSize = lengthBytesUTF8(token) + 1; var buffer = _malloc(bufferSize); stringToUTF8(token, buffer, bufferSize); return buffer; }, js主动发起Unity函数调用

前端调用的时候是这样的

this.gameInstance.SendMessage('OutSideInteractor', 'ReceiveDlteAddedProduct ', id)

其中 this.gameInstance是unity webgl平台出包后的文件夹里面的index.html的gameInstance对象.

SendMessage方法第一个是场景里面的物体名字,第二个是物体所挂脚本里面的某个方法名字,第三个参数是参数,要注意的是,即使前两个写对了,如果第三个参数没传对,也会报错说找不到方法

下面是index.html里面定义的内容,前端调用Unity的代码也可以写到这里,但更多是写到前端自己的某个脚本里面

var gameInstance = UnityLoader.instantiate("gameContainer", "Build/CPWEBGL.json", { onProgress: UnityProgress }) window.ReceiveAddSceneItemStr = function (e) { gameInstance.SendMessage('OutSideInteractor', 'ReceiveAddSceneItemStr', e) }

这里的CPWEBGL是我打webgl包的最后一个文件夹的名字,生成的json和unityLoad文件的文件名字与这个名字相同,unityLoad文件是Unity的主要内容的存放文件,这个名字一般要和前端约定好,因为前端加载Unity文件的时候会写死一个名字,双方的名字不同的时候会出现问题。具体参考 Unity WebGL错误集锦

因为这里使用的2021.3.8f1c1,后面的unity打包的index出入比较大,原来的gameInstance已经找不到了。 也可以在index.html的onLoad方法里面加上回调的语句,onLoad这个方法在生成好的工程的index.html里面是有的。这里的unityInstance由回调函数传入。 在这里插入图片描述

script.onload = () => { createUnityInstance(canvas, config, (progress) => { progressBarFull.style.width = 100 * progress + "%"; }).then((unityInstance) => { loadingBar.style.display = "none"; fullscreenButton.onclick = () => { unityInstance.SetFullscreen(1); }; unityInstance.SendMessage('Main Camera', 'ReceieveFromJS', "456"); }).catch((message) => { alert(message); }); };

经过测试是可以的。

要注意的一点是这时虽然能够传输信息,但是传输过去的时候对于大多数的脚本,其可能awake都还没有执行。所以这时进行变量的存储的比较必要的。有些变量在awake之后才进行使用。

index.html可以在unity的编辑器的Aseet文件夹下面的WebGLTemplates里面定义好,用于自定义WebGL加载画面 具体过程可以百度WebGLTemplates.

或者这里有一篇比较好的参考 【Unity3D日常开发】Unity3D模板 WEBGL模板 自定义Templates 使用教程

另外还要注意的一个点是,在onLoad刚刚结束的时候,可能Unity的生命周期还没开始。 此时往Unity里面发送消息完全是靠 运气的,有时能接收到,有时不能接收到。

所以做法是延迟一段时间,再往里面发送消息。 上面的

unityInstance.SendMessage('Main Camera', 'ReceieveFromJS', "456");

改成

setTimeout(function(){ // 延迟调用的方法 unityInstance.SendMessage('ReceiveFromJSToken', 'ReceiveFromJSMethod1', window.location.href); }, 0.7); 报错 在打包的时候,jslib里面不能够有中文。注释也是不行的。否则就会报这个错。 Building Library\Bee\artifacts\WebGL\build\debug_WebGL_wasm\build.js failed with output: Traceback (most recent call last): File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py", line 3571, in sys.exit(main(sys.argv)) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py", line 3564, in main ret = run(args) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py", line 1082, in run phase_post_link(options, wasm_target, wasm_target, target) File "D:\obj\windows-release\37amd64_Release\msi_python\zip_amd64\contextlib.py", line 74, in inner File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py", line 2400, in phase_post_link phase_emscript(options, in_wasm, wasm_target, memfile) File "D:\obj\windows-release\37amd64_Release\msi_python\zip_amd64\contextlib.py", line 74, in inner File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emcc2.py", line 2428, in phase_emscript emscripten.run(in_wasm, wasm_target, final_js, memfile) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emscripten.py", line 830, in run emscript(in_wasm, out_wasm, outfile_js, memfile, shared.DEBUG) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emscripten.py", line 308, in emscript glue, forwarded_data = compile_settings() File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\emscripten.py", line 178, in compile_settings cwd=path_from_root('src'), env=env) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\tools\shared.py", line 216, in run_js_tool return check_call(command, *args, **kw).stdout File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\tools\shared.py", line 202, in check_call return run_process(cmd, *args, **kw) File "C:\Program Files\Unity\Hub\Editor\2021.3.8f1c1\Editor\Data\PlaybackEngines\WebGLSupport\BuildTools\Emscripten\emscripten\tools\shared.py", line 97, in run_process ret = subprocess.run(cmd, check=check, input=input, *args, **kw) File "D:\obj\windows-release\37amd64_Release\msi_python\zip_amd64\subprocess.py", line 474, in run File "D:\obj\windows-release\37amd64_Release\msi_python\zip_amd64\subprocess.py", line 926, in communicate UnicodeDecodeError: 'gbk' codec can't decode byte 0x99 in position 393654: illegal multibyte sequence UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) 工程示例

Unity WebGL 前端js互相交互示例工程



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有