WebGL 内嵌网页的一种解决方案

摘要:
以前使用的ZFBrowser嵌入方案可以发布到Win、OS和Linux,但其他人不能发布,因为它使用的是Google内核,这在WebGL上应该是最方便的,因为它运行在浏览器内核上。以前的BrowserInput已经研究了如何将代码注入和调用网页。现在尝试通过在WebGL环境中注入代码来创建简单的嵌入式网页。Unity 2017之前的方法与ZFBrowser非常相似,使用起来非常方便,但是

  之前使用的 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走了一条歪路......

  PS : 既然注入 JavaScript 这么绕, 那肯定是为了性能了, 看了一下编译方案, 频繁出现 Emscripten 这个字眼, 查了一下, 就是这个编译器, 在编辑器文件夹下也找到了

WebGL 内嵌网页的一种解决方案第1张

  不管怎样顺着来吧, 就是注入一个创建 iframe 的代码, 让它能够显示在 Unity 的窗口范围之内, 如果成功的话, 加上自动跟随和缩放功能, 它就是半个嵌入式网页了, 因为它只能实现最上层显示, 不能像 ZFBrowser 那样嵌入 UI 或是任意 Mesh 上显示, 没有真正的遮挡.

   添加一个创建 iframe 的代码 :

mergeInto(LibraryManager.library, {

    CreateIFrame: function () 
    {
        window.alert("CreateIFrame!!!");
        var div = window.document.createElement('div');    
        div.style.zIndex = "100";
        div.style.position="absolute";
        window.document.body.appendChild(div);

        var iframe = window.document.createElement('iframe');        
        iframe.style.zIndex = "1000";
        iframe.style.position="absolute";
        iframe.src = "http://XXXX/OOOO/";
        div.appendChild(iframe);
    },
  
});

  Unity 添加调用代码 :

    [DllImport("__Internal")]
    private static extern void CreateIFrame();
    
    void Start()
    {
        CreateIFrame();
    }    

 

  PS : Unity使用的是绝对位置, 反而比较方便进行坐标对齐操作.

  运行之后大概是这个样子, 正常实现了网页覆盖, 因为原本就是嵌入到Unity的网页, 网页背景是透明的 : 

WebGL 内嵌网页的一种解决方案第2张

  要做成嵌入式的感觉, 只需要根据Unity的坐标计算换算到网页, 设置 iframe 位置 / 缩放 就可以了, 没什么好说的, 不过因为没有遮挡关系, 没有什么实用价值...

免责声明:文章转载自《WebGL 内嵌网页的一种解决方案》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WPF中UI及时更新,如何在处理长时间工作时,保持界面的持续更新[Android]竖直滑动选择器WheelView的实现下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

权限认证机制

一、Form表单认证 之前的项目以MVC为主,采用的是from表单认证,Forms认证示意图如下: HTTP是一个无状态的协议,WEB服务器在处理所有传入HTTP请求时,根本就不知道某个请求是否是一个用户的第一次请求与后续请求,或者是另一个用户的请求。 WEB服务器每次在处理请求时,都会按照用户所访问的资源所对应的处理代码,从头到尾执行一遍,然后输出响应...

【Oracle/Java】以Insert ALL方式向表中插入百万条记录,耗时9分17秒

由于按一千条一插程序长期无反应,之后改为百条一插方式,运行完发现插入百万记录需要9m17s,虽然比MySQL效率差,但比单条插入已经好不少了。 对Oracle的批量插入语法不明的请参考:https://www.cnblogs.com/xiandedanteng/p/11806720.html 代码如下: package com.hy; import...

操作百度API

1 string json = ""; 2 try 3 { //虽然两者都是异步请求事件,但是WebClient是基于事件的异步,而HttpWebRequst是基于代理的异步编程 4 WebClient client = ne...

MongoDB查询报错:class com.mongodb.MongoSecurityException: Exception authenticating MongoCredential

异常日志: 2019-05-30 10:10:24,252 [http-nio-8080-exec-1] DEBUG [java.sql.Connection] -ooo Connection Opened 2019-05-30 10:10:24,258 [http-nio-8080-exec-1] DEBUG [java.sql.PreparedSta...

springboot+aop切点记录请求和响应信息

本篇主要分享的是springboot中结合aop方式来记录请求参数和响应的数据信息;这里主要讲解两种切入点方式,一种方法切入,一种注解切入;首先创建个springboot测试工程并通过maven添加如下依赖: <!-- AOP --> <dependency> <gr...

Log4net配置

一 AssemblyInfo.cs文件 [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)] 二 创建log4net.config文件 <?xml version="1.0" encoding="utf-8" ?>&...