Android-在活动中嵌入Unity3d场景-需要取消注册接收器吗?

8

我已经是Stack Overflow的会员了一段时间,但从未提出过问题,所以现在我要问一个问题。

我的目标

我正在尝试制作一个包含两个活动的Android应用程序。第一个是菜单屏幕(使用标准的Android UI元素),其中包含一个按钮,可以打开游戏活动。游戏活动将具有一些标准的Android UI元素和一个包含Unity 3D场景的FrameLayout。

我正在使用Unity 5和Eclipse Luna。

我的成果

我已经制作了菜单屏幕,并添加了一个简单的按钮来启动第二个活动。我遵循了这个教程,成功地将我的Unity场景嵌入到我的第二个活动中。到目前为止都很好...

问题

第一次启动游戏活动时,它可以正常工作(我可以看到嵌入在FrameLayout中的Unity场景),但如果我关闭该活动(返回到菜单活动),然后再次启动游戏活动,我会收到以下错误信息...

Activity has leaked IntentReceiver com.unity3d.player.UnityPlayer$17@41866de0 that was originally registered here.  Are you missing a call to unregisterReceiver()?

我尝试过的方法

我在网上做了很多搜索,看起来我需要在onPauseonDestroy中调用类似于这样的东西;

m_UnityPlayer.currentActivity.unregisterReceiver(receiver);

...但是我不知道接收者是什么,所以我无法在unregisterReceiver调用中引用它。我尝试创建一个BroadcastReceiver,在onPause中注册并取消注册它,但没有任何区别。

我在Unity论坛上找到了一篇帖子,问的是完全相同的问题,但令人沮丧的是,它没有得到回答(Unity论坛上很多问题都没有得到回答,这就是为什么我来这里问这个问题的原因)。

我还尝试在onDestroy中调用此方法,但当我关闭游戏玩法活动时,它实际上会退出我的整个应用程序。

m_UnityPlayer.quit();

代码示例

这是我游戏活动的代码(为了清晰起见,我已删除了导入);

public class MyEmbeddedUnityActivity extends Activity {
    private UnityPlayer m_UnityPlayer;
    IntentFilter filter = new IntentFilter("");
    private BroadcastReceiver bRec = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //String action = intent.getAction();
            Log.d("", "onReceive intent: " + intent);
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_embedded_unity);

        if(m_UnityPlayer==null){
            m_UnityPlayer = new UnityPlayer(this);
            int glesMode = m_UnityPlayer.getSettings().getInt("gles_mode", 1);
            m_UnityPlayer.init(glesMode, false);

            m_UnityPlayer.currentActivity.registerReceiver(bRec, filter);

            FrameLayout layout = (FrameLayout) findViewById(R.id.my_frame);
            LayoutParams lp = new LayoutParams(200, 300);
            layout.addView(m_UnityPlayer, 0, lp);
        }

    }

    public void onWindowFocusChanged(boolean hasFocus){
        super.onWindowFocusChanged(hasFocus);
        m_UnityPlayer.windowFocusChanged(hasFocus);
    }

    @Override
    public void onDestroy (){
        //m_UnityPlayer.quit();
        m_UnityPlayer.currentActivity.unregisterReceiver(bRec);
        super.onDestroy();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig){
        super.onConfigurationChanged(newConfig);
        m_UnityPlayer.configurationChanged(newConfig);
    }

    @Override
    protected void onResume() {
        super.onResume();
        m_UnityPlayer.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        m_UnityPlayer.pause();
    }

}

最后...

我所遵循的嵌入Unity场景的步骤是在2011年编写的。整个过程(从Unity项目的暂存区提取文件并复制文件等)似乎非常不稳定和未记录

那么,有没有更好的方法使用Unity 5在Android活动中嵌入Unity场景呢?毕竟,在现有应用程序中添加Unity场景是一件相当普遍的事情,对吧?

谢谢,任何帮助都将不胜感激!


1
不幸的是,将Unity3D添加到现有应用程序并不是一项常见任务。如果您只需要一个启动屏幕,请考虑使用Unity UI系统来制作它。 - Andrey Kuznetsov
感谢您的输入,安德烈。我确实考虑过使用Unity UI组件,但我很想找到一种使用本地Android UI的方法。正如您在下面看到的,我已经找到了我要寻找的答案。 - gts101
1个回答

11

所以,我进行了更多的搜索,最终在SO上找到了答案!

此答案所述,将此行添加到清单中即可解决问题;

android:process=":UnityKillsMe"

所以清单的相关部分应该是这样的:

...

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name=".Studio"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:process=":UnityKillsMe"
        android:label="@string/title_activity_home" > 
    </activity>

...

这会强制使游戏活动在一个单独的进程中启动。这意味着您可以在活动的onDestroy方法中调用m_UnityPlayer.quit(),而不会导致整个应用程序关闭。

这是一个简单的修复方法,但令人恼火的是它似乎完全没有记录。

希望这能帮助到某些人!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接