这是一个很长很长的story!-芝麻粒儿创作 开篇源码地址:GitHub 本文目的,将Unity集成到Android端,学完本文后你可以做到
故事正题首要任务就是将Unity项目导出来(已经做好了3D的处理,关于通信和动态加载在下面介绍) 敲黑板,重点Export Project一定要勾选,之后点击最下方的Export 静等项目导出。 导出后的结构感觉好熟悉,就跟Android Studio的项目结构一样(PS:本来就是)打开Studio 以 moudle的形式导入android工程,第一次可能慢一些慢慢导,去喝杯茶。成功后重要的操作来了。打开刚才导入的build.gradle文件,首当其冲的就是gradle版本的修改,跟你的studio版本一致。 dependencies { classpath 'com.android.tools.build:gradle:3.2.0' } 我的是3.2 Android Studio,推荐不低于它。
往下走可以找到
apply plugin: 'com.android.application' 改为 apply plugin: 'com.android.library' 因为我们要以library的形式集成,接着再往下面走就是熟悉的sdkVsersion了,保持和你的anroid项目一致。还有个applicationId,删掉这个。 有的项目遇见UnityAds.aar文件,不影响。其他修改以及遇到的一些坑不再赘述,有问题可以留言。我的如下: // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.0' } } allprojects { repositories { google() jcenter() flatDir { dirs 'libs' } } } apply plugin: 'com.android.library' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) } android { compileSdkVersion 29 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { minSdkVersion 21 targetSdkVersion 29 ndk { abiFilters 'armeabi-v7a', 'x86' } versionCode 1 versionName '1.0' } lintOptions { abortOnError false } aaptOptions { noCompress = ['.unity3d', '.ress', '.resource', '.obb'] } buildTypes { debug { minifyEnabled false useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt' jniDebuggable true } release { minifyEnabled false useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-unity.txt' signingConfig signingConfigs.debug } } packagingOptions { doNotStrip '*/armeabi-v7a/*.so' doNotStrip '*/x86/*.so' } } 接着打开Unity项目的清单文件AndroidManifest.xml,删减application节点,删除intent-filter节点,activity增加内容process(解决某某问题) <application //删减其他 android:banner="@drawable/app_banner" android:isGame="true"> <activity ..... //删除下面两行-否则造成桌面两个icon //android:label="@string/app_name" //android:launchMode="singleTask" //增加这行 android:process="e.unity3d"> //删掉intent-filter <!--<intent-filter>--> <!--<action android:name="android.intent.action.MAIN" />--> <!--<category android:name="android.intent.category.LAUNCHER" />--> <!--<category android:name="android.intent.category.LEANBACK_LAUNCHER" />--> <!--</intent-filter>--> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity> ...... 至此,配置完成,已经可以玩了。 但为了玩的顺畅,我们再增加一个自定义控件(1.用来解决kill问题 2.增强自己的扩展性)。自定义一个java文件集成UnityPlayer(核心关键类) public class MUnityPlayer extends UnityPlayer { public MUnityPlayer(Context context) { super(context); } @Override protected void kill() { //super.kill(); //unity默认一些返回操作等会直接kill掉进程,覆写kill方法,去掉super.kill, 不让他kill } } 配置完成,点击菜单栏的Build,Rebuild Project unity的lib项目中生成aar文件 Unity导出的项目配置完成,配置自己的Android项目,首先将几个lib......so复制到你自己的项目jniLibs中。 然后在你需要集成的项目build文件中 implementation(name: 'XingFeiUnity', ext: 'aar') 接着将aar复制的你的项目libs文件下,记得重命名删除后面的“-debug”,否则会出现找不到类的问题。
一波骚操作搞定,跑起来已经基本可以了。但是这就结束了吗?不可能,骚起来我们就停不下来。 布局渲染我们需要在任意布局加载3d,怎么个任意法?就是找个view来addview 既不影响3d 还有android原生界面 //xml布局 <LinearLayout android:id="@+id/linear" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="50dp" android:orientation="vertical" /> //java文件 mLinear.removeAllViews(); mLinear.addView(mUnityPlayer.getView()); mUnityPlayer.requestFocus(); 操作效果请看图片,全部具体代码的话 就直接放到Github了 通信交互Android调用Unity //参数二是 Unity中的方法名 参数一是哪个物体挂在了这个C#脚本 参数三 字符串 UnityPlayer.UnitySendMessage("Main Camera", "AndroidCallUnity", ""); Unity调用Android 仔细看注释 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Manager : MonoBehaviour { private AndroidJavaObject m_androidObj = null; public GameObject diqiu; void Start() { //注意-情况不同 com.unity3d.player.UnityPlayer 可能不同,可参考其他博主 AndroidJavaClass androidClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); m_androidObj = androidClass.GetStatic<AndroidJavaObject>("currentActivity"); diqiu.SetActive(false); } //Unity中的某个物体出发此事件 public void UnityCallAndroid() { Debug.Log("调用方法"); if (m_androidObj != null) { Debug.Log("调用方法进来"); // 第一个参数是android里面java代码的方法名,第二个是携带的字符串参数 m_androidObj.Call("CallAndroid", "我是Unity,我给你发消息了"); } } //Android调用Unity-方法名一定要注意 public void AndroidCallUnity(string json) { if (diqiu.activeInHierarchy) { diqiu.SetActive(false); } else { diqiu.SetActive(true); } } } 场景切换
动态资源态加载资源的问题,因篇幅有限,咱先只提供个思路,Unity支持读取android设备的存储文件,让他们处理即可,然后android发消息告诉他们地址即可 // 参数一是Unity中的物体名称,参数二Unity中的方法名 参数三路径字符串 UnityPlayer.UnitySendMessage("AndriodMethodMgr", "CallUnitySetPath", Environment.getExternalStorageDirectory() + ""); 啊哈,到这基本就结束了。快了又开心。 坑中带坑为了愉快的装逼,最好还是看一看遇到的这些问题,能至少省几天时间。 1. 混淆问题,如果你开启了混淆,切记 切记,把混淆添加进入,这个大坑耽误我好久啊 2. 如果模型在unity中没问题,在android端穿帮,可以看看发布质量,将android的设置成高的
可以看动画的setting 退出时间,退出时间是比例(如下图),1代表全部动画,0.5代表动画使劲按的一般。过度时间前后动画重叠(好像默认.95?) 可以改成0,如图设置 4. 集成到apk后 申请了横竖屏 但是apk没作用,是unity发布出的设置导致的,再Unity导出的时候 other setting中设置宣传方向 5. 权限问题,上面说了会导出一个android项目,你仔细看这个项目的AndroidManifest文件,你会发现也有权限。 注意,这时候比如你的android项目有权限A 这个Unity导出的项目没有权限A,当你集成合并之后,导致最终的apk没有权限A,这并不是我们想看到的; 所以为了 解决这个问题,很简单,我们把两个清单文件的权限保持一致即可,记住啊,否则怎么哭的都不知道。 6. 还有一个未解决的问题,放到这,有朋友知道的话,感谢指教。 带有动画的一个物体,在有的android设备上,动画表现征程,但是有的会出现动画跳动的情况,感觉像是电视的进度条那在跳进度一样。 结尾最后,别问我为啥知道这么多问题,问就是因为自己跪着走过来的。 |
|