8

快速总结:

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

细节:

我们在 Windows 上有一个依赖 Zen Fulcrum 的嵌入式浏览器插件的工作原型,但我们希望支持 Android 设备,例如 Google DayDream、Gear VR,以及最终将在明年发布的基于 Android 的独立耳机。

以下是我目前找到的所有 Unity 网页渲染解决方案的列表:

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

Android SDK 提供了原生的WebView组件,它被渲染为一个我们无法真正挂钩的独立屏幕元素。谷歌刚刚在 Daydream 中发布了Chrome VR 浏览器的预览版,但它处于开发的早期阶段,我真的不认为他们计划在短期内为 VR 开发者提供使用的解决方案。Oculus 有实验性的Carmel 浏览器,但它似乎更专注于渲染 WebVR,而不是为 VR 开发者提供工具。我通过Oculus 网络浏览器与某人取得了联系团队(在 PAX 遇到了他,哈哈),他们计划发布一项功能,让开发人员更容易启动在 Gear VR 的内置 Oculus Web 浏览器中打开的网页。但这是一个应用切换场景,它不允许您在自己的 3D 场景中渲染网页。

我正在考虑探索的一种可能性:如果我们有一台服务器来为用户呈现网页并将该内容作为纹理数据流式传输回他们的设备会怎样?这有点像 OnLive 对视频游戏所做的,除了你有时可以容忍更多的延迟。它可以使用 Selenium(或其他一些 webdev 可视化回归测试工具)来处理渲染......嗯,这听起来很痛苦,不过,不确定我们公司是否有能力在这样的事情上花费几个月的时间。-_-

有什么建议么?谢谢!

4

2 回答 2

2

更新:我更新了repo以支持视频,它是一个基于 GeckoView 浏览器引擎的功能齐全的 3D 浏览器。它依靠 Oculus 的 OVROverlay 将 Android 插件中生成的帧渲染到 Unity3D 纹理上。

我不确定这个问题是重复的还是较新的问题,但这我制作的一个 repo,希望我们可以实现一个不错的游戏内浏览器。这有点错误/缓慢,但它可以工作(大部分时间)。

它使用 Java 插件,通过覆盖视图的方法将 Android 渲染WebView为 a ,将其转换为 png 并将其传递给 unity 。有很多工作要做,所以请随时改进它!BitmapDrawRawImage

如何使用它:

在 repo 中,您可以找到unitylibrary-debug.aar需要导入到 Assets/Plugins/Android/ 的插件 ( ) BrowserView.csUnityThread.cs您可以使用它来将 Android 转换为WebViewUnityRawImage可以显示的纹理。适当填写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;
    }
}

然后我们将 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;
    }
}
于 2018-12-02T17:38:20.157 回答
2

我四处寻找支持视频的webview 插件,而适用于 Android 的 Unity 3D webview 插件是我唯一能找到的。我已经使用了一段时间,并且会推荐它。这是一个使用它的例子:

using UnityEngine;
using Vuplex.WebView;

class SceneController : MonoBehaviour {

    // I set this in the editor to reference a webview in the scene
    public WebViewPrefab webPrefab;

    void Start() {
        webPrefab.Init(1.5f, 1.0f);
        webPrefab.Initialized += (sender, args) => {
            // load the video so the user can interact with it
            webPrefab.WebView.LoadUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
        };
    }
}
于 2019-06-03T03:46:00.210 回答