[英]Importing a Unity3D Scene into an Android fragment
我在網上搜索過類似的問題,雖然我發現了幾個類似的問題,但沒有一個可靠的答案,這就是我在這里發帖的原因。
當Unity3D項目為Android編譯時,它基本上只是將場景作為一個你可以開始/結束/等的Activity。 我想將此活動更改為片段,以便將其顯示為導航抽屜中的選項卡,以及另一個片段/活動中的子視圖。
所以基本上我有一個帶有打開按鈕的MainActivity
和一個UnityPlayerNativeActivity
,它是實際的 Unity3D 項目。
我搜索了如何將一般活動更改為片段,並將UnityPlayerNativeActivity
更改為匹配。 例如,在下面新命名的UnityPlayerNativeFragment
中(注釋反映了與之前的確切更改):
import com.unity3d.player.UnityPlayer;
// Other imports available in full code linked to below
public class UnityPlayerNativeFragment extends Fragment
{
// Changes in this class:
// 1- 'this' references changed to "getActivity()"
// 2- onCreate -> onCreateView
// 3- protected -> public in function names
// 4- @Override added before function calls
// 5- newInstance and onAttach added
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
private static final String ARG_SECTION_NUMBER = "section_number";
public static UnityPlayerNativeFragment newInstance(int sectionNumber) {
UnityPlayerNativeFragment fragment = new UnityPlayerNativeFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((HomeActivity) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
}
// 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.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
//below line removed because it was causing errors
//getActivity().requestWindowFeature(Window.FEATURE_NO_TITLE);
getActivity().getWindow().takeSurface(null);
getActivity().setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);
getActivity().getWindow().setFormat(PixelFormat.RGB_565);
mUnityPlayer = new UnityPlayer(getActivity());
if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
getActivity().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();
return playerView;
}
@Override
public void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
}
// onPause()/onResume() must be sent to UnityPlayer to enable pause and resource recreation on resume.
@Override
public void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
@Override
public void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
}
AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.SamerBekhazi.Test" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/AppTheme" android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:launchMode="singleTask" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="portrait" android:name=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>
</application>
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-feature android:glEsVersion="0x00020000" />
</manifest>
我只在這里包含了這 2 個文件,因為我認為問題出在其中一個。 完整代碼可在此處下載。 提取/導入到 Android Studio - 您可能需要按一次Sync Project with Gradle Files
才能使其工作。
該項目的其余部分基於 Android Studio 在創建新項目時自動為您創建的Navigation Drawer Activity
項目。 我基本上只是在NavigationDrawer
按下其相應的圖標時調用上述UnityPlayerNativeFragment
的newInstance
。
當我按下場景的選項卡時會產生什么結果:黑屏,操作欄仍然顯示,但沒有其他內容。 右上角的“設置”按鈕仍然可以按下,導航抽屜按鈕也是如此,但是當按下導航抽屜上的另一個選項卡時,整個應用程序會凍結,您必須強制退出。 我認為后一個問題是因為您無法關閉未正確打開的UnityPlayer
,因此主要問題實際上是使UnityPlayer
在 Fragment 中正確打開。 應用程序的其余部分(其他選項卡)工作正常。 我在上面的代碼和AndroidManifest.xml
文件中嘗試了幾種變體(我能想到的一切),但沒有任何效果。
Logcat 沒有顯示任何錯誤,它只是說:
11-11 21:22:19.681 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libmain.so has text relocations. This is wasting memory and is a security risk. Please fix.
11-11 21:22:19.681 29280-29280/com.Bekhazi.Bouncy_Ball D/dalvikvm﹕ Added shared lib /data/app-lib/com.Bekhazi.Bouncy_Ball-2/libmain.so 0x42d64cd8
11-11 21:22:19.691 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libmono.so has text relocations. This is wasting memory and is a security risk. Please fix.
11-11 21:22:19.691 29280-29280/com.Bekhazi.Bouncy_Ball W/linker﹕ libunity.so has text relocations. This is wasting memory and is a security risk. Please fix.
這里究竟有什么問題? 目標版本適用於 Android 5.0,我使用的是 Android Studio 0.8.14。 值得注意的是:當它是一個 Activity 時,我能夠成功地將場景加載到我的 Nexus 5 上。
試試這種方式,它在我身邊工作。
1.在Activity創建UnityPlayer
private UnityPlayer mUnityPlayer;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUnityPlayer = new UnityPlayer(this);
2.在片段上
private MyActivity mUnityMainActivity; private UnityPlayer mUnityPlayer; View playerView; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub mUnityMainActivity = (MyActivity) getActivity(); mUnityPlayer = mUnityMainActivity.GetUnityPlayer(); playerView = mUnityPlayer.getView(); LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); playerView.setLayoutParams(lp); if(playerView.getParent() != null){ ((ViewGroup)playerView.getParent()).removeAllViews(); } return playerView; }
我設法在上面提供的幫助和此鏈接的幫助下將其集成到片段中: https : //forum.unity.com/threads/unity3d-in-fragment.327303/ 。
在活動中使用標准方法是必不可少的。
更詳細的如下:
MyActivity
) 中:聲明變量 UnityPlayer mUnityPlayer;
這將觸發 import import com.unity3d.player.UnityPlayer;
在下面添加所有覆蓋代碼
//region Lifecycle methods @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUnityPlayer = new UnityPlayer(this); } /** FOR UNITY **/ @Override protected void onPause() { super.onPause(); mUnityPlayer.pause(); } // Resume Unity @Override protected void onResume() { super.onResume(); mUnityPlayer.resume(); } // Low Memory Unity @Override public void onLowMemory() { super.onLowMemory(); mUnityPlayer.lowMemory(); } // Trim Memory Unity @Override public void onTrimMemory(int level) { super.onTrimMemory(level); if (level == TRIM_MEMORY_RUNNING_CRITICAL) { mUnityPlayer.lowMemory(); } } // This ensures the layout will be correct. @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mUnityPlayer.configurationChanged(newConfig); } // Notify Unity of the focus change. @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mUnityPlayer.windowFocusChanged(hasFocus); } // For some reason the multiple keyevent type is not supported by the ndk. // Force event injection by overriding dispatchKeyEvent(). @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_MULTIPLE) return mUnityPlayer.injectEvent(event); return super.dispatchKeyEvent(event); } // Pass any events not handled by (unfocused) views straight to UnityPlayer @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } /*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } @Override protected void onDestroy() { super.onDestroy(); mUnityPlayer.quit(); }
變量聲明 private MyActivity myActivity;
變量聲明:private UnityPlayer unityPlayer;
這將觸發“import com.unity3d.player.UnityPlayer;”
下面的代碼
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { myActivity = (MyActivity) getActivity(); View unityPlayViewer = calibActivity.mUnityPlayer.getView(); new Handler().postDelayed(() -> initialize(), 5000); return unityPlayViewer; } private void initialize() { calibActivity.mUnityPlayer.UnitySendMessage("your commands to Unity to start playing"); }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.