原理概述:Unity在生成apk的时候,会把相对路径为Plugins/Android下的aar文件打入到apk里面,通过Unity自己的api,AndroidJavaClass就可以调用aar里面的代码,实现一些Android原生层的一些功能

本文内容:主要写了用aar沟通Unity的基础流程,不涉及具体的sdk等的接入,本人不是Android原生开发,所以Android的部分很多还不是很理解,所以只能提供一些基本方法,其他的只能靠大家自己去研究了

生成aar

要生成aar,大体步骤如下

  1. AndroiStudio 编辑器里面,新建一个空工程(只是用来当出aar包的载体,后面可以看到里面很多东西是不需要的)
  2. 添加新模块 Android Library
  3. 导入Unity提供的classes.jar包(主要是为了编译通过,如果你没用用到Unity的代码,只是Unity调用java,其实可以不用)
  4. 写自己需要的功能代码,同时根据功能,调整AndroiManifest.xml以及build.gradle(主要配置一些引用等内容,不一定需要调整)
  5. 执行Gradle的assemble task(可以选择出Debug或者Release版本,但没做调整实际都一样,所以简单接入的时候不需要关心)

下面将详细介绍每一步的操作

1. 新建空工程

unity引入aar unity aar_游戏引擎

第一次打开AndroidStudio的话就会让你创建工程,它会提供我们一些工程的模板,如果想看到最干净的Android工程,就选择No Activity,想要做一些最简单的展示啥的,就用BasicActivity,两者差距并不是很大,这里我创建No Activity

unity引入aar unity aar_android_02

这个界面是设置的是工程的名字等信息,Name和Package name没什么关联,随便取都行,后面也一般不会涉及到这些参数。

unity引入aar unity aar_游戏引擎_03


unity引入aar unity aar_unity引入aar_04

AndroidStudio的左边这个位置,会有选项让你看到当前项目的结构,选择Project,就是真实的这个项目在硬盘上的目录结构,而选择Android则是精简过的,Android开发时只需要注意的文件,这个影响不大

unity引入aar unity aar_Android_05


一个空的Android工程其实文件数量就不少,但是实际我看来就两部分,app就是我们自己的代码、图标等内容,是开发阶段我们需要注意的,其他的Gradle都是在生成apk时,发布阶段需要注意的,app文件夹里面也是一样,凡事Gradle相关的,在开发阶段我们都不用太关心(除非你要添加些依赖啥的)

2. 添加新模块

左上角选择File>ProjectStucture,打开如下面板

unity引入aar unity aar_Android_06


文章最开始也提到过,我们创建这个Android App工程只是为了生成aar的一个载体,这个位置我们可以先加一个module(点击+号)

unity引入aar unity aar_Android_07


module name 和 PackageName 也一样,可以随意,只是这里的Package name后面Unity调用的时候就会用到了,因为Unity就是通过这个包名+类名才能定位到java函数的位置

unity引入aar unity aar_Android_08


选中app模块并移除,因为我们实际上不需要这个东西,不删除也无所谓,只是放在这儿比较碍眼,不方便我们工作

unity引入aar unity aar_android_09


移除完后,实际上app还是会在磁盘上,只是现在可以右键删除了,这里我们删除一下即可,同时可以看到刚刚创建的Library已经有了,里面的结构也和app大差不差的,没什么特别要关心的

unity引入aar unity aar_游戏引擎_10


里面的这两个文件夹可以删除掉,都是测试用的,我们用不上,改了这儿还可以去这个路径下的build.gradle里面把几个test工具的引用也移除掉(这几个工具具体的作用我并不清楚,只能说删除后不影响我们后续的流程),每次修改Gradle后,Android Studio都会提示你Sync同步一下,这里你可能会遇到Java连不上网的情况,这个时候可能是你之前配置过vpn,百度一下,删除掉就行

unity引入aar unity aar_unity引入aar_11

3. 导入Unity提供的classes.jar包

这个jar包的路径在unity安装目录下面,相对路径是这个,我是2019.4.19f1版本的,2019.4.19f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes
这个版本的jar包里面是没有UnityPlayerActivity这个java类的,这个类在2019.4.19f1\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player下面,需要自己导入,我们这里用不上,也就不导入了

unity引入aar unity aar_android_12

直接拖到libs下面就行,这个时候还只是在磁盘上放了这个文件,工程还没有引用这个jar包,所以需要右键classes.jar,在列表的最下面选择Add As Libraray即可,正常情况下你就能看到这个jar包里面的代码等内容了

