版本信息

特别说明

  • 这篇文章意图
  • 本文章重点
  • 建议参考
  • 代码部分
  • 目录结构
  • Java不继承UniWebView Activity如何使用
  • 原作者说明
  • AndroidManifestxml
  • 关键点修改UniWebViewcs
  • 华为虚拟按键
  • 界面自适应缩放
  • AndroidPluginjava
  • UniWebViewDialogjava
  • UniWeb ViewPluginAndroidcs
  • UniWebViewcs
  • 重点
  • 结合NGUI适应页面
  • 边距
  • 简单的pixel转point
  • 结合NGUI使用

版本信息

  • Unity 5.4.2p3
  • Native Plugin UniWebView 2.7.1

特别说明

这篇文章意图

  • 发现最近很火游戏里面嵌入网页,大家都在问这玩意怎么搞
  • 一般如何接入的文章倒是巨多,但是很多缺陷问题,却没人解决,于是就总结下自己的使用
  • 博主比较懒,因此Mac版的一直没去弄,感觉也没太大意义(其实主要是因为运行就error,懒得去fix),哪天心情比较好再考虑去搞吧

本文章重点

  1. 解决在Java中必须继承UniWebViewActivity的缺陷
  2. 解决一些网页浏览适配的问题
  3. 结合NGUI设置页面大小

建议参考

  • Unity3D使用Native Plugins(快速便捷接入SDK) —— C#篇
  • Unity3D使用Native Plugins(快速便捷接入SDK) —— Java篇

代码部分

目录结构

unity模型如何加载到网页上 unity嵌入到网页_#if

- UniWebView目录结构就如图了

Java不继承UniWebView Activity如何使用

原作者说明

By default, Unity is using an activity called UnityPlayerActivity in Android as the main activity. UniWebView needs to run in its own activity as the main activity avoid some potential issues such as input handler or background switch. The activity which UniWebView is using by default is a subclass of UnityPlayerActivity, so it will not break anything of origin Unity. But sometimes you have to let other plugin’s activity to run as the main activity. Fortunately, UniWebView is shipped with original source code for Android, so you can modify the source code and recompile it as you need. This guide will show you how to do it.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Web.UniWebView" >
</manifest>
  • 不要诧异什么都没有配置,因为这玩意真的不需要

关键点,修改UniWebView.cs

#if UNITY_ANDROID
    private void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            Hide();
        }
        else
        {
            Show();
        }
    }
#endif
  • 如果不继承的话,锁屏或者切界面的时候,有可能会导致原来WebView对Unity界面的触摸拦截失效
  • 其实这样子很好处理,既然是在锁屏或者且界面的时候出现的问题,那就在这个时候做些特殊处理
  • 其实就像一个堆栈,Unity弹出来前,WebView先弹出来,Unity入栈了,WebView就跟着入栈,保证WebView在Unity上面,就这么简单几句就可以了
  • 如果有些项目有些特殊需求,具体问题具体分析吧,至少我们项目足够处理了

华为虚拟按键

/// <summary>
    /// Get or set a value indicating whether this <see cref="UniWebView"/> is in immersive mode.
    /// </summary>
    /// <value><c>true</c> if immersive mode; otherwise, <c>false</c>.</value>
    /// <description>
    ///
    /// </description>
    public bool immersiveMode {
        get {
            return _immersiveMode;
        }
        set {
            #if UNITY_ANDROID && !UNITY_EDITOR
            _immersiveMode = value;
            UniWebViewPlugin.SetImmersiveModeEnabled(gameObject.name, _immersiveMode);
            #endif
        }
    }
  • Unity默认是显示虚拟按键的
  • UniWebView默认是不显示虚拟按键的,所以这里再初始化的时候需要设置为false

界面自适应缩放

AndroidPlugin.java

public static void _UniWebViewReload(String name)
  {
    runSafelyOnUiThread(new Runnable(name)
    {
      public void run() {
        Log.d("UniWebView", "_UniWebViewReload");
        UniWebViewDialog dialog = UniWebViewManager.Instance().getUniWebViewDialog(AndroidPlugin.this);
        if (dialog != null)
          dialog.reload();
      }
    });
  }

