WebGL关于网页端与U3D互动的传值方法

WebGL关于网页端与U3D互动的传值方法

本帖最后由 sconi 于 2017-2-16 09:47 编辑

因工作需要,所以对WEBGL进行了研究,期间遇到了挺多坑。所以针对我所遇到的坑,来做个总结。

这是我第一次发布教程类文章,所以如果有遗漏或没说清楚的地方,请留言告诉我。我也是刚刚研究,所以我无法讲清楚其中原理,所以只能写一些解决的方法,和心得体会。

测试环境:

系统:Windows7旗舰版SP1
HTTP服务器:Nodejs //可选服务器,浏览器也可直接运行。
U3D版本:.5.0f3
浏览器:火狐51.0.1 (32 位)
语言:c# javascript html

一个DEMO:
http://hecom.in/lab/webgl-chat/

实现方法:
首先发布Webgl,需要下载的支持组件,自动下载。
WebGL关于网页端与U3D互动的传值方法

123.gif (90.54 KB, 下载次数: 0)

下载附件  保存到相册

2017-2-15 18:22 上传



安装完毕后,即可发布WebGL版本了。
我第一次发布的时候遇到了错误,没有查询到有用的资料,后来*谷歌也无果。无奈,就将所有脚本剪切出项目,排除脚本问题,发现可以发布,于是再将脚本分批导入,排查。发现在原项目中使用了Forms控件,应该是Windows控件造成的。using System.Windows.Forms;//控件本身没有问题,注释相关函数即可生成WebGL。
这是遇到第一个问题,原因应该是U3D的WebGL不支持Forms控件,想想也对。

发布是很简单的,但原项目Mysql不能读取,国内无法获取到有用的信息,*谷歌查找资料,发现WEBGL不支持直连数据库,这耗费了我一天的时间。
查找资料的结果是要通过WEB端获取数据库的值,传值给U3D执行。
大致的流程是 Mysql->Web->Javascript-> 。
通过*谷歌找到一个日本开发者的博客,非常详实的介绍了WebGL
博客地址:http://tips.hecomi.com/entry/2014/12/08/002719

解决的办法:
这是WEB端的代码,通过JavaScript传值给U3D。
在U3D生成的index.html复制一份,改个名字,这样新生成的就不会覆盖修改后的了。
WEB端代码(基本是最小WEBGL框架了):

[HTML] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE html>
<html>
 
    <head>
        <meta charset="UTF-8">
        <title>测试Uweb</title>
        <script src="TemplateData/UnityProgress.js"></script>
        <link rel="stylesheet" href="TemplateData/style.css">
        <link rel="shortcut icon" href="TemplateData/favicon.ico" />
        <style type="text/css">
            .Main {
                width: 100%;
                height: 100%;
            }
             
            .MainLeft {
                width: 200px;
                float: left;
            }
             
            .MainRight {
                width: 800px;
                height: 600px;
                float: right;
            }
        </style>
    </head>
 
    <body>
        <!--html-->
        <div class="Main">
            <div style="font-size: 18px;text-align: center;">
                <h3>WebGL-测试</h3>
            </div>
            <div class="MainLeft">
                <div>
                    <form>
                        <div>
                            <label>字符串数据</label>
                            <input type="text" value="1" id="storeID" placeholder="测试数据">
                        </div>
                        <button type="button" >提交</button>
                    </form>
                </div>
            </div>
            <div class="MainRight">
                <canvas class="emscripten" id="canvas" style=" height: 500px;width: 600px;margin: 0;padding: 0;display: block;"></canvas>
            </div>
        </div>
        <div style="font-size: 18px;text-align: center;">
            <h3>By Code Sconi</h3>
        </div>
        </div>
    </body>
    <!--传值方法-->
    <script type="text/javascript">
        //按钮点击事件id为print()
        function print() {
            //获取ID名为storeID的Value的值,赋值给sID
            var sID = document.getElementById("storeID").value;
            console.log(sID);
            //传参到U3D场景内Button挂载脚本的OnClickText函数,参数为一个字符串
            SendMessage("Button", "OnClickText", sID);
        }
    </script>
    <!--Webgl获取数据方法,请根据自己U3D生成数据为准-->
    <script type='text/javascript'>
        var Module = {
            TOTAL_MEMORY: 268435456,
            errorhandler: null, // arguments: err, url, line. This function must return 'true' if the error is handled, otherwise 'false'
            compatibilitycheck: null,
            backgroundColor: "#ffffff",
            splashStyle: "Light",
            dataUrl: "Development/public.data",
            codeUrl: "Development/public.js",
            asmUrl: "Development/public.asm.js",
            memUrl: "Development/public.mem",
        };
    </script>
    <!--读取脚本,必须有-->
    <script src="Development/UnityLoader.js"></script>
 
