Unity3D项目导入Android Studio并利用Fragment显示

Unity3D导入AS并利用Fragment显示

  • AS显示Unity3D场景
    • Unity3D导出
      • 1.设置Player Settings
      • 2.导出项目
    • AS导入Unity3D项目
      • 1.以Module形式导入Unity3D项目
      • 2.修改Module为library
      • 3.添加依赖
      • 4.为了避免冲突及统一修改AndroidManifest
      • 5.尝试组建
    • 在AS中测试是否能够打开Unity3D场景
      • 1.在app的MainActivity中添加一个按钮跳转到Unity3D场景
      • 2.在虚拟机上运行测试
  • 在Fragment中显示Unity3D场景
    • 创建Fragment
      • 1.创建一个AFragment继承Fragment(注意为v4支持),并添加onAttach、onCreateView、onPause、onResume方法
      • 2.在app的MainActivity中创建Fragment容器,并加入AFragment
      • 3.虚拟机运行测试
    • 在Fragment中添加UnityPlayer
      • 1.在app中添加unity-classes依赖
      • 2.在MainActivity中初始化UnityPlayer
      • 3.AFragment中返回mUnityPlayer的View,并关联
      • 4.大功告成虚拟机测试
  • 可能遇到的问题
    • 1.运行时报错:No implementation found for void com.unity3d.player.UnityPlayer.nativeRestartActivityIndicator()

Unity3D导入AS并利用Fragment显示-本文较为详细介绍了,Unity3D项目导入AS,AS中显示Unity3D,利用Fragment显示Unity3D三个问题的主要过程,一些常见错误都在正文中指出,不再单独列出。

AS显示Unity3D场景

参考文章如下:
在Android(AS)中调用unity场景(view)
主要思路就是在Unity3D利用Gradle导出工程,以Module方式导入AS,再修改为library,完成功能。

Unity3D导出

1.设置Player Settings

主要设置内容为:Company Name、Product Name及Other Settings中的Package Name,至于参考文章中提到的Keystore我未做处理以及包名和AS中包名是否相同具体什么情况我不太了解,我在实践中是不相同的,目前并没有遇到问题。
主要截图如下:
Unity3D项目导入Android Studio并利用Fragment显示_第1张图片
Unity3D项目导入Android Studio并利用Fragment显示_第2张图片
Unity3D项目导入Android Studio并利用Fragment显示_第3张图片

2.导出项目

选中Gradle导出即可
导出设置如下:
Unity3D项目导入Android Studio并利用Fragment显示_第4张图片
导出后得到文件目录:
Unity3D项目导入Android Studio并利用Fragment显示_第5张图片

AS导入Unity3D项目

1.以Module形式导入Unity3D项目

Unity3D项目导入Android Studio并利用Fragment显示_第6张图片

2.修改Module为library

1.导入时在AS中两个项目独立,图标显示这样:
Unity3D项目导入Android Studio并利用Fragment显示_第7张图片
2.在build.gradle中将application修改为library
Unity3D项目导入Android Studio并利用Fragment显示_第8张图片
3.提示Sync,点击后报错,直接在build.gradle中删掉bundle()
Unity3D项目导入Android Studio并利用Fragment显示_第9张图片
4.Try Again后,再次报错,这是因为设置了两个applicationId,将Unity3D中的删除即可
报错
Unity3D项目导入Android Studio并利用Fragment显示_第10张图片
5.再次Try Again,成功,图标改变
Unity3D项目导入Android Studio并利用Fragment显示_第11张图片

3.添加依赖

这个有多种方法,我是用AS设置。
1.打开Project Structure
Unity3D项目导入Android Studio并利用Fragment显示_第12张图片
2.在app依赖中添加Module依赖
Unity3D项目导入Android Studio并利用Fragment显示_第13张图片
Unity3D项目导入Android Studio并利用Fragment显示_第14张图片
3.ok后报错(这是因为我的Unity3D项目中使用了别的库,各位自行了解),找不到这个库,我直接在app中添加这个依赖,VuforiaWrapper为aar文件,我将其复制到app的libs再依赖。
报错
Unity3D项目导入Android Studio并利用Fragment显示_第15张图片