UniWebViewDialog.java

public void loadWithOverviewMode(boolean use) {
    this._uniWebView.getSettings().setLoadWithOverviewMode(use);
  }

UniWeb ViewPluginAndroid.cs

public static void SetUseLoadWithOverviewMode(string name, bool use)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            webView.CallStatic("_UniWebViewLoadWithOverviewMode", name, use);
        }
    }

UniWebView.cs

public void SetUseLoadWithOverviewMode(bool use)
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        UniWebViewPlugin.SetUseLoadWithOverviewMode(gameObject.name, use);
#endif
    }

重点

  • 在Java层增添了一个接口,在初始化的时候设置为true
  • 这需要重新编译UniWebView的java源码,然后在导出jar
  • 虽然原作者是在Mac下操作生成jar的,但是在Eclipse上生成完全没有问题,问题基本是Min SDK或者是Target SDK问题吧,博主手残删了自己的Eclipse工程,所以下次要用到我再更新博客吧(我好懒,yeah)

结合NGUI适应页面

边距

/// <summary>
    /// Get the height of the screen.
    /// </summary>
    /// <value>
    /// The height of screen.
    /// </value>
    /// <description>
    /// In iOS devices, it will always return the screen width in "point", 
    /// instead of "pixel". It would be useful to use this value to calculate webview size.
    /// On other platforms, it will just return Unity's Screen.height.
    /// For example, a portrait iPhone 5 will return 320 and a landscape one 568. You should 
    /// always use this value to do screen-size-based insets calculation.
    /// </description>
    public static int screenWidth {
        get {
 #if UNITY_IOS && !UNITY_EDITOR
            return UniWebViewPlugin.ScreenWidth();
 #else
            return Screen.width;
 #endif
        }
    }
  • 看说明,在iOS上,使用的并不是像素,而是边距,因此我们在所有的计算上,都应该进行一个转换

简单的”pixel”转”point”

public static int ConvertPixelToPoint(float pixel, bool width)
    {
#if UNITY_IOS && !UNITY_EDITOR
        float scale = 0;
        if (width)
        {
            scale = 1f * screenWidth / Screen.width;
        }
        else
        {
            scale = 1f * screenHeight / Screen.height;
        }

        return (int)(pixel * scale);
#endif

        return (int)pixel;
    }
}
  • 很简单的写法,在iOS上转换一下,根据比例

结合NGUI使用

using UnityEngine;

public static class UniWebViewExtHelper
{
    public static UniWebView CreateUniWebView(UIWidget widget, string url)
    {
        if (widget == null || !widget.isActiveAndEnabled)
        {
            return null;
        }

        // 强制刷新一遍
        widget.ResetAndUpdateAnchors();
        var camera = widget.anchorCamera;
        var bottomLeft = camera.WorldToScreenPoint(widget.worldCorners[0]);
        var topRight = camera.WorldToScreenPoint(widget.worldCorners[2]);

        return CreateUniWebView(widget.gameObject, url, Screen.height - topRight.y, bottomLeft.x, bottomLeft.y, Screen.width - topRight.x);
    }


    public static UniWebView CreateUniWebView(GameObject go, string url, float top, float left, float bottom, float right)
    {
        if (go == null || !go.activeSelf)
        {
            return null;
        }

        var view = go.GetComponent<UniWebView>();
        if (view == null)
        {
            view = go.AddComponent<UniWebView>();
        }

        view.insets = new UniWebViewEdgeInsets(UniWebViewHelper.ConvertPixelToPoint(top, false), UniWebViewHelper.ConvertPixelToPoint(left, true), UniWebViewHelper.ConvertPixelToPoint(bottom, false), UniWebViewHelper.ConvertPixelToPoint(right, true));
        view.SetShowSpinnerWhenLoading(false);
        view.immersiveMode = false;
        view.url = url;

        return view;
    }
}
  1. 为了防止Widget的大小还会变,强制刷新一遍
  2. 获取Widget在屏幕中的位置,算出距离边的像素距离
  3. 换成point距离,然后初始化