欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android/Unity大乱斗-完整双方集成交互指南

程序员文章站 2023-02-20 15:02:57
这是一个很长很长的story!-芝麻粒儿创作 开篇 源码地址:GitHub 本文目的,将Unity集成到Android端,学完本文后你可以做到 Android任意布局加载Unity 3D场景 任意操作布局中的按钮/3D物品(缩放旋转等) 互相消息通信(你叼我,我叼你) *切换Unity中的场景 动 ......

这是一个很长很长的story!-芝麻粒儿创作

开篇

源码地址:github

本文目的,将unity集成到android端,学完本文后你可以做到

  1. android任意布局加载unity 3d场景
  2. 任意操作布局中的按钮/3d物品(缩放旋转等)
  3. 互相消息通信(你叼我,我叼你)
  4. *切换unity中的场景
  5. 动态加载手机sd卡3d资源,一次开发到处使用。
  6. 在小白面前装逼用

Android/Unity大乱斗-完整双方集成交互指南

故事正题

首要任务就是将unity项目导出来(已经做好了3d的处理,关于通信和动态加载在下面介绍)

Android/Unity大乱斗-完整双方集成交互指南

敲黑板,重点export project一定要勾选,之后点击最下方的export 静等项目导出。

Android/Unity大乱斗-完整双方集成交互指南

导出后的结构感觉好熟悉,就跟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(核心关键类)

Android/Unity大乱斗-完整双方集成交互指南

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文件

Android/Unity大乱斗-完整双方集成交互指南Android/Unity大乱斗-完整双方集成交互指南

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大乱斗-完整双方集成交互指南

通信交互

android调用unity

//参数二是 unity中的方法名   参数一是哪个物体挂在了这个c#脚本  参数三 字符串
unityplayer.unitysendmessage("main camera", "androidcallunity", "");

Android/Unity大乱斗-完整双方集成交互指南

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内部自己去处理,就跟玩游戏一样,让unity开发自己去做
  • andorid触发,unity换场景,这个借助上面说的消息通信来实现
  • 这还有一个技巧,如果资源不是很多且在一个场景的话,可以让unity一次直接渲染出来存在字典里,然后想显示哪个android给unity发消息,unity根据订好的消息,展示不同的内容,这个好处就是切换展示速度极快。重点处理一下刚启动的时候的耗时即可。

动态资源

态加载资源的问题,因篇幅有限,咱先只提供个思路,unity支持读取android设备的存储文件,让他们处理即可,然后android发消息告诉他们地址即可

// 参数一是unity中的物体名称,参数二unity中的方法名  参数三路径字符串
unityplayer.unitysendmessage("andriodmethodmgr", "callunitysetpath", environment.getexternalstoragedirectory() + "");

啊哈,到这基本就结束了。快了又开心。

坑中带坑

为了愉快的装逼,最好还是看一看遇到的这些问题,能至少省几天时间。

1. 混淆问题,如果你开启了混淆,切记 切记,把混淆添加进入,这个大坑耽误我好久啊

2. 如果模型在unity中没问题,在android端穿帮,可以看看发布质量,将android的设置成高的

Android/Unity大乱斗-完整双方集成交互指南
3. 如果反复执行的模型动画不对,怎么不对?举例心脏跳动,这是非常注重动画的衔接的,如果衔接时间不对会造成心脏动画的抖动,这会非常的明显。

可以看动画的setting 退出时间,退出时间是比例(如下图),1代表全部动画,0.5代表动画使劲按的一般。过度时间前后动画重叠(好像默认.95?)  可以改成0,如图设置

Android/Unity大乱斗-完整双方集成交互指南

4. 集成到apk后 申请了横竖屏 但是apk没作用,是unity发布出的设置导致的,再unity导出的时候 other setting中设置宣传方向

5. 权限问题,上面说了会导出一个android项目,你仔细看这个项目的androidmanifest文件,你会发现也有权限。

注意,这时候比如你的android项目有权限a 这个unity导出的项目没有权限a,当你集成合并之后,导致最终的apk没有权限a,这并不是我们想看到的;

所以为了 解决这个问题,很简单,我们把两个清单文件的权限保持一致即可,记住啊,否则怎么哭的都不知道。

6. 还有一个未解决的问题,放到这,有朋友知道的话,感谢指教。

带有动画的一个物体,在有的android设备上,动画表现征程,但是有的会出现动画跳动的情况,感觉像是电视的进度条那在跳进度一样。

结尾

最后,别问我为啥知道这么多问题,问就是因为自己跪着走过来的。

Android/Unity大乱斗-完整双方集成交互指南