解决Unity中的mUnityPlayer.quit()方法导致一系列问题

发表于2019-01-04
评论0 6.4k浏览
如果做过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真是个坑爹的玩意儿!

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引