次のフォーラム投稿のコードをガイドとして使用して、AndroidアプリでUnityPlayerインスタンスをアクティブにロードする必要があるアプリに取り組んでいます:
http://forum.unity3d.com/threads/98315-Using-Unity-Android-In-a-Sub-View 。
最初、アプリケーションは「UnityActivity.Java」と呼ばれるアクティビティ内にUnityPlayerを正しく表示しています。
この問題は、ユーザーが(ハードウェアの戻るボタンを押すか、ActionBarの戻るボタンをクリックして)MainActivityに戻ってから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に2回目に移動したときに記録されます。
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);
}
これは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();
}
これは、アクティビティがマニフェストに記述されている方法です../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>
これが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>
正しい方向に向けるヒントや解決策に感謝します。
はい、簡単なことから
_W/libc(21095): pthread_create sched_setscheduler call failed: Operation not permitted
_
それについてあなたができることは何もありません。 Unity for Androidから直接コンパイルした場合でもこれが発生するため、エンジン内の問題です。
リンクしたガイドはかなり古くなっています。単純なAndroidプロジェクトを作成するために、さまざまな場所からファイルをコピーする必要がなくなりました。
Build Settings -> Android -> Google Android project
_を設定してAndroidプロジェクトを作成します新しいAndroidプロジェクトのクラスUnityPlayerNativeActivity
は、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);
}
}
_
UnityPlayerNativeActivity
はNativeActivity
を拡張しますが、私の知る限り、問題なくActionBarActivity
から拡張することもできます。少なくともそれは私の実験中にはうまくいった。
欠落している最も重要な部分は、mUnityPlayer.quit()
中のonDestroy()
の呼び出しです。古いインスタンスがまだ実行されているときにUnityPlayer
の新しいインスタンスを作成しようとすると、クラッシュ、ハングしたアクティビティ、無限の苦しみが発生します。
UnityActivity
から戻ったときにアプリ全体が単純に閉じることに驚かれる可能性があることを修正します。 mUnityPlayer.quit()
は、内部で実行されているプロセスを強制終了します。 mUnityPlayer.quit()
を呼び出した後に単一のメソッドが実行されることはなく、onDestroy()
メソッドも終了しません。
勝利への道は、_Android:process=":UnityKillsMe
_内のアクティビティにパラメーター _AndroidManifest.xml
_ を追加して、UnityActivity
を新しいプロセスとして開始することです。
あなたの場合は次のようになります
_<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>
_
パラメータ_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フォルダーに配置する必要があります。
幸運を!
質問は2年前ですが、それについての詳細なガイドを見つけるのに苦労しました。
主なアイデアは、Unityプロジェクトを取得し、それをネイティブのライブラリとして使用することですAndroid app。
このガイドがお役に立てば幸いです。
よく、私はこれに対する明確な答えはありませんが、いくつかの興味深いpsotsを見つけました
1- Androidでのpthread_create警告 について話しますW/libc(21095):pthread_create sched_setscheduler呼び出しが失敗しました:操作は許可されていません投稿で始まりますpthread_create関数を呼び出した後、次のメッセージを受け取ります:私は投稿から引用します:
このエラーは、スレッドを作成しようとしているプロセスに、指定されたスケジューリング優先順位を設定するための適切な特権がないことを意味します。
回答としてマークされた投稿には、良い情報がいくつかあります。そこを見てくださいが、コードではpthread_create()を呼び出していません-[1]
2- LogcatでのChoreographerメッセージの意味W/Choreographer(20963):保留中のvsyncイベントがすでにあります。一度に1つだけあるべきです私は引用します
Choreographerを使用すると、アプリは自身をvsyncに接続し、適切なタイミングでパフォーマンスを改善できます。
そして
はい、そうです。 Choreographerはおそらくアニメーションを処理するコンポーネントであり、十分なCPUサイクルを取得できない場合、いくつかのフレームをスキップしてこのデバッグメッセージを出力するので、これはUIのアニメーションに関連しています--- [2]
そう? [1]と[2]に基づく:Unityによって生成されたアニメーションの問題であり、ユーザーの制御下にはありません。
私自身の結論と意見は:これはUnityコードのバグであり、Unityで修正する必要がありますか?多分?
申し訳ありませんが、役に立たない場合は試してみました。 Unityで作業したことはありませんが、他の投稿から結論を得ようとしました。
幸運を
あなたはこのリンクを見ることができます
nity3dビューをAndroid activity に統合します
パブリッククラスUnityPlayerNativeActivityはNativeActivityを拡張します{protected UnityPlayer mUnityPlayer; //この変数の名前は変更しないでください。ネイティブコードから参照
// 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);
}
}