一 、前言
最近有幸接触到unity,也刚好有时间,索性就花了点时间来认识和学习unity,学了差不多一个多月吧,算是窥探到了一点点unity的门路,本想再继续往深处研究下的,但是在继续学习的过程中发现unity和Android通信稍微有点不太畅快,就是unity端和Android端要通信的的话,我觉得有两个问题比较麻烦:
1.两端代码的依赖度比较高。怎么说呢,如果你有一点unity3d基础,你就知道unity要调用Android的话,则必须确切的知道Android端具体的的类名、方法名以及方法需要的参数等信息,这样的话,每个unity项目的代码就比较定制化,扩展性不强;Android端调用unity端倒是比较简单,因为unity的sdk里封装好了对应的方法,不过还是有一点麻烦的地方就是,当要调用的unity端的方法太多差异太大的时候,就没有办法进行较好的封装,不便于维护。
2.unity编译生成的android项目里,呈现unity场景的Activity需要加入大量的代码,并且没有支持在fragment里呈现场景的示例,每次集成都需要做很多重复性工作。
为了解决在学习和使用unity的过程中遇到的这些问题,所以我就花了点时间实现了一个可以帮助android开发者快速对接unity工程的插件工程。这个插件工程支持使用Activity、Fragment、View等组件呈现unity场景,虽然谈不上什么高大上,但是接入简单,只需少量代码即可完成与unity工程的对接。具体的可以去看github的demo和unity3dplugin源码。
ps:demo依赖的unity工程有个文件超过了100M,无法上传到github,所以上传到了code.aliyun.com,没账号的童鞋注册后登录了再点击链接就可以了。
想要快速看到效果?
1.clone demo依赖的unity工程到本地,用unity编辑器导入,编译并导出为android project备用。
2.新建一个android项目,并参照android端demo和plugin源码工程里的demo,集成unity3dplugin,然后复制第一步生成的android project里src/main/assets目录里的内容到你工程的src/main/assets目录下,其他代码参照demo里的即可。
或者,直接clone demo编译运行。
关于unity3d入门,这里有一个很好的链接,大家要耐心看完:一个小时内用Unity3D制作一个小游戏
二 、实现思路
不了解unity3d与android通信的请先戳这里:Android与Unity交互研究
上面说到了这个插件主要是为了解决两个问题:一个是降低android端代码和unity端代码的耦合度,还有一个是降低android端的接入复杂度,那我们就一个一个来解决吧。
2.1 解决unity和android两端代码的依赖度比较高的问题
为了降低android端代码和unity端代码的耦合度,我分了两个方面来考虑:一个是android端提供给unity调用的入口统一化,unity所发来的所有消息都经过一个单一对象分发出去,这样的话,两端就不会再出现直接调用彼此具体的某个方法之类的了;另一个是两端通信的消息内容标准化,无论是unity3d调用android还是android调用unity3d,我都让他们传递一个ICallInfo来通信,至于具体要调用哪个类的那个方法,这些信息都封装在ICallInfo里。
2.1.1 android端提供给unity调用的单一入口——AndroidCall
public class AndroidCall {
private final String TAG = getClass().getName();
public static boolean enableLog;
private IOnUnity3DCall onUnity3DCall;
private SoftReference<Activity> hostContext;
/**
* In order to further relax the restrictions of OnUnity3DCall, let Fragment implement OnUnity3DCall can also load Unity3D view, so added {@link IGetUnity3DCall}
* interface.
*
* @param iGetUnity3DCall
*/
public AndroidCall(@NonNull IGetUnity3DCall iGetUnity3DCall) {
this.onUnity3DCall = iGetUnity3DCall.getOnUnity3DCall();
hostContext = new SoftReference<>((Activity) onUnity3DCall.gatContext());
}
public void destroy() {
if (null != hostContext) {
hostContext.clear();
}
}
protected void checkConfiguration() {
if (null == hostContext || null == hostContext.get()) {
throw new RuntimeException(getClass().getSimpleName() + " ,Invalid Context");
}
}
@Nullable
public Context getApplicationContext() {
final Context context = getContext();
return null == context ? null : context.getApplicationContext();
}
@Nullable
public Context getContext() {
return null == hostContext || null == hostContext.get() ? null : hostContext.get();
}
public voi