Unity3D项目导入Android Studio并利用Fragment显示_第16张图片
4.Sync后报错,此时需要将libs加入路径,Try Again后成功
Unity3D项目导入Android Studio并利用Fragment显示_第17张图片
Unity3D项目导入Android Studio并利用Fragment显示_第18张图片

repositories {
        google()
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }

4.为了避免冲突及统一修改AndroidManifest

虽说会自动合并,但是我将所有统一写在app的AndroidManifest中
1.将Unity3D项目AndroidManifest中所有合并到app的AndroidManifest中(这里请自行设置常规设置),需要注意的是参考文章中提到的关于启动页的问题。
Unity3D项目导入Android Studio并利用Fragment显示_第19张图片
注意需要删除图中选中代码(设置启动页)
Unity3D项目导入Android Studio并利用Fragment显示_第20张图片

5.尝试组建

组建成功,说明导入完成
Unity3D项目导入Android Studio并利用Fragment显示_第21张图片

在AS中测试是否能够打开Unity3D场景

通过刚刚导出的Module可以发现Unity3D项目只是提供一个Activity,当你进入这个Activity即可显示Unity3D中的场景,至于加载Unity3D中的那个View是由Unity3D项目自己控制的,当然可以通过AS和Unity3D交互完成切换,这里不讨论。

1.在app的MainActivity中添加一个按钮跳转到Unity3D场景

1.添加按钮,按钮添加过程略去
2.利用intent跳转,发现在打入UnityPlayerActivity过程中会有提示,这是因为我们在app中注册了Unity3D项目中提供的那个Activity
Unity3D项目导入Android Studio并利用Fragment显示_第22张图片
Unity3D项目导入Android Studio并利用Fragment显示_第23张图片

2.在虚拟机上运行测试

1.点击前
Unity3D项目导入Android Studio并利用Fragment显示_第24张图片
2.点击后
Unity3D项目导入Android Studio并利用Fragment显示_第25张图片
Unity3D项目导入Android Studio并利用Fragment显示_第26张图片
3.成功完成

在Fragment中显示Unity3D场景

之前提到Unity3D项目只提供了一个Activity,在Activity中发现具体是利用UnityPlayer完成。经过网上搜索后,成功实现在Fragment中显示Unity3D场景。参考文章如下:
android的fragment中嵌套unity3d+事件控制 附带实例
android与Unity3D交互,fragment显示unity3d视图

创建Fragment

1.创建一个AFragment继承Fragment(注意为v4支持),并添加onAttach、onCreateView、onPause、onResume方法

这几个方法在控制UnityPlayer时需要用到。过程略。

2.在app的MainActivity中创建Fragment容器,并加入AFragment

1.添加容器为了便于观察控制高度为300dp
Unity3D项目导入Android Studio并利用Fragment显示_第27张图片
2.在MainActivity中实例化AFragment并添加至容器
实例化并添加

aFragment = new AFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fl_container_a,aFragment).commitAllowingStateLoss();

若报错
Unity3D项目导入Android Studio并利用Fragment显示_第28张图片
说明没有继承v4的Fragment

3.虚拟机运行测试

Unity3D项目导入Android Studio并利用Fragment显示_第29张图片
由于AFragment什么也没有添加,所以显示为空白,但运行成功说明问题不大

在Fragment中添加UnityPlayer

1.在app中添加unity-classes依赖

