Android/Unity大乱斗-完整集成交互指南
这是一个很长很长的story!- 芝麻粒儿创作
开篇
源码地址:
本文目的,将Unity集成到Android端,学完本文后你可以做到
- Android任意布局加载Unity 3D场景
- 任意操作布局中的按钮/3D物品(缩放旋转等)
- 互相消息通信(你叼我,我叼你)
- 自由切换Unity中的场景
- 动态加载手机SD卡3D资源,一次开发到处使用。
- 在小白面前装逼用
故事正题
首要任务就是将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);