解决Unity中的mUnityPlayer.quit()方法导致一系列问题
发表于2019-01-04
如果做过Unity并且与Android打过交道的人,相信被Unity某些特性弄得没有脾气,比如说有个mUnityPlayer.quit()方法,这个方法在UnityPlayerActivity类的onDestroy方法中是这样的写的:
// Quit Unity @Override protected void onDestroy() { mUnityPlayer.quit(); super.onDestroy(); }
结果写有什么问题呢?你会发现后面的代码都不执行了,如果你是以startActivityForResult方法来启动UnityPlayerActivity的话,你会发现onActivityResult方法并不会执行。为啥呢?进到mUnityPlayer.quit()方法反编译是这样的:
public void quit() { this.k = true; if(!this.e.e()) { this.pause(); } this.a.a(); try { this.a.join(4000L); } catch (InterruptedException var1) { this.a.interrupt(); } if(this.g != null) { this.h.unregisterReceiver(this.g); } this.g = null; if(l.c()) { this.removeAllViews(); } if(i.b) { i.g.a(this.h); } this.kill(); h(); }
注意倒数第二行的this.kill()方法,不看实现可以猜出应该是杀进程的。神马?杀进程,Unity真是简单粗暴啊,怪不得你会发现该执行的都不执行了,进程都没有了后面想做的当然没法做了,不过还是再进去看下吧:
protected void kill() { Process.killProcess(Process.myPid()); }
好吧,对于这种粗暴的方式退出应用我只想对Unity说你懂不懂Android啊。说到这里,我当初就觉得没必要调用mUnityPlayer.quit()方法,直接在上面提到的onDestroy注释掉了。结果呢,这个方法真不能注释掉,如果注释掉会造成第二次启动UnityPlayerActivity的时候程序就崩溃了,而爆出的错误都是底层的错误,Java层是无法直接定位的。对于这个问题,我真是找了很久后来重新生成一个新的项目才发现这个mUnityPlayer.quit()是必须执行的。但是这个方法上面提到过会杀死进程导致后续需要释放的(解绑服务、广播等)无法执行。呵呵,答案是我把mUnityPlayer.quit()放在最后一行执行就可以了。另外我在搜索mUnityPlayer.quit()的时候还看到别人针对这个问题做了另外一种解决,就是重写UnityPlayer类的kill方法(就是上面提到的kill方法,然后再去调用自己重写的方法即可。参考地址:http://www.knowsky.com/1050011.html
重写的例子如下:
/** * Created by Xanthium on 2017/3/23. * <p> * 主要是重写父类的{@link UnityPlayer#kill}方法,因为父类的做法太粗暴了,让Activity自己去finish即可 */ public class MyUnityPlayer extends UnityPlayer { public MyUnityPlayer(ContextWrapper contextWrapper) { super(contextWrapper); } /** * 不执行父类方法 */ @Override protected void kill() { // super.kill(); } }
Activity中这样使用
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code // Setup activity layout @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); ActivityManager.putActivity(this); getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy mUnityPlayer = new MyUnityPlayer(this); setContentView(mUnityPlayer); mUnityPlayer.requestFocus(); }
补充:
然而最近在使用上面重写后又出现问题了,会导致Unity的界面无法正常显示,就没有用了!我只想说Unity真是个坑爹的玩意儿!