unity引入aar unity aar_游戏引擎_13

4. 写代码

这步骤就因人而异了,也就是说前面的流程已经把基本环境弄好了,剩下的就是自己定制了,这里我只提供一个最简单的测试用的代码

package com.jodebug.myapplication;

import android.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.unity3d.player.UnityPlayer;

public class TutorialTest extends Fragment {
    private static final String TAG = "TestLibrary";
    private String gameObjectName;
    private static TutorialTest Instance = null;

    public static TutorialTest GetInstance(String gameObject) {
        if (Instance == null) {
            Instance = new TutorialTest();
            Instance.gameObjectName = gameObject;
            UnityPlayer.currentActivity.getFragmentManager().beginTransaction().add(Instance, TAG).commit();
        }
        return Instance;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    private int callCount = 0;

    public void UnityCall() {
        callCount += 1;
        // Java调用Unity代码,第一个参数是场景中,绑定了脚本的物体名,第二个参数是方法名,第三个参数是值
        UnityPlayer.UnitySendMessage(gameObjectName, "JavaPluginCallback", String.valueOf(callCount));
    }
}

我这里不需要改AndroidManifest,所以到此,代码写完,就可以开始出包aar了,这里我贴出我的AndroidManifest的内容(其实就是默认的)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jodebug.myapplication">

</manifest>

5. 执行assemble task

unity引入aar unity aar_unity引入aar_14


位置在右边,这个Gradle的位置,里面的myapplication下的带齿轮标签的Task就是我们要执行的目标,简单提一下这个是什么,这个是Gradle出包脚本的一些通用指令,assemble这个指令,可以理解成就是出包指令,而assemble_release等,带了后缀的,都是指出包不同的版本,release就是release版本,不带后缀就是所有版本都生成。执行后,会在一个build文件夹下面(不设置的话就是默认),生成aar。

unity引入aar unity aar_unity引入aar_15

这个位置你可能有时候看不到Tasks,这个时候一般是因为你还有其他的Gradle task已经在执行了,这种情况,本界面的上方会提示你说为什么task列表没显示,这个时候进去,把“其他task执行期间不许执行”这个选项取消掉就行

unity引入aar unity aar_unity引入aar_16


执行task后,这个路径下面就会生成我们要打aar了,剩下的就是Unity里面的流程了

Unity使用aar

随便建一个Unity工程,把aar文件放到Plugins/Android目录下即可

unity引入aar unity aar_unity引入aar_17


但是这个时候实际上打包会报错,因为我们之前在aar里面引用了classes.jar包,但是Unity自己打包apk的时候也会引用他,这样就重复引用了,所以需要删除掉aar里面的classes.jar包,直接用压缩包的形式打开aar文件(本质就是一个压缩包)

unity引入aar unity aar_游戏引擎_18


注意删的不是这里的classes.jar,是libs里面的,这里的是我们自己写的代码生成的jar。

之后我们要做的就是些C#代码去掉java代码了

using System;
using UnityEngine;
using UnityEngine.UI;

public class JavaConnector : MonoBehaviour
{
    private readonly string className = "com.jodebug.myapplication.TutorialTest";
    
    public Text javaCallUi;
    public Text javaCallbackUi;

    private int _callCount = 0;
    public void CallJava()
    {
        try
        {
            var pluginObj =
                new AndroidJavaClass(className).CallStatic<AndroidJavaObject>("GetInstance", gameObject.name);
            pluginObj.Call("UnityCall");
            _callCount++;
            javaCallUi.text = "call:" + _callCount.ToString();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public void JavaPluginCallback(string text)
    {
        javaCallbackUi.text = "back:" + text;
    }
}

这里隐藏了我绑定按钮点击事件的过程,这个有点儿Unity基础的应该都不难,简单解释下代码就是每次点击的时候我Unity自己显示一个调用次数+1,因为在java层被调用的时候,我让java层也反过来调用了Unity层,如果互通了的话,javacallback也会更新显示,这个脚本需要绑定到场景中的任意一个物体上(不关心名字,是因为名字已经动态传给java层了)至此,代码写完,Unity出包测试

最终效果

unity引入aar unity aar_unity引入aar_19


初始我放随便写的两个数字11,后面每次点击都会显示当前点击了几次,回调触发了几次