转自 : 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,大致示意图如下
参考了很多帖子对我帮助很大,有兴趣可以看下:WebGL关于网页端与U3D互动的传值方法
知道了如何交互数据,但是问题还是没有解决,其中SendMessage无论如何都无法回传数值,奇怪,明明跟大家用的方法相同,为何会没有效果?无奈之下只能做小DEMO测试问题所在。
用Unity5.5作为测试版本,开始测试Unity与html之间的数值交互。首先创建一个Text,创建一个名为Show脚本挂载在Main Camera上。
打开脚本创建如下代码:
-
using UnityEngine;
-
using UnityEngine.UI;
-
public class Show : MonoBehaviour {
-
public Text showText;
-
void Start()
-
{
-
//调用外部函数(参数为方法名、参数)
-
Application.ExternalCall("SayHello", "Hello World!");
-
}
-
//获取返回值方法
-
public void Receive(string s)
-
{
-
showText.text = s;
-
}
-
}
将Text控件拖到Main Camera上挂载的方法中,接着发布为WebGL。
发布出来之后是1个html+2个文件夹,然后右键用VS打开html文件。
我们往Script中添加如下代码:
[javascript] view plain copy
- <code class="language-javascript"><script type='text/javascript'>
- function SayHello(arge){
- alert(arge);
- SendMessage("Main Camera", "Receive", "back");
- }
- </code>
OK,接下来我们右键html文件用火狐浏览器打开。
竟然成功了!刚才出问题的版本是Unity5.6,那是不是版本的问题呢,接下来我们再用5.6再试一下,操作跟之前相同,最后导出为WebGL,发现只有1个html和1个文件夹,而且从html中的代码也可以很清楚看到,Unity5.6较Unity5.5而言优化了很多,少了很多东西。
老规矩,我们往Script中添加上面的代码,然后右键运行。
可以看到方法是调用了,但是无法回传数值,还是没有解决。。。
于是我又开始搜寻解决方法,网上目前关于WebGL的解决方法太少了。
功夫不负有心人,我找到了一篇外文解决方案,我大致翻译一下:
在Unity5.6中我们使用的是一个新的嵌入方案,它允许嵌入一个适当的名称空间用于构建WebGL任意页面从而避免主页面代码的冲突。例如,现在你还应该能够嵌入多个基于相同的页面。因为这个原因全局的SendMessage就没有意义了,你应该显式地指定游戏中你发送消息的实例。每个游戏实例都有它自己的SendMessage方法(以及SetFullscreen方法)。html中的JavaScript 或许如下:
-
var gameInstance = UnityLoader.instantiate("gameContainer", "Build/mybuild.json", {onProgress: UnityProgress});
-
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");
代码如下:
-
<script>
-
var gameInstance = UnityLoader.instantiate("gameContainer", "Build/新建文件夹.json");
-
function SayHello(arge)
-
{
-
alert(arge);
-
gameInstance.SendMessage("Main Camera", "Receive", "back2");
-
}
-
</script>
终于运行成功了!不容易,Unity5.6之后的版本可以用这种方法解决。Unity官方针对Unity5.6版本进行API的优化却不说,会让使用者费很大的力去解决一个原本并不难的问题,而且,Unity支持各个平台其实还有很多坑,有些根本无法绕过,例如WebGL,选用之前请先充分考虑是否一定要用Unity开发网页端项目。
还有,在使用新版本之前请查看新版本的更新内容,说不定能帮上你大忙,避免踩到坑,本次就先这样吧,我也是新手,如有不足之处敬请原谅!