实现Unity和Android进行交互

1.背景

这里的实现是在Android studio 2.2和Unity 5.4上。本人是Android开发者,因为公司的业务需求需要与unity进行对接。那么暴露出来最需要解决的问题就是android上实现的方法和unity脚本上实现的方法如何进行相互的调用。在解决该问题的过程中,找了很多的教程以及google了很多其中问题的解决方法。下面就是我整理出来的一些操作步骤和问题的解决方式。

2 Android上的操作

2.1 新建Android项目

首先新建一个android项目,file-->new-->new project,这里新建项目的名称为UnityAndroid,包名为cn.unity.android,一直点击next到finish就ok了。

新建android项目

  然后将项目切换成project的格式,打开app目录下的build.gradle文件,将apply plugin: 'com.android.application',改成apply plugin: 'com.android.library',因为android studio只有在这种格式下才可以导出unity需要使用的aar或者jar文件。然后删除defaultConfig下的applicationId,去掉默认的dependencies下的
compile 'com.android.support:appcompat-v7:25.0.0'的引入,因为这里不需要用到它,而且这个包包含了很多的资源文件我们是用不到的,最后格式为。
build.gradle文件

project格式

  接下来我们需要修改AndroidManifest文件和res文件,首先删除values下的style.xml文件,因为这里面默认包含的是之前删除的com.android.support:appcompat-v7:25.0.0包里面的主题。然后修改AndroidManifest文件中application下的theme为android自带的主题。同时将<activity android:name=".MainActivity">修改为<activity android:name="cn.unity.android.MainActivity">,防止在unity中导出的app与AndroidManifest中的包名不一致产生的问题。
  然后添加<meta-data>信息,否则在 Unity 导出 APK 时会报找不到manifest 文件的错误信息

<meta-data android:name="unityplayer.UnityActivity" android:value="true" /> 

最后得到的AndroidManifest和res的格式如下

修改后的AndroidManifest
res目录结构

2.2 引入unity的 classes.jar包

找到unity的classes.jar包。windows下和mac下包的路径分别为
C:\ProgramFiles\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\classes.jar
/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes\classes.jar
  将其拷贝到UnityAndroid项目app目录下的libs目录下,然后进行导入,导入之后可以发现在build.gradle中就有他的引入了。

导入classes.jar
classes.jar导入成功

2.3 为unity写android方法

首先需要让MainActivity继承UnityPlayerActivity,因为unity导出的app的视图展示需要在UnityPlayerActivity下。假如MainActivity继承的是Activity,那么显示的就是Android自己的界面。在这里我们写两个方法,一个是弹出Toast通知,一个是获取当前时间,具体代码如下。

package cn.unity.android;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;

import com.unity3d.player.UnityPlayerActivity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends UnityPlayerActivity {

    private Toast mToast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    public void showToast(final String text) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {

            public void run() {
                if (mToast == null) {
                    mToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT);
                } else {
                    mToast.setText(text);
                }
                mToast.show();
            }
        });
    }

    public String getNowTime() {
        long time = System.currentTimeMillis();
        return new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss", Locale.CHINESE).format(new Date(time));
    }
}

接下来需要导出aar包和jar包,为接下来unity调用提供方法。点击build-->build apk,然后在app-->build-->outputs-->aar目录下的到app-debug.aar文件

app-debug.aar

  将app-debug.aar文件解压,得到根目录下的classes.jar文件,请注意这个classes.jar文件并不是最开始从unity中导入到android的classes.jar文件,而且你写的android代码的class文件的压缩包(可以解压看看里面实际的内容)。之后unity所需要使用的是res文件夹下的文件,classes.jar(android的)和AndroidManifest文件。

解压后的文件

(ps:理论上来说现在版本的unity是直接可以使用android的aar包的,但是博主在实际使用过程中一直会有问题,所以这边所使用的还是jar包和res文件的形式,如果有小伙伴使用aar成功的话请告知博主)

3 Unity上的操作

3.1 创建Unity项目

打开unity,创建项目名称为UnityDemo,layout的格式改为2by3,project下修改为One column layout(纯粹是个人喜欢这种布局的方法,当然你也可以用其他的)。

One column layout
2by3

  往unity添加一个canvas(画布),设置render mode为screen space camera(跟随相机的模式),然后设置ui scale mode 为scale with screen camera 并设置x,y为600和400。