因为在app需要用到UnityPlayer,故需要添加依赖
1.将jar包复制到app的libs中,添加依赖
Unity3D项目导入Android Studio并利用Fragment显示_第30张图片
2.添加后Gradle为报错,但重新组建时,报错,这是因为app依赖的Unity3D项目library中同样依赖了unity-classes,故修改Unity3D中依赖方式为编译时依赖(我就这么一说)即可
Unity3D项目导入Android Studio并利用Fragment显示_第31张图片
修改依赖方式,注意去掉之前那个依赖jar包语句
Unity3D项目导入Android Studio并利用Fragment显示_第32张图片

//implementation fileTree(dir: 'libs', include: ['*.jar'])
  compileOnly files('libs/unity-classes.jar')

3.Sync后成功,重新组建后成功。

2.在MainActivity中初始化UnityPlayer

这里使用参考文章中的那个方法,使用静态变量mUnityPlayer完成
1.创建一个新类继承Activity以储存静态变量mUnityPlayer
因为Android会自动回收,推荐使用这种方式管理静态变量
Unity3D项目导入Android Studio并利用Fragment显示_第33张图片
2.在MainActivity中初始化mUnityPlayer
初始化

Constants.mUnityPlayer = new UnityPlayer(this);
int glesMode = Constants.mUnityPlayer.getSettings().getInt("gles_mode", 1);
Constants.mUnityPlayer.init(glesMode, false);

2.在MainActivity中关联mUnityPlayer的onResume、onPause、onDestroy、onConfigurationChanged、onWindowFocusChanged、dispatchKeyEvent(这些都可以在Unity3D项目中提供的UnityPlayerActivity中找到)
Unity3D项目导入Android Studio并利用Fragment显示_第34张图片
Unity3D项目导入Android Studio并利用Fragment显示_第35张图片

    @Override
    protected void onDestroy() {
        Constants.mUnityPlayer.quit();
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        Constants.mUnityPlayer.resume();
        super.onResume();
    }

    @Override
    protected void onPause() {
        Constants.mUnityPlayer.pause();
        super.onPause();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Constants.mUnityPlayer.configurationChanged(newConfig);
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        Constants.mUnityPlayer.windowFocusChanged(hasFocus);
        super.onWindowFocusChanged(hasFocus);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
            return Constants.mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
        return super.dispatchKeyEvent(event);
    }

3.AFragment中返回mUnityPlayer的View,并关联

1.在onCreateView中返回playerView,注意这里windowFocusChanged的关联(黑屏问题)
Unity3D项目导入Android Studio并利用Fragment显示_第36张图片
2.关联onResume、onPause
Unity3D项目导入Android Studio并利用Fragment显示_第37张图片

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mcontext = (Activity) context;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        playerView = Constants.mUnityPlayer.getView();
        if(playerView.getParent() != null){
            ((ViewGroup)playerView.getParent()).removeAllViews();
        }
        playerView.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
            @Override
            public void onWindowFocusChanged(boolean hasFocus) {
                Constants.mUnityPlayer.windowFocusChanged(hasFocus);
            }
        });
        return playerView;
    }

    @Override
    public void onResume() {
        Constants.mUnityPlayer.resume();
        super.onResume();
    }

    @Override
    public void onPause() {
        Constants.mUnityPlayer.pause();
        super.onPause();
    }

4.大功告成虚拟机测试

1.点击按钮前
Unity3D项目导入Android Studio并利用Fragment显示_第38张图片
2.点击按钮后退出,原因好像是因为只能有一个UnityPalyer,这不是什么大问题了,mUnitypalyer已经是静态变量了
Unity3D项目导入Android Studio并利用Fragment显示_第39张图片

可能遇到的问题

1.运行时报错:No implementation found for void com.unity3d.player.UnityPlayer.nativeRestartActivityIndicator()

具体为什么并不清楚,大体上是因为build.gradle设置的问题(大概是32和64的问题),可以尝试在app的build.gradle中加上下面代码

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'x86'
        }
    }

你可能感兴趣的:(Unity3D项目导入Android Studio并利用Fragment显示)