javascript 调用js-Unity3D在WebGL平台上开发unity与js后端通信交互

2023-08-29 0 9,356 百度已收录

其实我一开始用的是webgl,比ios和Android的记录还晚。 由于没想到javascript 调用js,所以结合博客和自己的经历记录在这里。

Unity在WebGL平台上的特性及交互请参考官方文档

与Unity(WebGL)和JS沟通2022最新坐姿

1. 老方法

unity发布webplayer平台后,会输出html和unity3d文件。 我们的程序主要封装在unity3d文件中,html是网页的界面显示。 webPlayer 早已被弃用。 由于有些公司老项目可能还在使用这个平台,所以这里保留这部分解释。

1.Unity向JS发送消息

Unity想要和js交互,提供了一个函数:Application.ExternalCall(); 此功能仅限于网页播放器平台。 我们编辑发布的 html 文件并在其上添加 js 脚本,如下所示:

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

在unity中我们调用start函数

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

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

javascript 调用js-Unity3D在WebGL平台上开发unity与js后端通信交互

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;
    }

运行效果如下:

2、新版本

javascript 调用js-Unity3D在WebGL平台上开发unity与js后端通信交互

最近在使用webgl方面,2018.2.9版本弃用了Application.ExternalCall方法。 选择添加jslb文件作为中间层。我们搜索官方文档可以看到使用方法如下,官方文档WebGL: Interacting with browser scripting

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为unitywebgl平台打包后文件夹下index.html的gameInstance对象。

SendMessage的第一个方法是场景中对象的名称,第二个是附加到该对象的脚本上的方法名称,第三个参数是参数。 需要注意的是,虽然前两个是正确的,但是如果第三个参数没有正确传递的话javascript 调用js,就会报错说找不到该方法

下面是上面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文件的时候会写一个名字,两方名字不同就会出现问题。具体可以参考UnityWebGL错误集合

因为这里使用的是2021.3.8f1c1,所以之前的unity包的索引比较大,原来的gameInstance早就丢失了。 还可以在index.html的onLoad方法中添加反弹语句。 onLoad 方法在生成的项目的index.html 上可用。 这里的unityInstance是bounce函数传入的。

 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);
        });
      };

测试后就OK了。

需要注意的一点是,即使此时可以传输信息,当唤醒过去时,大部分脚本也可能不会被执行。 所以这个时候就需要存储变量。 有些变量直到唤醒后才会使用。

可以在unity编辑器的Aseet文件夹下的WebGLTemplates上定义index.html来自定义WebGL加载屏幕

具体流程可以百度WebGLTemplates。

或者这里有更好的参考【Unity3D日常开发】Unity3D模板WEBGL模板自定义模板教程

还有一点需要注意的是,当onLoad刚刚结束时,Unity的生命周期可能还没有开始。

这时候向Unity发送消息完全是靠运气,有时能收到,有时收不到。

所以做法就是延迟一段时间,然后给它发消息。

里面

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

变成

  setTimeout(function(){
    // 延迟调用的方法
    unityInstance.SendMessage('ReceiveFromJSToken',
            'ReceiveFromJSMethod1', window.location.href);
  }, 0.7);

打包的时候报错,jslib上不能有英文。 评论也不予受理。 否则会报这个错误。

Building LibraryBeeartifactsWebGLbuilddebug_WebGL_wasmbuild.js failed with output:
Traceback (most recent call last):
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemcc2.py", line 3571, in <module>
    sys.exit(main(sys.argv))
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemcc2.py", line 3564, in main
    ret = run(args)
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemcc2.py", line 1082, in run
    phase_post_link(options, wasm_target, wasm_target, target)
  File "D:objwindows-release37amd64_Releasemsi_pythonzip_amd64contextlib.py", line 74, in inner
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemcc2.py", line 2400, in phase_post_link
    phase_emscript(options, in_wasm, wasm_target, memfile)
  File "D:objwindows-release37amd64_Releasemsi_pythonzip_amd64contextlib.py", line 74, in inner
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemcc2.py", line 2428, in phase_emscript
    emscripten.run(in_wasm, wasm_target, final_js, memfile)
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemscripten.py", line 830, in run
    emscript(in_wasm, out_wasm, outfile_js, memfile, shared.DEBUG)
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemscripten.py", line 308, in emscript
    glue, forwarded_data = compile_settings()
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptenemscripten.py", line 178, in compile_settings
    cwd=path_from_root('src'), env=env)
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptentoolsshared.py", line 216, in run_js_tool
    return check_call(command, *args, **kw).stdout
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptentoolsshared.py", line 202, in check_call
    return run_process(cmd, *args, **kw)
  File "C:Program FilesUnityHubEditor2021.3.8f1c1EditorDataPlaybackEnginesWebGLSupportBuildToolsEmscriptenemscriptentoolsshared.py", line 97, in run_process
    ret = subprocess.run(cmd, check=check, input=input, *args, **kw)
  File "D:objwindows-release37amd64_Releasemsi_pythonzip_amd64subprocess.py", line 474, in run
  File "D:objwindows-release37amd64_Releasemsi_pythonzip_amd64subprocess.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&)

工程实例

UnityWebGL后端js交互示例项目

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript 调用js-Unity3D在WebGL平台上开发unity与js后端通信交互 https://www.wkzy.net/game/181904.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务