添加canvas

  往canvas中添加一个text和一个button,并调整他们的大小和位置,用于之后的事件操作和显示。

text
最终的ui显示

  然后将我们之前导出的jar和res文件拷贝到Plugins/Android文件夹下。

导入文件

3.2 编写unity脚本

新建一个AndroidControl的C#脚本,并将其挂载到Canvas对象上。(直接通过鼠标左键拖动到Canvas上)。打开脚本,在OnStart()方法中获取android的MainActivity对象。

private AndroidJavaObject jo;
    void Start ()
    {
        //获取Android的Java接口  
        AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");  
        jo = jc.GetStatic<AndroidJavaObject> ("currentActivity"); 
    }

首先获取unityPlayer实例,每个unity app在启动的时候都会有一个unityPlayer实例。通过获取该实例里面currentActivity对象,其实就是我们的MainActivity实例。我们可以在android studio中查看源码的方式知道为什么是获取这个currentActivity。

UnityPlayer

  创建方法ShowAndroidTime来获取系统时间并进行显示。

public void  ShowAndroidTime ()
    {
        string time = jo.Call<string> ("getNowTime");
        jo.Call ("showToast", new object[]{ time });
    }

首先调用MainActivity中的getNowTime方法得到时间,然后在调用showToast方法让时间Toast出来。接下来是要对button设置点击事件去调用这个ShowAndroidTime方法。选中button,然后砸onclick点击+。由于我们的脚本是挂在到Canvas上的,所以需要选择canvas对面里面的AndroidControl脚本的ShowAndroidTime方法。

添加点击事件

3.3 导出Android app

将scene保存,然后点击file-->build settings,选择platform为android,然后点击switch platform,同时将要导出的scene add进来。

settings

  点击player settings进行一些android 导出的设置。在这里我们设置apk的名称为UnityDemo,显示为横屏,设置包名为cn.unity.demo,要注意的是把install location设置为Automatic,否则apk会安装失败,同时需要指定apk的签名。

名称
横屏
包名
签名

最后点击build导出apk,如果已经连接上android设备的话,可以直接build and run进行导出和启动。

导出apk

看下我们最终实现的效果


效果

4 Android上调用Unity的方法

以上我们实现了unity上调用android的方法,那么android上如何调用unity的方法呢,我们先回到unity的AndroidControl脚本。添加方法OnTimeResult,注意在这里需要导入UnityEngine.UI包usingUnityEngine.UI;

public void OnTimeResult (string result)
    {
        Text text = GameObject.Find ("TimeShow").GetComponent<Text> ();
        text.text = result;
    }

上面代码的意思是获取名称为TimeShow的对象,然后将该对象上的Text脚本的文本改为得到的result。所以我们需要将之前的Text对象名称改为TimeShow

修改名称

  回到android的MainActivity,修改方法showToast,让Toast时间的时候同时调用OnTimeResult方法修改text的文本。

public void showToast(final String text) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {

            public void run() {
                if (mToast == null) {
                    mToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT);
                } else {
                    mToast.setText(text);
                }
                mToast.show();
                UnityPlayer.UnitySendMessage("Canvas","OnTimeResult",text);
            }
        });
    }

UnityPlayer.UnitySendMessage("Canvas","OnTimeResult",text);方法的意思是调用名称为Canvas对象上的OnTimeResult方法,传入的参数为text。这样我们的操作就完成了,重复上面的操作,我们来看下效果。

效果

5 使用adb logcat查看日志

上述的过程已经完成了unity和android之间的方法的相互调用,但是问题来了。这样没有出错还好,一旦出错,如何查看日志呢。这个时候我们可以使用android的adb工具了。(使用之前我们需要配置环境变量,至于如何配置adb的环境,这里就不多阐述了)。
  在unity的脚本代码中,增加日志的输出。并导出apk

public void OnTimeResult (string result)
    {
        Text text = GameObject.Find ("TimeShow").GetComponent<Text> ();
        text.text = result;
        Debug.Log ("UnityTime-->"+result);
    }

打开控制台,输入adb logcat -s Unity,然后打开apk,点击button,这个时候就可以看到刚刚的日志输出了。(ps:更多的adb logcat的语法可以自己百度google查看)

logcat
logcat输出

6 后续:

至此,一个比较完整的unity和android交互的步骤和如何查看日志就已经完成了。如果大家在学习使用的过程有什么问题或者有什么更好的方法方式欢迎一起交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容