最近剛換了工做,新公司不是作手遊的,一開始有點抵觸,總以爲不是作遊戲本身就是跨行了,認爲本身不對口,可是慢慢發如今這能夠學的東西面很廣,因此感受又到了打怪升級的時候了,老子就在這進階了。javascript
一進公司他們使用H5開發,作一款地形信息系統的軟件,基於Unity開發,可是全部頁面都是Js寫的,因此我第一件事要作的是實現Unity嵌入網頁,並實現交互。css
在這裏,領導說以前作過相似的即用的Embedded Browser2.1.0這個插件,讓我研究下作個簡單Demo。html
使用插件Embedded Browser2.1.0實現unity與網頁交互java
1.Unity中導入插件node
2.新建Canvas,在Canvas下建立一GameObject,平鋪在Canvas上jquery
3.將網頁映射到GameObject上ajax
這一步須要給建立的BrowserGUI掛載插件腳本bootstrap
首先是Brower腳本,此腳本是設置嵌入網頁的URL以及一些幕布大小等參數,在這裏說下,有兩種嵌入方式c#
,1.能夠直接嵌入瀏覽器網頁2.能夠將html文件放入與Assets文件夾同級的BrowserAssets(必須一致,必須是這個文件夾,由於若放Assets下面,會自動默認爲代碼爲UnityScript而不是JavaScript),加載嵌入,這種方式相對快一些。瀏覽器
再一個就是掛載GUI Brower UI腳本,這腳本是構建UI的一個做用,請求的網頁會顯示出來是由於這個腳本,而且會自動添加上Raw Image組件
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; width: 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; width: 100px; line-height: 32px; position: relative; } 13 #nav div { width: 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-width: 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>
場景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>
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>
這種註冊按鈕的方式,按着我以前說的那中監聽方式會監聽不到,
如: $('#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 }