从进入目前公司的第一个项目起,到现在反反复复一共做了有四个项目,每一个都是需要对接U3D的,从一开始用百度来的最基础的方式对接U3D和到后来为了加快启动U3D进出速度而采用singleInstance的方式,和到现在给Unity一个独立进程,尽可能使在Unity里的交互更加顺畅,每一个项目都在不断优化,尝试把它做得更好,后面还会有优化的方向吗?我觉得插件化是一个方向,最大限度地和当前工程解耦,当然U3D里面有很多东西,和普通的插件化不一样,里面还是有很多坑的。好了,废话就到这里了,接下来进入正题。。。
一,U3D工程导入
快速导入
1.解压U3D资源包;
2.在AS项目工程中选择File-->new-->import module,导入U3D输出的Android工程构建;
3.导入完成后打开U3D module目录下的build.gradle文件,将
applyplugin:'com.android.application'
修改为
applyplugin:'com.android.library'
修改完成后删除或注释掉defaultConfig;
// defaultConfig {
// applicationId "com.wangong.MRDecorate"
// minSdkVersion 19
// targetSdkVersion 23
// }
4.打开U3D module main目录下的manifest文件,将头部
修改为
5.将Application头部
修改为
6.去掉U3D入口Activity的的配置:
去掉前:
去掉后:
手动导入
新建一个module,将U3D导出工程对应目录下的资源手动复制到module对应的资源目录下即可(Unity默认导出是eclipse结构的Android工程,Unity5.6以后可选Gradle的工程)。
二,创建一个用于显示Unity的Activity主界面
1,继承自UnityPlayerActivity,注意是继承自如下图这个activity;
2,注意manifest中修改为自己的activity,如Unity中接入了第三方如暴风墨镜等,需继承自MojingActivity,这就是实际情况而定了。
三,Android与U3D相互调用方法
1,U3D调用Android方法;
在自己创建的UnityActivity中定义一个方法:
public void goToLogin(){
runOnUiThread(new Runnable() {
@Override
public void run() {
//跳转登录页面
}
});
}
在U3D中调用:
//获取Android的Java接口
AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo=jc.GetStatic("currentActivity");
//调用无参goToLogin方法
jo.Call("goToLogin");
//调用单个参数的方法
jo.Call("MethodName","param1")
//调用多个参数的方法
string[] mObject=new string[2];
mObject[0]="param1";
mObject[1]="param2";
jo.Call("MethodName",mObject)
//或者:
jo.Call("MethodName","param1", "param2");
//调用带有返回值的方法
jo.Call("MethodName");
//调用静态方法
jo.CallStatic("StaticMethodName");
//调用带返回值的静态方法
jo.CallStatic("StaticMethodName");
2.Android调用U3D方法;
在U3D中创建一个脚本并挂载到对应游戏对象(GameCenter)上,如下所示:
void Login(String userId)
{
//登录
}
在Android中调用:
UnityPlayer.UnitySendMessage("GameCenter", "Login", "userId");
GameCenter为脚本挂载到的游戏对象名,Login为方法名,userId为传递的参数
注意这里只能传递一个参数,如需传递多个参数可以采用字符串拼接或json字符串等其他方式传递
四, 进出U3D优化
1,修改UnityActivity启动模式为singleInstance,由于singleInstance是一个独立任务栈,第一次启动后UnityActivity后就不finish,而是直接用Intent跳出来,下次进入U3D启动就会非常快了,由于singleInstance的特殊性,有时候在U3D中跳转App的页面又要切换回来,这时可以在UnityActivity中定义两个标志位,在进入UnityActivity的前一个界面的onstart中去判断要不要恢复UnityActivity界面;
2,UnityActivity创建为独立进程,这时候标志位放到了App主页,采用了动态广播的方式去更新标志位,App退出时会广播通知Unity进程退出;
3,退出U3D到App界面问题,由于很多地方都可以进U3D,所以单进程时直接用AppManagerUtil获取上一个activity跳转出去,多进程时进入UnityActivity时会传入Activity名称,直接使用反射跳出去。
五, Unity方法一览
1.public static void UnitySendMessage(String var0, String var1, String var2);
//java调用U3D中提供的方法
2.public void quit();//退出U3D的方法
3.public void Call(string methodName, params object[] args);
//U3D调用Android无返回值的方法
4.public ReturnType Call
//U3D调用Android有返回值的方法
5.public void CallStatic(string methodName, params object[] args);
//U3D调用Android无返回值的静态方法
6.public ReturnType CallStatic
//U3D调用Android有返回值的静态方法
六, 注意事项
1.Android中方法必须为public的;
2.如果没有导入x86的.so库是无法在模拟器上运行的;
3.使用了第三方的VR,比如暴风魔镜的VR,需继承第三方提供的Activity,并且无法在模拟器上运行,第三方的VR部分手机硬件不支持,进入U3D时会直接崩溃;
4.实际项目中最好先在项目工程下创建好对应目录U3D的module,然后将相关资源复制过来,保持项目module配置结构的一致性,方便后期维护;
5,通常unity module结构整理好后不用怎么修改,在U3D不增加新的第三方库的情况下,只需要更新asssets->bin->data下的脚本文件即可,这里有一个小技巧,可以给unity module创建一个独立git仓库,让unity开发人员负责更新;
6,一开始启动U3D的白屏或黑屏页可以配置一下UnityActivity的Theme,可以加一张启动背景图;
7,目前遇到的坑,谷歌的ARCode的aar包必须放在主模块下(启动模块),U3D使用的一个播放视频的第三方EasyMovieTexture,视频资源必须放在主模块的assets目录下,不然会找不到资源。
七、参考文献
http://www.2cto.com/kf/201507/414027.html