</html>

SendMessage是WEBGL的通信方法,其结构为:SendMessage(“场景内物体名”,”挂载脚本内函数名”,参数);。

这样就将Input输入的内容传值到,U3D场景内的一个名称为“Button”的游戏物体,挂载的脚本内名为“OnClickText”函数,其参数为Input的值。

如果不写参数,那么会直接执行指定的函数。

Html和JavaScript的教程可以到:http://www.runoob.com/ 菜鸟教程网站获取。


接下来是U3D端的代码:

[C#] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class TestClickShell : MonoBehaviour {
    public Text WebText;
    public void OnClickText(string abc)
    {
        WebText.text = abc;  //在U3D的ugui的WebText上显示传值进来的字符串
    }
}

这样就将abc的值传递到U3D的函数内,并执行函数了。就可以通过WEB端的按钮来控制u3d场景的变化。

但我要做到的是要传递多个参数到U3D,所以这个方法要扩展一下,不假思索我首先尝试了这个:
[JavaScript] 纯文本查看 复制代码
 
SendMessage("Button", "OnClickText",abc,12);

和这个:
[JavaScript] 纯文本查看 复制代码
 
SendMessage("Button", "OnClickText",abc+12);

U3D:
[C#] 纯文本查看 复制代码
 
public void OnClickText(string abc,int number);

提示如下错误:
Failed to call function OnClickText of class TestClickShell Calling function OnClickText With1 parameter but the function requires 2.
函数需要2个参数,只传递了一个参数,错误;

又试了好多方法,都不行。

如果成功就见鬼了,所以我没搞清原理,就想当然了,于是翻山越岭找到一篇美帝的博客:http://www.feedingedge.co.uk/blog/2011/03/09/browser-to-unity3d-communication-and-back-again/

文章说,U3D只接受一个字符串(我试了Int也行),但只接收一个。

该博文还介绍了如何用分隔符来获取多个数值,找到宝藏了,于是修改为:

Javascript的传值方法:(替换HTML内的js代码,值的获取对照复制即可)
[JavaScript] 纯文本查看 复制代码
 
SendMessage("Button","OnClickText",abc+'~'+abc+'~'+abc);
通过建立分割符来分割不同参数,用连接串将不同参数连接起来。

U3D的接收方法:
U3D的c#函数只能接收一个字符串参数。
通过建立数组,使用自建分隔符str.Split(‘~’); 来,获取到多个数值。

[C#] 纯文本查看 复制代码
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class TestClickShell : MonoBehaviour {
public Text textGo;
public Text intGo;
public Text floatGo;
public void OnClickText(string str)
   {
     string[] words = str.Split('~');
     textGo.text = words[0];
     intGo.text = words[1];
     floatGo.text = words[2];
   }
}


OK这样,多值传递也可以了,这的确用了我几天的时间,也是非常有乐趣的几天。

这实现起来是很简单的,只是官方手册和国内资料,不够详尽,始终无法理解透彻,所以我翻山越岭总算解决了这些小问题。
这是我的第一篇,希望是个好的开端,我认为我说的一些可能不那么专业,但我尽力了。