WebGL 內嵌網頁的一種解決方案
阿新 • • 發佈:2020-07-14
之前使用的 ZFBrowser 嵌入方案可以釋出到 Win, OS, Linux 上, 可是其它的就不行, 因為它用的谷歌核心嘛, 在 WebGL 上照理來說應該是最方便的啊, 因為它本身就是執行在瀏覽器核心上的, 前面的 BrowserInput 已經研究過向網頁注入程式碼以及呼叫了, 現在試試在 WebGL 環境下來注入程式碼, 來建立簡單的內嵌網頁看看.
Unity2017之前的方法跟 ZFBrowser 的很像, 用起來很方便, 可是以後會被禁用 :
[Obsolete("Application.ExternalEval is deprecated. See https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html for alternatives.")] public static void ExternalEval(string script); [Obsolete("Application.ExternalCall is deprecated. See https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html for alternatives.")] public static void ExternalCall(string functionName, params object[] args);
也不知道他們咋想的, 官方給的新方法是寫一個 XXX.jslib 檔案, 裡面寫的程式碼就是注入形式的程式碼, 通過[DllImport("__Internal")] 的方式引用方法, 感覺就是編譯成C++程式碼了, 先不說它效率高不高, 單是一個使用上就很蛋疼了啊, 看看一個 .jslib 檔案, 官方的 :
mergeInto(LibraryManager.library, { HelloString: function (str) { window.alert(Pointer_stringify(str)); // unity傳過來的string, 需要進行轉換才能作為瀏覽器字串 }, PrintFloatArray: function (array, size) { // 陣列還要自己傳遞長度 for(var i = 0; i < size; i++) console.log(HEAPF32[(array >> 2) + i]); //float[] 陣列, 這樣轉換夠奇葩了 }, StringReturnValueFunction: function () { var returnStr = "bla"; // 網頁字串 var bufferSize = lengthBytesUTF8(returnStr) + 1; var buffer = _malloc(bufferSize); stringToUTF8(returnStr, buffer, bufferSize); return buffer; // 傳遞給Unity的字串經過轉換才能傳遞... }, });
Unity 呼叫 :
[DllImport("__Internal")] private static extern void HelloString(string str); [DllImport("__Internal")] private static extern void PrintFloatArray(float[] array, int size); [DllImport("__Internal")] private static extern string StringReturnValueFunction(); void Start() { HelloString("This is a string."); // 傳遞string給WebGL float[] myArray = new float[10]; PrintFloatArray(myArray, myArray.Length); // 傳遞Array給WebGL, 長度也要傳... Debug.Log(StringReturnValueFunction()); // 從WebGL獲取字串 }
這樣反人類的做法, 估計是不能成事的了, Unity走了一條歪路......
不管怎樣順著來吧, 就是注入一個建立 iframe 的程式碼, 讓它能夠顯示在 Unity 的視窗範圍之內, 如果成功的話, 加上自動跟隨和縮放功能, 它就是半個嵌入式網頁了, 因為它只能實現最上層顯示, 不能像 ZFBrowser 那樣嵌入 UI 或是任意 Mesh 上顯示, 沒有真正的遮擋.