不同版本Unity发布的WebGL与html,js间的相互通信

时间:2024-04-05 10:46:06

转自 : https://blog.csdn.net/york_new/article/details/78984678

 

Unity支持20多种平台听起来好像很厉害,可是稍微接触了才发现其实有很多大坑。最近因为项目需要接触了WebGL,其中还要连接SQL数据库,原本以为只需要发布为WebGL即可,结果问题很多,问题如下:

1.发布项目时报错(看了一下错误是System.Windows.Form.dll报错,应该是WebGL不支持对Windows的系统属性的调用,如本地IP地址以及windows窗口)
2.打开发布出来的Html格式文件报错(发布出来的Html只是测试文件,只能用火狐浏览器打开,发布到服务器上才能用其他浏览器打开)
3.项目中的文字消失(Webgl不支持使用本地字体也就是Unity默认字体,字体必须包含在Unity项目中)
4.项目无法与数据库连接
 

前面都是小坑,看一下网上的解决方案就能够解决,倒是最后一个坑花了我很长时间。我查了一下之后才知道,WebGL是无法直接跟本地(服务器)的数据库连接的,需要在Unity中调用html中的JavaScript方法,通过JavaScript跟数据库(服务器)进行数据传输,处理完数据之后再回传给Unity,大致示意图如下

不同版本Unity发布的WebGL与html,js间的相互通信

参考了很多帖子对我帮助很大,有兴趣可以看下:WebGL关于网页端与U3D互动的传值方法

 

知道了如何交互数据,但是问题还是没有解决,其中SendMessage无论如何都无法回传数值,奇怪,明明跟大家用的方法相同,为何会没有效果?无奈之下只能做小DEMO测试问题所在。

用Unity5.5作为测试版本,开始测试Unity与html之间的数值交互。首先创建一个Text,创建一个名为Show脚本挂载在Main Camera上。

不同版本Unity发布的WebGL与html,js间的相互通信

打开脚本创建如下代码:

 

 
  1. using UnityEngine;

  2. using UnityEngine.UI;

  3. public class Show : MonoBehaviour {

  4. public Text showText;

  5. void Start()

  6. {

  7. //调用外部函数(参数为方法名、参数)

  8. Application.ExternalCall("SayHello", "Hello World!");

  9. }

  10. //获取返回值方法

  11. public void Receive(string s)

  12. {

  13. showText.text = s;

  14. }

  15. }

 

将Text控件拖到Main Camera上挂载的方法中,接着发布为WebGL。

不同版本Unity发布的WebGL与html,js间的相互通信

发布出来之后是1个html+2个文件夹,然后右键用VS打开html文件。

不同版本Unity发布的WebGL与html,js间的相互通信

不同版本Unity发布的WebGL与html,js间的相互通信

我们往Script中添加如下代码:

 

[javascript] view plain copy

  1. <code class="language-javascript"><script type='text/javascript'>  
  2. function SayHello(arge){  
  3. alert(arge);  
  4. SendMessage("Main Camera", "Receive", "back");   
  5. }  
  6. </code>  
 

OK,接下来我们右键html文件用火狐浏览器打开。

不同版本Unity发布的WebGL与html,js间的相互通信

不同版本Unity发布的WebGL与html,js间的相互通信

竟然成功了!刚才出问题的版本是Unity5.6,那是不是版本的问题呢,接下来我们再用5.6再试一下,操作跟之前相同,最后导出为WebGL,发现只有1个html和1个文件夹,而且从html中的代码也可以很清楚看到,Unity5.6较Unity5.5而言优化了很多,少了很多东西。

不同版本Unity发布的WebGL与html,js间的相互通信

不同版本Unity发布的WebGL与html,js间的相互通信

老规矩,我们往Script中添加上面的代码,然后右键运行。

 

不同版本Unity发布的WebGL与html,js间的相互通信

不同版本Unity发布的WebGL与html,js间的相互通信

可以看到方法是调用了,但是无法回传数值,还是没有解决。。。

于是我又开始搜寻解决方法,网上目前关于WebGL的解决方法太少了。

功夫不负有心人,我找到了一篇外文解决方案,我大致翻译一下:

 

在Unity5.6中我们使用的是一个新的嵌入方案,它允许嵌入一个适当的名称空间用于构建WebGL任意页面从而避免主页面代码的冲突。例如,现在你还应该能够嵌入多个基于相同的页面。因为这个原因全局的SendMessage就没有意义了,你应该显式地指定游戏中你发送消息的实例。每个游戏实例都有它自己的SendMessage方法(以及SetFullscreen方法)。html中的JavaScript 或许如下:

 

 
  1. var gameInstance = UnityLoader.instantiate("gameContainer", "Build/mybuild.json", {onProgress: UnityProgress});

  2. setTimeout(function () {gameInstance.SendMessage("MyObject", "MyFunction", "testData");}, 3000);

 

请注意,您只需要使用这个外部游戏实例API从全局JavaScript名称空间发送消息到你的游戏。如果您正在使用SendMessage函数在一个JavaScript插件包含在您的项目,然后里面的插件代码将执行相应的模块名称空间,所以你可以直接从您的JavaScript插件调用SendMessage函数而不用使用外部调用API。

注:有一个小问题在早期的5.6测试版,API声明为.sendMessage代替.SendMessage。现在这应该是固定的。SendMessage和.SetFullscreen的游戏实例方法应以大写字母开始。

注:如果你想避免应用异常出现在你的案例中当游戏还在加载的时候,您可以直接重写onRuntimeInitialized模块方法从使用附加嵌入参数的html中,它将通知嵌入页面的模块准备好接收消息。

 

恍然大悟!于是我稍微修改了一下代码

gameInstance.SendMessage("Main Camera", "Receive", "back2");

代码如下:

 

 
  1. <script>

  2. var gameInstance = UnityLoader.instantiate("gameContainer", "Build/新建文件夹.json");

  3. function SayHello(arge)

  4. {

  5. alert(arge);

  6. gameInstance.SendMessage("Main Camera", "Receive", "back2");

  7. }

  8. </script>

 

 

不同版本Unity发布的WebGL与html,js间的相互通信

终于运行成功了!不容易,Unity5.6之后的版本可以用这种方法解决。Unity官方针对Unity5.6版本进行API的优化却不说,会让使用者费很大的力去解决一个原本并不难的问题,而且,Unity支持各个平台其实还有很多坑,有些根本无法绕过,例如WebGL,选用之前请先充分考虑是否一定要用Unity开发网页端项目。

还有,在使用新版本之前请查看新版本的更新内容,说不定能帮上你大忙,避免踩到坑,本次就先这样吧,我也是新手,如有不足之处敬请原谅!