UnityAndroid(2) Android加载Unity
目录
一、Android加载Unity
1.1 Unity打包Android项目
1.2 Android加载Unity生成项目
1.3 加载Unity内容
二、Unity和Android交互
2.1 Unity发消息给Java
2.2 Android发消息给Unity
开发环境:Unity2019.2.17f,AndroidStudio3.5.3,VS2019。
我要达到的功能是
1.在unity里面点击一个按钮,在Unity三维内容前面弹出一个窗口,显示Android内容。
2.在Android界面的一部分显示Unity的三维内容。
一、Android加载Unity
1.1 Unity打包Android项目
参考:Unity 工程 融合 AndroidStudio工程
Unity导出Android项目,AndroidStudio导入过程中提示了几个窗口
总之继续下去,打开项目。
下载SDK,能够正常导入了。
加入现在打包运行的话,看到的就是Unity程序了。
--------------------------------------------------------------------------
1.2 Android加载Unity生成项目
将刚刚导出的项目从application改成library,修改成类库。
根据错误提示把下面的bundle和applicationId注释掉
可以打包成aar文件了。
放入Android项目中的libs文件夹中
加入到项目中
Build后出现错误:Manifest merger failed with multiple errors, see logs
参考:https://blog.csdn.net/dengweijunkedafu/article/details/80541104
输入gradlew processDebugManifest --stacktrace,结果
总之把Unity导出项目里面的AndroidManifest.xml的里面的冲突的都删除了。
也就是前面教程中的
就像这样
可以Build了。
---------------------------------------------------------
1.3 加载Unity内容
接下来在Android界面中加载Unity的内容
private UnityPlayer mUnityPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("MainActivity","onCreate"); //initUnityPlayer(); Button btnInit=findViewById(R.id.btnInitUnity); btnInit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i("MainActivity","btnInit onClick"); initUnityPlayer(); } }); } private void initUnityPlayer() { try { Log.i("MainActivity","initUnityPlayer"); LinearLayout layout = findViewById(R.id.unityview); mUnityPlayer = new UnityPlayer(this); layout.addView(mUnityPlayer.getView()); mUnityPlayer.requestFocus(); }catch (Exception ex){ Log.e("MainActivity","Exception:"+ex); } }
运行测试的结果,initUnityPlayer放到onCreate或者onStart里面会闪退,而且没有提示。
加工按钮后,提示E/Unity: Failed to load 'libmain.so'
搜索E/Unity: Failed to load 'libmain.so',在百度上找不到相关资料,感觉它对于纯英文的比较无力....
libmain.so是Unity生成项目里面的
google到 https://forum.unity.com/threads/integration-unity-as-a-library-in-native-android-app.685240/
这个好像是Version1,还有个Version2
相关的还有:https://forum.unity.com/threads/using-unity-as-a-library-in-native-ios-android-apps.685195/
https://forum.unity.com/threads/integration-unity-as-a-library-in-native-android-app-version-2.751712/,
感觉官方的教程不是aar加载而是作为一个Model加载进来的。
另外,有个官方Demo:https://github.com/Unity-Technologies/uaal-example
按照这个
把Unity生成项目的ndk拷贝过来
ndk { abiFilters 'armeabi-v7a' }
结果,不崩溃了,但是还是出不来,那个要显示Unity的区域变成黑色了。
------------------------------------------------------------------------------------
经过研究、思考,理解UnityPlayer是什么,观察Unity打包项目的UnityPlayerActivity后,算是弄出来了。
把前面的initUnityPlayer放到onCreate中,同时把UnityPlayerActivity里面的其他Override方法都拷贝过来。
public class MainActivity extends AppCompatActivity { private UnityPlayer mUnityPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("MainActivity","onCreate"); initUnityPlayer(); } private void initUnityPlayer() { try { Log.i("MainActivity","initUnityPlayer"); LinearLayout layout = findViewById(R.id.unityview); mUnityPlayer = new UnityPlayer(this); layout.addView(mUnityPlayer.getView()); mUnityPlayer.requestFocus(); }catch (Exception ex){ Log.e("MainActivity","Exception:"+ex); } } @Override protected void onNewIntent(Intent intent) { // To support deep linking, we need to make sure that the client can get access to // the last sent intent. The clients access this through a JNI api that allows them // to get the intent set on launch. To update that after launch we have to manually // replace the intent with the one caught here. super.onNewIntent(intent); setIntent(intent); mUnityPlayer.newIntent(intent); } // Quit Unity @Override protected void onDestroy () { mUnityPlayer.destroy(); super.onDestroy(); } // Pause Unity @Override protected void onPause() { super.onPause(); mUnityPlayer.pause(); } // Resume Unity @Override protected void onResume() { super.onResume(); mUnityPlayer.resume(); }。。。。。
拷贝过来后,onNewIntent会让你加个super.onNewIntent。
运行后,在预定的区域(一个LinearLayout里面)显示了Unity的内容了。
测试发现显示Unity内容是用mUnityPlayer.resume();,在requestFocus,马上resume的话,三维能够出来。按钮点击触发resume的话也能出来。
----------------------
直接继承UnityPlayerActivity其实就可以了
public class MainActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUnityPlayer(); } private void initUnityPlayer() { try { Log.i("MainActivity","initUnityPlayer"); LinearLayout layout = findViewById(R.id.unityview); //mUnityPlayer = new UnityPlayer(this); layout.addView(mUnityPlayer.getView());//UnityPlayerActivity里面已经new了 //mUnityPlayer.requestFocus(); }catch (Exception ex){ Log.e("MainActivity","Exception:"+ex); } }}
-------------------------------------------
不过有发现,1.默认的标题栏不见了; 2.手机旋转时会崩溃退出。
第一个不是问题,第二个必须处理。
直接横屏再打开是可以的。
Unity导出项目,生成运行测试,旋转不会崩溃。
。。。。。
===============================================================
二、Unity和Android交互
参考:Unity与Android Studio交互,Unity 与 Android 互调用
2.1 Unity发消息给Java
public void ClickF() { Debug.Log("ClickF"); Count++; Result.text = Count + ""; AndroidJavaClass jc = new AndroidJavaClass("com.example.myapplication.MainActivity"); AndroidJavaObject overrideActivity = jc.GetStatic("instance"); int r=overrideActivity.Call("UnityClick", Count); Result.text += "|" + r; }
Java中有相应的类->对象->方法,com.example.myapplication.MainActivity->instance->UnityClick。
public class MainActivity extends UnityPlayerActivity { public static MainActivity instance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); instance = this; //... } @Override protected void onDestroy() { super.onDestroy(); instance = null; } public int UnityClick(int c){ return c+1; }}
2.2 Android发消息给Unity
// objectName: Unity 对象的名称// methodName: Unity 对象绑定的脚本方法名// message: 自定义消息UnityPlayer.UnitySendMessage(String objectName, String methodName, String message);
Button btn=findViewById(R.id.btnInitUnity); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UnityPlayer.UnitySendMessage("JavaInterface","ReceiveFromAndroid","abc"); } });
同样的Unity中必须有相应的GameObject->Function
public class JavaInterfaceABC : MonoBehaviour{ public void ReceiveFromAndroid(string a) { Debug.Log("ReceiveFromAndroid:" + a); }}
类名不重要,重要的GameObject的名称。
另外假如JavaInterface对象上有多个脚本有ReceiveFromAndroid方法,都会被调用一次的。
-----------
总的来说,和Unity(Webgl)与Html交互很像。
因此实际功能开发时打算也是做成单一入口,所有的交互都从一个接口进入、一个接口出去,用json字符串的方式传递对象数据。
更多相关文章
- PullToRefreshScrollView和Banner
- Android官方文档翻译 三 1.1Creating an Android(安卓)Project
- android加载大图片内存问题
- Android:瀑布流效果 的简单实现
- android图片异步加载解决步骤
- Android(安卓)原始下载图片 通过HTTp
- android studio 复制项目
- android:使用webview加载网页
- android itemtouchhelper-extension 仿微信删除