在Android上的Unity3D中将网站渲染为纹理

Liv*_*ruz 7 browser android unity-game-engine daydream google-vr

快速摘要:

我正在开发一个VR应用程序,我们想在VR场景中的3D空间中渲染一个网站,最好是在一个纹理上。有许多方法可以在台式机(PC / Mac)上完成此操作,而在Android设备上则没有。

细节:

我们在Windows上有一个可用的原型,该原型依赖Zen Fulcrum的Embedded Browser插件,但我们希望支持Android设备,例如Google DayDream,Gear VR,以及最终将在明年发布的基于Android的独立耳机。

这是到目前为止我发现的所有Unity网页渲染解决方案的列表:

  • Zen Fulcrum的嵌入式浏览器 -支持Windows和OSX
  • Yumigi的UniWebView-它们不支持将网页渲染为纹理。网页在图形引擎渲染之上的平坦层上渲染。
  • Piotr Zmudzinski开发的应用程序内Web浏览器 -似乎具有相同的限制
  • Chestnut Games的iOS Webkit-仅适用于iOS,其公司网站似乎无法正常运行。
  • ZHing的NGUI和Unity GUIHTML引擎 -似乎不是真正的Web浏览器。似乎有人制作了一些脚本,将HTML转换为UI元素。
  • JaeYunLee撰写的适用于Android的EasyWebViewTexture-我知道一些使用过此功能的开发人员,但该项目被神秘地取消并终止。
  • Khrona Software 撰写的Unity Awesomium- Unity的Wiki文章在其Wiki网站GitHub上都是空白。在整个awesomium网站已被关闭为好,所以有Krhona软件公司的网站。他们有一个Unity集成的GitHub Repo,但自述文件说它仅支持Windows和Mac。
  • Mythos Labs的uWebKit3-不再可用。他们原来的网站已不存在。uWebKit的早期版本声称支持Android。他们在Unity论坛上宣布关闭他们的消息非常神秘而突然。我在GitHub上找到了一些声称是uWebKit3的东西,但是自述文件声称只支持PC和Mac。
  • 虚幻引擎4的Web浏览器小部件 -这是UE4中内置的实验性小部件,在桌面上,它可以在3D世界中呈现几乎没有问题的网页。不幸的是,即使它声称支持Android,但当您实际部署到设备上时,您会发现浏览器只是在游戏引擎渲染之上而不是在3D世界中渲染。

我真的找不到任何信息,说明过去为什么不再支持Android。也许Android堆栈发生了变化?如果我想自己弄乱Chromium并使其在Android上运行,我是否会遇到死胡同杀死了所有这些项目?

Android SDK提供了本地WebView组件,该组件呈现为我们无法真正融入的独立屏幕元素。谷歌刚刚在Daydream中发布了Chrome VR浏览器的预览版,但是它还处于开发初期,我真的不认为他们打算为VR开发人员提供一个解决方案,以供其很快使用。Oculus拥有试验性的Carmel浏览器,但它似乎更专注于呈现WebVR,而不是为VR开发人员提供工具。我一直在与来自Oculus Web浏览器的人保持联系团队(在PAX见到他,大声笑),他们计划发布一项功能,使开发人员可以更轻松地启动在Gear VR的内置Oculus Web浏览器中打开的网页。但这是应用程序切换的情况,它不允许您在自己的3D场景中渲染网页。

我正在考虑探索的一种可能性:如果我们拥有一台服务器来为用户呈现网页并将该内容作为纹理数据流回其设备,该怎么办?有点像OnLive对视频游戏所做的事情,只是您有时可以忍受更多的延迟。它可以使用Selenium(或其他Webdev可视化回归测试工具)来处理渲染……嗯,这听起来很麻烦,尽管不确定我们的公司是否有能力花数月时间来做类似的事情。-_-

有什么建议么?谢谢!

pal*_*one 3

UPDATE: I updated the repo to support video and is a fully functioning 3D browser based on the GeckoView browser engine. It relies on the OVROverlay from Oculus to render frames generated in an Android plugin onto a Unity3D texture.

