• Unity中嵌入网页插件Embedded Browser2.1.0


    背景

    最近刚换了工作,新公司不是做手游的,一开始有点抵触,总觉得不是做游戏自己就是跨行了,认为自己不对口,但是慢慢发现在这可以学的东西面很广,所以感觉又到了打怪升级的时候了,老子就在这进阶了。

    一进公司他们使用H5开发,做一款地形信息系统的软件,基于Unity开发,但是所有页面都是Js写的,所以我第一件事要做的是实现Unity嵌入网页,并实现交互。

    在这里,领导说之前做过类似的即用的Embedded Browser2.1.0这个插件,让我研究下做个简单Demo。

    实现方案

    使用插件Embedded Browser2.1.0实现unity与网页交互

    具体步骤

    1.Unity中导入插件

    2.新建Canvas,在Canvas下创建一GameObject,平铺在Canvas上

    3.将网页映射到GameObject上

    这一步需要给创建的BrowserGUI挂载插件脚本

    首先是Brower脚本,此脚本是设置嵌入网页的URL以及一些幕布大小等参数,在这里说下,有两种嵌入方式

    ,1.可以直接嵌入浏览器网页2.可以将html文件放入与Assets文件夹同级的BrowserAssets(必须一致,必须是这个文件夹,因为若放Assets下面,会自动默认为代码为UnityScript而不是JavaScript),加载嵌入,这种方式相对快一些。

    再一个就是挂载GUI Brower UI脚本,这脚本是构建UI的一个作用,请求的网页会显示出来是因为这个脚本,并且会自动添加上Raw Image组件

    Unity通过插件与网页的交互

    1.Unity接收网页操作做出响应

    C#监听代码:

    js代码:

    Tips:Unity接收网页推送事件RegisterFunction(“MethodName”,CallBack);

    即:网页进行一系列操作,unity中监听到并响应执行事件

    2.Unity做出相应操作通知网页并更新网页显示

    案例:此为unity方5秒倒计时,每轮计时结束时间重置,目标数+=3;通知网页端并显示的Demo

    c# 代码:

    Js代码:

    Tips:网页监听Unity操作:browser.CallFunction("MethodName",params).Down();

     即:unity进行一系列操作,unity通知网页自身变化并调用网页更新函数

    完整代码

    场景1:网页点击按钮,Unity接收参数:

     c#:

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEngine.UI;
      5 using ZenFulcrum.EmbeddedBrowser;
      6 using UnityEngine.SceneManagement;
      7 /// <summary>
      8 /// Unity使用插件控制脚本
      9 /// </summary>
     10 public class DemoTexMgr : MonoBehaviour
     11 {
     12     /// <summary>
     13     /// 插件组件
     14     /// </summary>
     15     Browser browser;
     16     /// <summary>
     17     /// 监听H5操作作出响应物体
     18     /// </summary>
     19     public Transform targetScle;
     20 
     21     /// <summary>
     22     /// 嵌入网页地址
     23     /// </summary>
     24     string URL = "file:///C:/Users/lenovo/Desktop/工作/自测需要/测试Js脚本/TextTool.html";
     25     /// <summary>
     26     /// 目标位置(显示同步到H5)
     27     /// </summary>
     28     private Vector3 targetPos;
     29     public Vector3 TargetPos { get; set; }
     30 
     31 
     32     private void Awake()
     33     {
     34         //获取插件Browser组件(Unity方使用插件基础一步)
     35         browser = transform.Find("BrowserGUI").GetComponent<Browser>();
     36     }
     37     void Start()
     38     {
     39         InitData();
     40     }
     41     public void Update()
     42     {
     43        
     44     }
     45     /// <summary>
     46     /// 初始化函数(初始化嵌入页面)
     47     /// </summary>
     48     public void InitData()
     49     {
     50         //设置嵌入页面网址
     51         browser.Url = URL;
     52         //插件前往函数
     53         browser.GoForward();
     54         //browser.gameObject.GetComponent<RawImage>().raycastTarget = false;
     55 
     56         //改变背景深度(透明度)
     57         browser.gameObject.GetComponent<RawImage>().color = new Color(browser.gameObject.GetComponent<RawImage>().color.r, browser.gameObject.GetComponent<RawImage>().color.b, browser.gameObject.GetComponent<RawImage>().color.g, 20);
     58        
     59         //插件中监听函数,监听H5操作(点击缩小按钮,Unity做出缩小响应)
     60         browser.RegisterFunction("displayDate", (JSONNode jk) =>
     61         {
     62             Debug.Log("yuanjun  Unity Get  H5     参数" + jk[0].AsJSON + "  参数  " + jk[1].AsJSON + "  " + jk[0].Value);
     63             targetScle.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
     64         });
     65         browser.RegisterFunction("GetUniMethodty", (JSONNode jk) =>
     66         {
     67             targetScle.transform.localScale = new Vector3(float.Parse(jk[0].AsJSON), 0.8f, 0.8f);
     68             Debug.Log("yuanjun  Unity Get  H5  GetUniMethodty    参数1" + jk[0].AsJSON);
     69         });
     70 
     71     } 96     //退出按钮
     97     public void OnClickQuitBtn()
     98     {
     99         Application.Quit();
    100     }
    101     public void ChangeBtn()
    102     {
    103         SceneManager.LoadScene(1);
    104     }
    105 }

    js脚本:

     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      2 <html xmlns="http://www.w3.org/1999/xhtml">
      3 <head>
      4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      5 <title>类似于Jquery的JS下拉菜单</title>
      6 <style type="text/css">
      7 * { margin: 0; padding: 0; font-style: normal; font-family: 宋体; }
      8 body { text-align: center; font-size: 12px; background:url(1.jpg) center center; }
      9 #content { margin: 0 auto;  600px; }
     10 #content #nav { height: 32px; margin-top: 60px; background-color: #464749;FILTER: alpha(opacity=80); opacity: 0.8; -moz-opacity: 0.8;  }
     11 #content #nav ul { list-style: none; }
     12 #content #nav ul li { float: left;  100px; line-height: 32px; position: relative; }
     13 #nav div {  100px;FILTER: alpha(opacity=80); opacity: 0.8; -moz-opacity: 0.8; position:absolute; left:0px; top:32px; z-index:1; padding-bottom: 0px; float: left; height: 0; overflow: hidden; background-color: #fff;color:#000; }
     14 #content #nav li .a { text-decoration: none; color: #FFFFFF; line-height: 32px; display: block; border-right- 1px; border-right-style: solid; border-right-color: #393A3C; }
     15 #nav div a { text-decoration: none; color: #000; line-height: 26px; display: block; z-index:100; }
     16 #nav div a:hover { background-color: #ccc; }
     17 </style>
     18 </head>
     19 <body>
     20 <div id="content">
     21   <div id="nav">
     22     <ul id="supnav">
     23       <li><a href="#" class="a">物体变大</a>
     24         <div>
     25             <button onclick="GetUniMethodty(5)">变大</button>
     26         </div>
     27       </li>
     28       <li><a href="#" class="a">物体旋转</a>
     29         <div> 
     30             <a href="#">物体旋转</a> 
     31         </div>
     32       </li>
     33       <li><a href="#" class="a">物体缩小</a>
     34         <div> 
     35             <button onclick="displayDate(1,2)">缩小</button>
     36         </div>
     37       </li>
     38       <li><a href="#" class="a">导航菜单</a>
     39         <div> 
     40             <a href="#">导航菜单</a> 
     41         </div>
     42       </li>
     43       <li><a href="#" class="a">导航菜单</a>
     44         <div> 
     45             <a href="#">导航菜单</a> 
     46         </div>
     47       </li>
     48       <li><a href="#" class="a">导航菜单</a>
     49         <div> 
     50             <a href="#">导航菜单</a> 
     51          </div>
     52       </li>
     53     </ul>
     54   </div>
     55 </div>
     56 <script type="text/javascript">
     57     var supnav = document.getElementById("supnav");
     58     var nav = document.getElementById("nav");
     59     var btns = document.getElementsByTagName("li");
     60     var subnavs = nav.getElementsByTagName("div");
     61     var paddingbottom = 20;
     62     var defaultHeight = 0;
     63     function drop(obj, ivalue) {
     64         var a = obj.offsetHeight;
     65         var speed = (ivalue - obj.offsetHeight) / 8;
     66         a += Math.floor(speed);
     67         obj.style.height = a + "px";
     68     }
     69     window.onload = function() {
     70         for (var i = 0; i < btns.length; i++) {
     71             btns[i].index = i;
     72             btns[i].onmouseover = function() {
     73                 var osubnav = subnavs[this.index];
     74                 var sublinks = osubnav.getElementsByTagName("a");
     75                 if (osubnav.firstChild.tagName == undefined) {
     76                     var itarheight = parseInt(osubnav.childNodes[1].offsetHeight) * sublinks.length + paddingbottom;
     77                 } else {
     78                     var itarheight = parseInt(osubnav.firstChild.offsetHeight) * sublinks.length + paddingbottom;
     79                 }
     80                 clearInterval(this.itimer);
     81                 this.itimer = setInterval(function() {
     82                     drop(osubnav, itarheight);
     83                 },
     84                 30);
     85             }
     86             btns[i].onmouseout = function() {
     87                 var osubnav = subnavs[this.index];
     88                 clearInterval(this.itimer);
     89                 this.itimer = setInterval(function() {
     90                     drop(osubnav, defaultHeight);
     91                 },
     92                 30);
     93             }
     94         }
     95     }
     96 </script>
     97 
     98 
     99 <script>
    100 function displayDate(a,b){
    101  alert("DisPlayData  " +a );
    102 return a+b;
    103 }
    104 </script>
    105 
    106 <script>
    107 function GetUniMethodty(s){
    108        alert("Data Come " +s);
    109    return s;
    110 }
    111 </script>
    112 
    113 
    114 <script>
    115 function myFunction(){
    116     alert("Welcome " +  "Harry Potter ");
    117 }
    118 </script>
    119 
    120 </body>
    121 </html>
    View Code

     场景2:Unity中Cube移动位置,网页上位置信息更新

    c#:

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEngine.UI;
      5 using ZenFulcrum.EmbeddedBrowser;
      6 using UnityEngine.SceneManagement;
      7 public class DemoTesxMgrOne : MonoBehaviour
      8 {
      9     /// <summary>
     10     /// 插件组件
     11     /// </summary>
     12     Browser browser;
     13     /// <summary>
     14     /// 监听H5操作作出响应物体
     15     /// </summary>
     16     public Transform targetScle;
     17 
     18     /// <summary>
     19     /// 嵌入网页地址
     20     /// </summary>
     21     string URL = "file:///C:/Users/lenovo/Desktop/工作/自测需要/测试Js脚本/demo.html";
     22     /// <summary>
     23     /// 目标位置(显示同步到H5)
     24     /// </summary>
     25     public delegate void del(Vector3 v);
     26     public del _del;
     27     public Vector3 oldv;
     28     private Vector3 targetPos;
     29     public Vector3 TargetPos {
     30         get {
     31             return targetPos;
     32             }
     33         set
     34         {
     35             targetPos = value;
     36             if (oldv!=targetPos)
     37             {
     38                 _del(targetPos);
     39                 oldv=targetPos;
     40             }
     41         } }
     42 
     43     public int TextValue = 0;
     44     public float timer = 5;
     45 
     46     private void Awake()
     47     {
     48         //获取插件Browser组件(Unity方使用插件基础一步)
     49         browser = transform.Find("BrowserGUI").GetComponent<Browser>();
     50         _del += calH5;
     51        // oldv = targetScle.transform.localPosition;
     52     }
     53     void Start()
     54     {
     55         InitData();
     56     }
     57     public void Update()
     58     {
     59         TargetPos = targetScle.transform.localPosition;
     60             //if (timer > 0)
     61             //{
     62             //    timer -= Time.deltaTime;
     63             //}
     64             //else
     65             //{
     66             //    TextValue += 3;
     67             //    timer = 5;
     68             //    browser.CallFunction("selall", TextValue).Done();
     69             //}
     70 
     71     }
     72     public void calH5(Vector3 v)
     73     {
     74         browser.CallFunction("selall", v.ToString()).Done();
     75     }
     76     /// <summary>
     77     /// 初始化函数(初始化嵌入页面)
     78     /// </summary>
     79     public void InitData()
     80     {
     81         //设置嵌入页面网址
     82         browser.Url = URL;
     83         //插件前往函数
     84         browser.GoForward();
     85         //browser.gameObject.GetComponent<RawImage>().raycastTarget = false;
     86 
     87         //改变背景深度(透明度)
     88         browser.gameObject.GetComponent<RawImage>().color = new Color(browser.gameObject.GetComponent<RawImage>().color.r, browser.gameObject.GetComponent<RawImage>().color.b, browser.gameObject.GetComponent<RawImage>().color.g, 20);
     89 
     90         //插件中监听函数,监听H5操作(点击缩小按钮,Unity做出缩小响应)
     91         //browser.RegisterFunction("displayDate", (JSONNode jk) =>
     92         //{
     93         //    Debug.Log("yuanjun  Unity Get  H5     参数" + jk[0].AsJSON + "  参数  " + jk[1].AsJSON + "  " + jk[0].Value);
     94         //    targetScle.transform.localScale = new Vector3(0.8f, 0.8f, 0.8f);
     95         //});
     96         //browser.RegisterFunction("GetUniMethodty", (JSONNode jk) =>
     97         //{
     98         //    targetScle.transform.localScale = new Vector3(float.Parse(jk[0].AsJSON), 0.8f, 0.8f);
     99         //    Debug.Log("yuanjun  Unity Get  H5  GetUniMethodty    参数1" + jk[0].AsJSON);
    100         //});
    101 
    102     }
    103 
    104     //unity调试
    105     public void OnClickJsData()
    106     {//调用页面中任何可用的js(自上而下)
    107      // browser.EvalJS("displayDate(7,5)").Then(Result =>
    108      //   { Debug.Log(Result.Value); }
    109      //).Done();
    110      // //查询页面中的数据,可以查看返回值(测试多返回值时好像只返回最后一个值)
    111      //browser.CallFunction("displayDate", 1, 2).Then(Result =>
    112      //{
    113      //    Debug.Log(" displayDate   " + Result.Value);
    114      //});
    115 
    116        // browser.CallFunction("selall", 100).Done();
    117 
    118     }
    119  
    120     //退出按钮
    121     public void OnClickQuitBtn()
    122     {
    123         Application.Quit();
    124     }
    125     public void ChangeBtn()
    126     {
    127         SceneManager.LoadScene(0);
    128     }
    129 }

     js:

    1 <body>
     2 <!-- 我记得复选框不是这样写的? 那个是 下拉选择框 -->
     3 <input type="checkbox" id="cb1" onclick="fun0()"/>全选/全不选
     4 </br>
     5 <input type="checkbox" name="love">篮球<br/>
     6 <input type="checkbox" name="love">足球<br/>
     7 <input type="checkbox" name="love">排球<br/>
     8 <input type="checkbox" name="love">冰球<br/>
     9  
    10 <input type="button" value="全选" onclick="selall()"/>
    11 <input type="button" value="全不选" onclick="selno()"/>
    12 <input type="button" value="反选" onclick="selother()"/>
    13 <script type="text/javascript">
    14 function fun0(){
    15 var cb = document.getElementById("cb1");
    16 if(cb.checked==true){
    17 selall();
    18 }else{
    19 selno();
    20 }
    21 }
    22 function selall(a){
    23 alert(a);
    24 var nodes = document.getElementsByName("love");
    25 for(var i = 0; i < nodes.length; i++){ //遍历节点
    26 var node1 = nodes[i];
    27 node1.checked = true; //把节点的checked属性设置为 true
    28 }
    29 }
    30 function selno(){
    31 var nodes = document.getElementsByName("love");
    32 for(var j = 0; j < nodes.length; j++){ //遍历节点
    33 //var node2 = nodes[j];
    34 //node2.checked = false;
    35 nodes[j].checked = false; //把节点的checked属性设置为 false
    36 }
    37 }
    38 </script>
    39 </body>
    View Code

     Tips:注意以上有不少冗余代码,为什么用两个场景两个网页测试,归根结底是因为我不懂Js,我想要的事件一个无法满足还不会扩展,所以,重点看方法不看代码。

    我也只是跑通了,里面还有很多方法函数,我这里只是先实现了互通,理解可能不准确或者不对,热烈欢迎指出并交流。

    最近:最近在做demo时,具体遇到了这么几点:

    1.上面在嵌入网页时需要挂在GUI Brower UI脚本,但是在我做demo时发现,这个脚本在这个版本还可以用,但是已被编辑为过时[Obsolete("Use PointerUIGUI and CursorRendererOS instead.")],应用PointerUIGUI脚本替代。

    2.

    js代码:

      1 <!doctype html>
      2 <html lang="en">
      3   <head>
      4     <!-- Required meta tags -->
      5     <meta charset="utf-8">
      6     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      7 
      8     <!-- Bootstrap CSS -->
      9     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
     10 
     11     <title>Ventilation UI</title>
     12 
     13     <style>
     14         html {
     15             height: 100%;
     16         }
     17 
     18         body
     19         {
     20             font-family: Monospace;
     21             font-weight: bold;
     22             background-color: #ccccff00;
     23             margin: 0px;
     24             height: 100%;
     25             overflow: hidden;
     26         }
     27     </style>
     28 
     29   </head>
     30   <body>
     31       <!-- Optional JavaScript -->
     32       <!-- jQuery first, then Popper.js, then Bootstrap JS -->
     33       <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
     34       <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
     35       <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
     36 
     37       <div class="container">
     38           <div class="btn-toolbar " role="toolbar" aria-label="Toolbar">
     39               <div class="btn-group mr-2" role="group" aria-label="First Group">
     40                   <button id="createLaneway" type="button" class="btn btn-success">新建</button>
     41                   <button id="editLaneway" type="button" class="btn btn-success">编辑</button>
     42                   <button id="drawAirDuct" type="button" class="btn btn-success">绘制</button>
     43                   <button id="drawAirDoor" type="button" class="btn btn-success">绘制</button>
     44                   <button id="drawLine" type="button" class="btn btn-success">画线</button>
     45                   <button id="drawFace" type="button" class="btn btn-success">画面</button>
     46               </div>
     47               <div class="btn-group mr-2" role="group" aria-label="Second Group">
     48                   <button type="button" class="btn btn-success">平移</button>
     49                   <button type="button" class="btn btn-success">旋转</button>
     50                   <button type="button" class="btn btn-success">缩放</button>
     51               </div>
     52               <div class="btn-group" role="group" aria-label="Fourth group">
     53                   <button id="undo" type="button" class="btn btn-success">撤销</button>
     54                   <button id="redo" type="button" class="btn btn-success">重做</button>
     55                   <button id="none" type="button" class="btn btn-success">退出编辑</button>
     56                   <button id="exit" type="button" class="btn btn-success">退出程序</button>
     57               </div>
     58           </div>
     59       </div>
     60 
     61       <script>
     62           $('#createLaneway').on('click', function () { onCreateLane(); });
     63           $('#editLaneway').on('click', function () { onEditLane(); });
     64           $('#drawAirDuct').on('click', function () { onDrawDuct(); });
     65           $('#drawAirDoor').on('click', function () { onDrawDoor(); });
     66           $('#drawLine').on('click', function () { onDrawLine(); });
     67           $('#drawFace').on('click', function () { onDrawFace(); });
     68           $('#undo').on('click', function () { onUndo(); });
     69           $('#redo').on('click', function () { onRedo(); });
     70           $('#none').on('click', function () { onExitEdit(); });
     71           $('#exit').on('click', function () { onExit(); });
     72 
     73 
     74           
     75           function onCreateLane(e) {
     76 
     77               console.log('新建');
     78 
     79           }
     80 
     81           
     82           function onEditLane(e) {
     83 
     84               console.log('编辑');
     85 
     86           }
     87 
     88         
     89           function onDrawDuct(e) {
     90 
     91               console.log('绘制');
     92 
     93           }
     94 
     95           
     96           function onDrawDoor(e) {
     97 
     98               console.log('绘制');
     99 
    100           }
    101 
    102           // 画线事件响应
    103           function onDrawLine(e) {
    104 
    105               console.log('画线');
    106 
    107           }
    108 
    109           // 画面事件响应
    110           function onDrawFace(e) {
    111 
    112               console.log('画面');
    113 
    114           }
    115 
    116           // 撤销事件响应
    117           function onUndo(e) {
    118 
    119               console.log('撤销');
    120 
    121           }
    122 
    123           // 重做事件响应
    124           function onRedo(e) {
    125 
    126               console.log('重做');
    127 
    128           }
    129 
    130           function onExitEdit() {
    131               console.log('退出编辑');
    132           }
    133 
    134           function onExit() {
    135               console.log('退出');
    136           }
    137 
    138           //加载结束
    139           function loadEnd() {
    140               console.log("Load end");
    141           }
    142 
    143           window.onload = function () { loadEnd(); }
    144 
    145       </script>
    146 
    147   </body>
    148 </html>
    View Code

    这种注册按钮的方式,按着我之前说的那中监听方式会监听不到,

    如:  $('#createLaneway').on('click', function () { onCreateLaneway(); });这句注册按钮代码,如果写成  $('#createLaneway').on('click',  onCreateLaneway() );就会监听不到,所以外面套了个function () { },就可以了。

    3.比如你要加载完H5页面再执行逻辑,browser.WhenLoaded(StartApp());使用browser.WhenLoaded()函数,里面传Action参数,在里面可以处理写加载完页面后你想处理的事件。

    4.请求地址可以在最后面写:browser.WhenReady(SetRequestURL());使用browser.WhenReady()这个函数,里面传Action参数,在里面写请求地址。如:

    1   private Action SetRequestURL()
    2         {
    3             return delegate ()
    4             {
    5                 // 设置Url地址
    6                 browser.Url = "localGame://index.html";
    7             };
    8         }
    View Code
  • 相关阅读:
    【Selenium】Option加载用户配置,Chrom命令行参数
    Webdriver中关于driver.navigate().to()和driver.get()使用的区别
    【Selenium】idea导入eclisp项目的问题
    【数据库】数据库操作
    【monkey】
    【idea】idea快捷键
    【Selenium】Selenium1
    【Selenium】idea的selenium环境配置
    前端学习
    CSS 居中
  • 原文地址:https://www.cnblogs.com/answer-yj/p/11158092.html
Copyright © 2020-2023  润新知