参考文章如下:
在Android(AS)中调用unity场景(view)
主要思路就是在Unity3D利用Gradle导出工程,以Module方式导入AS,再修改为library,完成功能。
主要设置内容为:Company Name、Product Name及Other Settings中的Package Name,至于参考文章中提到的Keystore我未做处理以及包名和AS中包名是否相同具体什么情况我不太了解,我在实践中是不相同的,目前并没有遇到问题。
主要截图如下:
选中Gradle导出即可
导出设置如下:
导出后得到文件目录:
1.导入时在AS中两个项目独立,图标显示这样:
2.在build.gradle中将application修改为library
3.提示Sync,点击后报错,直接在build.gradle中删掉bundle()
4.Try Again后,再次报错,这是因为设置了两个applicationId,将Unity3D中的删除即可
5.再次Try Again,成功,图标改变
这个有多种方法,我是用AS设置。
1.打开Project Structure
2.在app依赖中添加Module依赖
3.ok后报错(这是因为我的Unity3D项目中使用了别的库,各位自行了解),找不到这个库,我直接在app中添加这个依赖,VuforiaWrapper为aar文件,我将其复制到app的libs再依赖。
4.Sync后报错,此时需要将libs加入路径,Try Again后成功
repositories {
google()
jcenter()
flatDir {
dirs 'libs'
}
}
虽说会自动合并,但是我将所有统一写在app的AndroidManifest中
1.将Unity3D项目AndroidManifest中所有合并到app的AndroidManifest中(这里请自行设置常规设置),需要注意的是参考文章中提到的关于启动页的问题。
注意需要删除图中选中代码(设置启动页)
通过刚刚导出的Module可以发现Unity3D项目只是提供一个Activity,当你进入这个Activity即可显示Unity3D中的场景,至于加载Unity3D中的那个View是由Unity3D项目自己控制的,当然可以通过AS和Unity3D交互完成切换,这里不讨论。
1.添加按钮,按钮添加过程略去
2.利用intent跳转,发现在打入UnityPlayerActivity过程中会有提示,这是因为我们在app中注册了Unity3D项目中提供的那个Activity
之前提到Unity3D项目只提供了一个Activity,在Activity中发现具体是利用UnityPlayer完成。经过网上搜索后,成功实现在Fragment中显示Unity3D场景。参考文章如下:
android的fragment中嵌套unity3d+事件控制 附带实例
android与Unity3D交互,fragment显示unity3d视图
这几个方法在控制UnityPlayer时需要用到。过程略。
1.添加容器为了便于观察控制高度为300dp
2.在MainActivity中实例化AFragment并添加至容器
aFragment = new AFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fl_container_a,aFragment).commitAllowingStateLoss();
由于AFragment什么也没有添加,所以显示为空白,但运行成功说明问题不大
因为在app需要用到UnityPlayer,故需要添加依赖
1.将jar包复制到app的libs中,添加依赖
2.添加后Gradle为报错,但重新组建时,报错,这是因为app依赖的Unity3D项目library中同样依赖了unity-classes,故修改Unity3D中依赖方式为编译时依赖(我就这么一说)即可
修改依赖方式,注意去掉之前那个依赖jar包语句
//implementation fileTree(dir: 'libs', include: ['*.jar'])
compileOnly files('libs/unity-classes.jar')
3.Sync后成功,重新组建后成功。
这里使用参考文章中的那个方法,使用静态变量mUnityPlayer完成
1.创建一个新类继承Activity以储存静态变量mUnityPlayer
因为Android会自动回收,推荐使用这种方式管理静态变量
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中找到)
@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);
}
1.在onCreateView中返回playerView,注意这里windowFocusChanged的关联(黑屏问题)
2.关联onResume、onPause
@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();
}
1.点击按钮前
2.点击按钮后退出,原因好像是因为只能有一个UnityPalyer,这不是什么大问题了,mUnitypalyer已经是静态变量了
具体为什么并不清楚,大体上是因为build.gradle设置的问题(大概是32和64的问题),可以尝试在app的build.gradle中加上下面代码
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
defaultConfig {
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
}