android - 将两个 Unity 项目导入 Android Studio 无法按预期工作

标签 android android-studio unity-game-engine

我目前正在接受培训,以制作使用 Unity 添加一些功能(AR、VR 等)的应用程序。目前我一直在使用 Android Studio 进行 Android 工作,一旦完成,我将在 iOS 上进行训练。

我的目标很简单:我的 MainActivity 显示两个按钮,每个按钮调用一个单独的 Unity 项目(从 Unity 导出为 Google Android 项目)来启动其场景。

为此,我将这两个 Unity 项目 Scene1Scene2 作为库导入,并通过启动它们的 Activity 来调用它们(请参阅下面的代码)。

public class MainActivity extends AppCompatActivity {

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

    public void goToUnity1(View v){
        Intent intent = new Intent(this, com.example.unityscene1.UnityPlayerActivity.class);
        startActivity(intent);
    }

    public void goToUnity2(View v){
            Intent intent = new Intent(this, com.example.unityscene2.UnityPlayerActivity.class);         
            startActivity(intent);

     }
}

及其 AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.multipleunity">

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name="com.example.unityscene1.UnityPlayerActivity"></activity>
    <activity android:name="com.example.unityscene2.UnityPlayerActivity"></activity>


</application>

Scene1Scene2 中的 UnityPlayerActivity 文件是由 Unity 生成的,因此它们很相似(这里是它们的 onCreate) > 方法):

public class UnityPlayerActivity extends 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);

        getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy

        mUnityPlayer = new UnityPlayer(this);
        setContentView(mUnityPlayer);
        mUnityPlayer.requestFocus();
    }

    ...
}

代码编译没有任何问题,应用程序启动并显示 MainActivity 及其两个按钮。当我单击第一个按钮时,它会按我的预期启动第一个 Unity 场景。但是,当我单击第二个按钮时,它还会启动第一个 Unity 场景而不是第二个。

所以我试图理解为什么会发生这种情况,到目前为止我可以说的是:

  • 我没有错误地放置两次相同的 Unity 项目
  • 在将 Scene2 转换为库之前,它本身就可以很好地工作
  • 当我单击第二个按钮时,将调用 Activity com.example.unityscene2.UnityPlayerActivity

更新

在花了几个小时研究这个问题后,我确信问题来自于我在 Google Android 项目中导出时 Unity 提供的资源名称,这些资源名称始终相同 (unity-classes.jar)。

这是我读到的内容 here :

The Android development tools merges the resources of a library project with the resources of the application project. In the case that a resource’s ID is defined several times, the tools select the resource from the application, or the library with highest priority, and discard the other resource.

除此之外,如果我有多个库,则优先级与依赖项顺序(它们在 Gradle 依赖项 block 中出现的顺序)相匹配。

因此,我尝试颠倒依赖项的顺序,将第二个 Unity 项目放在第一个项目之前,正如预期的那样,两个按钮都会启动 Unity 的第二个场景。

现在我知道了,有没有办法避免这种名称冲突?

最佳答案

我没有解决我的问题,但我设法找到一种方法来避免它:我决定制作一个更大的项目,其中包括两个不同的场景(一个使用 Vuforia AR,另一个使用一些用户界面文本)。接下来的挑战是找到一种方法,当我单击我在 Android 上设计的关联按钮时调用正确的 Unity 场景。

团结

在每个场景中,我创建了一个空对象(我将其称为 SceneManagerObject),该对象将附加脚本 GoToScene。在此脚本中将有以下方法:

private void ChangeScene(string sceneName)
{
    SceneManager.LoadScene (sceneName);
}

public void ReceiveJavaMessage(string message)
{
    if (message.Equals ("Scene1") || message.Equals ("Scene2")) 
    {
        ChangeScene (message);
    } 
    else 
    {
        Debug.Log ("The scene name is incorrect");
    }
}

第二个方法将从 Java 代码中调用。

然后我在每个场景上创建了一个 UI 按钮,单击时将调用 onClick 方法,其目的是能够返回到 Android 而不破坏 Unity Activity ,以便我们可以在 if 后恢复它我想要。为此,我创建了另一个空对象,并附加了脚本 GoBackToAndroid:

