zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    User Get 'Access Denied' with Excel Service WebPart
    How To Search and Restore files from Site Collection Recycle Bin
    How To Collect ULS Log from SharePoint Farm
    How To Restart timer service on all servers in farm
    How to Operate SharePoint User Alerts with PowerShell
    How to get Timer Job History
    Synchronization Service Manager
    SharePoint 2007 Full Text Searching PowerShell and CS file content with SharePoint Search
    0x80040E14 Caused by Max Url Length bug
    SharePoint 2007 User Re-created in AD with new SID issue on MySite
  • 原文地址:https://www.cnblogs.com/answer-yj/p/11158092.html
Copyright © 2011-2022 走看看