IAE*_*IAE 16 android unity-game-engine android-activity
我正在开发一个需要在活动中加载UnityPlayer实例的Android应用程序,使用以下论坛帖子中的代码作为指南:
http://forum.unity3d.com/threads/98315-Using-Unity-Android-In-a-Sub-View.
最初,应用程序在名为"UnityActivity.java"的活动中正确显示UnityPlayer.
当用户导航回MainActivity(通过按下硬件后退按钮或单击ActionBar后退按钮)然后尝试重新打开UnityActivity时会出现问题 - 在这种情况下会显示黑屏而不是UnityPlayer.论坛中的用户建议将onPause和onResume生命周期事件转发给UnityPlayer,如下面的代码所示.但是,在执行此操作时,会显示以下错误并且应用程序崩溃.
首次导航到UnityActivity时会记录此信息:
W/libc(21095): pthread_create sched_setscheduler call failed: Operation not permitted
单击后退按钮时会记录此错误:
W/Choreographer(20963): Already have a pending vsync event. There should only be one at a time.
第二次导航到UnityActivity时会记录此错误:
A/libc(21095): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 21176 (Thread-5073)
......此时我被踢出了申请表.
这是主要活动的摘录MainActivity.java
:
public void startUnityActivity(View view) {
Intent intent = new Intent(this, UnityActivity.class);
startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)
这是Unity活动的摘录UnityActivity.java
:
public class UnityActivity extends ActionBarActivity {
UnityPlayer m_UnityPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_unity);
m_UnityPlayer = new UnityPlayer(this);
int glesMode = m_UnityPlayer.getSettings().getInt("gles_mode", 1);
m_UnityPlayer.init(glesMode, false);
FrameLayout layout = (FrameLayout) findViewById(R.id.unityView);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
layout.addView(m_UnityPlayer, 0, lp);
m_UnityPlayer.windowFocusChanged(true);
m_UnityPlayer.resume();
}
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
m_UnityPlayer.windowFocusChanged(hasFocus);
}
@Override
public void onPause() {
super.onPause();
m_UnityPlayer.pause();
}
@Override
public void onResume() {
super.onResume();
m_UnityPlayer.resume();
}
Run Code Online (Sandbox Code Playgroud)
这是清单中描述活动的方式../AndroidManifest.xml
:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.package.example.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.package.example.UnityActivity"
android:label="@string/title_activity_unity"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:parentActivityName="com.package.example.MainActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
</activity>
</application>
Run Code Online (Sandbox Code Playgroud)
这就是如何定义UnityActivity的布局../res/layout/activity_unity.xml
:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.package.example.UnityActivity"
tools:ignore="MergeRootFrame" >
<FrameLayout
android:id="@+id/unityView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</FrameLayout>
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)
我会感谢任何提示和解决方案指向我正确的方向.
Ste*_*ann 28
好的,首先是简单的事情
W/libc(21095): pthread_create sched_setscheduler call failed: Operation not permitted
Run Code Online (Sandbox Code Playgroud)
你无能为力.当你直接从Unity for Android编译时,你甚至会得到这个,所以这是引擎内部的一个问题.
您链接的指南已经过时了.您不再需要从各个位置复制文件来创建简单的Android项目.
Build Settings -> Android -> Google Android project
UnityPlayerNativeActivity
新Android项目中的课程向您展示如何设置UnityPlayer
以及需要转发的事件.这是Unity 4.3.4使用的版本
package de.leosori.NativeAndroid;
import com.unity3d.player.*;
import android.app.NativeActivity;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
public class UnityPlayerNativeActivity extends NativeActivity
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// UnityPlayer.init() should be called before attaching the view to a layout - it will load the native code.
// UnityPlayer.quit() should be the last thing called - it will unload the native code.
protected void onCreate (Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
getWindow().takeSurface(null);
setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
getWindow().setFormat(PixelFormat.RGB_565);
mUnityPlayer = new UnityPlayer(this);
if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
int glesMode = mUnityPlayer.getSettings().getInt("gles_mode", 1);
boolean trueColor8888 = false;
mUnityPlayer.init(glesMode, trueColor8888);
View playerView = mUnityPlayer.getView();
setContentView(playerView);
playerView.requestFocus();
}
protected void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
}
// onPause()/onResume() must be sent to UnityPlayer to enable pause and resource recreation on resume.
protected void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
protected void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.onKeyMultiple(event.getKeyCode(), event.getRepeatCount(), event);
return super.dispatchKeyEvent(event);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然我可以说UnityPlayerNativeActivity
延伸NativeActivity
你仍然可以延伸ActionBarActivity
而不是任何问题.至少它在我的实验中起作用了.
你缺少的最重要的部分是对mUnityPlayer.quit()
期间的呼唤onDestroy()
.试图创建一个新的实例,UnityPlayer
而旧的实例仍在运行将导致崩溃,悬挂活动和无尽的痛苦.
修复你可能会感到惊讶,现在你的整个应用程序只是在你从你的回来时关闭UnityActivity
.mUnityPlayer.quit()
将杀死它在里面运行的进程.调用后没有一个方法会执行mUnityPlayer.quit()
,甚至onDestroy()
方法都不会完成.
获胜的途径是UnityActivity
通过将参数添加android:process=":UnityKillsMe
到您的活动中来启动您的新流程AndroidManifest.xml
.
在你的情况下,它看起来像这样
<activity
android:name="com.package.example.UnityActivity"
android:label="@string/title_activity_unity"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:process=":UnityKillsMe"
android:parentActivityName="com.package.example.MainActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>
Run Code Online (Sandbox Code Playgroud)
我不确定参数unityplayer.ForwardNativeEventsToDalvik
...在开头创建的项目设置它false
和官方(过时的)文档提到
由于触摸/运动事件是在本机代码中处理的,因此Java视图通常不会看到这些事件.但是,Unity中存在一种转发机制,允许将事件传播到DalvikVM.
在我的小示例项目中,我看不出有什么区别
您需要找到一个工作流程,将您的开发与Unity集成到Android项目中,反之亦然.使用Unity再次导出会与您在Android项目中所做的更改发生冲突,因此您需要导出到单独的文件夹并从Android项目链接到Unity部分.
根据上述文档,您可以将已编译的Android类和AndroidManifest.xml
插件集成到Unity中.
生成的.class文件应压缩为.jar文件并放在Assets-> Plugins-> Android文件夹中.由于清单指示要启动哪个活动,因此还需要创建新的AndroidManifest.xml.AndroidManifest.xml文件也应该放在Assets-> Plugins-> Android文件夹中.
祝好运!