public class GoBackToAndroid : MonoBehaviour {
public string activityName; // contains the name of the activity I want to go when I quit this scene

public void onClick()
{
    callJavaMethod();
}


private void callJavaMethod()
{
    AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer);
    AnroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    jo.Call("ReceiveUnityMessage", activityName); // Will call a method in Java with activityName as parameter
}

在我将项目导出为 Google Android 项目并为下一步做好准备之后,Unity 就这样了。

Android Studio

将 Unity 项目导入为库后。我创建了三个 Activity :MainActivitySecondActivityMultipleScenesUnityActivity:

public class MultipleScenesUnityActivity extends UnityPlayerActivity {
    public static boolean unityIsRunning = false; // true if a Unity Activity is running on background


    @Override protected void onDestroy()
    {
        unityIsRunning = false;
        super.mUnityPlayer.quit();
        super.onDestroy();
    }

    @Override protected void onResume()
    {
        Intent currentIntent = getIntent();
         // If there's no Unity Activity inside the back stack
        // (meaning it just had been created)
        if (!unityIsRunning)
        {
             super.mUnityPlayer.UnitySendMessage("SceneManagerObject", "ReceiveJavaMessage", currentIntent.getStringExtra("sceneName");
        }
        unityIsRunning = true;
        super.onResume();
        super.mUnityPlayer.resume();
    }

    public void ReceiveUnityMessage (String messageFromUnity)
    {
        Intent intent;
        if (messageFromUnity.equals("MainActivity"))
        {
            intent = new Intent(this, MainActivity.class);
            startActivity(intent);
        }
        else if (messageFromUnity.equals("SecondActivity"))
        {
            intent = new Intent(this, SecondActivity.class);
            startActivity(intent);
        }
        else 
            Log.d("Test", "The activity " + messageFromUnity + " doesn't exist");
    }
}

ReceiveUnityMessage 是我们离开 Unity Activity 时调用的方法,其目的是引导我们前往我们想要前往的 Activity。

然后是MainActivity(SecondActivity遵循相同的模式):

public class MainActivity extends AppCompatActivity {

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

    public void goToActivity2(View view) // called when I click on a button
    {
        Intent intent = new Intent(this, SecondActivity.class);
        startActivity(intent);
    }

    public void goToUnity(View view) // called when I click on another button
    { 
        Intent intentUnity = new Intent(this, MultipleScenesUnityActivity.class);

        if (unityIsRunning)
        {
            intentUnity.removeExtra("sceneName"); // We have to clean the extra before putting another one otherwise we'll get always the same Unity scene

            /*  If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought
             *  to the front of its task's history stack if it is already running. */
            intentUnity.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

            /* We send a string to Unity which, when received, will change the scene.
            * This ONLY works when the Unity activity is running on background. */
            UnitySendMessage("SceneManagerObject", "ReceiveJavaMessage", "Scene1");
        }

        else
        {
            /* The intent gets a key with its String value. The value has to be the name of the Unity
            * scene and is received in UnityActivity1 when the activity starts.*/
            intentUnity.putExtra("sceneName", "Scene1");
        }
        startActivity(intentUnity);
    }
}

所以我所做的就是通过发送消息连接所有内容,以便我可以管理我想要启动的场景, Activity 也是如此。

我确信有更好的方法可以做到这一点,我仍然是一个新手,我可能会很笨拙..无论如何,我设法避免了我原来的问题,所以如果有人面临同样的问题,这个答案可能是有趣的替代方案。

关于android - 将两个 Unity 项目导入 Android Studio 无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42953597/

相关文章:

android - 样式化 ChromeCast MediaRoute 按钮

javascript - 我有一场团结一致的乒乓球比赛,进球后球永远不会停止

android - ViewPager 中的第二个 fragment 使用滚动事件

android-studio - 模拟器上的屏幕尺寸在Android Studio上太大

android - ArrayList<Object> 使用 getSerialized 问题到第二个 Activity

android - 从 IntelliJ IDEA 导入项目到 Android Studio

c# - Unity 游戏在 IOS 上崩溃,但在 Android 上运行完美

c# - 公共(public) bool 方法无法将类型 `bool' 隐式转换为 `void'

android - 什么时候在 ListView 中加载图像?

android - Facebook 应用邀请无效