I'm not sure if this question is a duplicate or the newer one is, but this is a repo I made in the hopes we can implement a nice in-game browser. It's a bit buggy/slow but it works (most of the time).

It uses a Java plugin that renders an Android WebView to a Bitmap by overriding the view's Draw method, converts that to a png and passes it to a unity RawImage. There is plenty of work to do so feel free to improve it!

How to use it:

unitylibrary-debug.aar在存储库中,您可以找到需要导入到 Assets/Plugins/Android/ 的插件 ( ) BrowserView.csUnityThread.cs您可以使用该插件将 Android 转换WebView为 Unity 可以显示的纹理RawImage。适当填写BrowserView.cs的公共字段。确保 Unity 播放器设置中的 API 级别设置为 25。

代码示例

这里重写 的WebView方法Draw来创建位图和 PNG,并初始化您需要的变量:

public class BitmapWebView extends WebView{

    private void init(){
        stream = new ByteArrayOutputStream();
        array = new ReadData(new byte[]{});
        bm = Bitmap.createBitmap(outputWindowWidth,
             outputWindowHeight, Bitmap.Config.ARGB_8888);
        bmCanvas = new Canvas(bm);
   }


    @Override
    public void draw( Canvas ){
        // draw onto a new canvas  
        super.draw(bmCanvas);
        bm.compress(Bitmap.CompressFormat.PNG, 100, stream);

        array.Buffer = stream.toByteArray();
        UnityBitmapCallback.onFrameUpdate(array,
            bm.getWidth(),
            bm.getHeight(),
            canGoBack,
            canGoForward );
        stream.reset();

    }
}  
// you need this class to communicate properly with unity
public class ReadData {
    public byte[] Buffer;
    public ReadData(byte[] buffer) {
        Buffer=buffer;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们将 png 传递给 unity RawImage。这是 Unity 接收方:

// class used for the callback with the texture
class AndroidBitmapPluginCallback : AndroidJavaProxy
{
    public AndroidBitmapPluginCallback() : base("com.unityexport.ian.unitylibrary.PluginInterfaceBitmap") { }
    public BrowserView BrowserView;

    public void onFrameUpdate(AndroidJavaObject jo, int width, int height, bool canGoBack, bool canGoForward)
        {
        AndroidJavaObject bufferObject = jo.Get<AndroidJavaObject>("Buffer");
        byte[] bytes = AndroidJNIHelper.ConvertFromJNIArray<byte[]>(bufferObject.GetRawObject());
        if (bytes == null)
            return;
        if (BrowserView != null)
        {
            UnityThread.executeInUpdate(()=> BrowserView.SetTexture(bytes,width,height,canGoBack,canGoForward));
        }
        else
            Debug.Log("TestAndroidPlugin is not set");

    }
 }


public class BrowserView : MonoBehaviour {
// Browser view needs a RawImage component to display webpages


   void Start () {
        _imageTexture2D = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, false);
        _rawImage = gameObject.GetComponent<RawImage>();
        _rawImage.texture = _imageTexture2D;

        #if !UNITY_EDITOR && UNITY_ANDROID
        // Get your Java class and create a new instance
        var tempAjc = new AndroidJavaClass("YOUR_LIBRARY.YOUR_CLASS")
        _ajc = tempAjc.CallStatic<AndroidJavaObject>("CreateInstance"); 
        // send the callback object to java to get frame updates
        AndroidBitmapPluginCallback androidPluginCallback = new AndroidBitmapPluginCallback {BrowserView = this};
        _ajc.Call("SetUnityBitmapCallback", androidPluginCallback);
        #endif

    }
   // Android callback to change our browser view texture
    public void SetTexture( byte[] bytes, int width, int height, bool canGoBack, bool canGoForward)
    {

        if (width != _imageTexture2D.width || height != _imageTexture2D.height)
            _imageTexture2D = new Texture2D(width, height, TextureFormat.ARGB32, false);

        _imageTexture2D.LoadImage(bytes);
        _imageTexture2D.Apply();
        _rawImage.texture = _imageTexture2D;
    }
}
Run Code Online (Sandbox Code Playgroud)