引言
最近為了實現(xiàn)Unity與Android之間的通信邮弹,在網(wǎng)絡(luò)上發(fā)現(xiàn)了很多種實現(xiàn)方案泰鸡。有打包Jar的,有打包aar的奏纪,有直接拷貝文件的鉴嗤。試了幾種方案雖然都能解決需求,但是使用起來給我的感覺并不是很舒服序调。在各種嘗試中醉锅,已了解了Unity和Android之間通信的底層原理。該方案為本人結(jié)合Java特性所給出发绢,可以減少很多其它方案的一些不明確以及繁瑣的步驟硬耍。
本文適用對象
- 有一定的Unity開發(fā)經(jīng)驗,會使用Unity
- 有一定的Android開發(fā)經(jīng)驗边酒,會使用AndroidStudio
方案優(yōu)勢
- 不需要引用unity下的class.jar
- 不用在Unity的/Plugins/Android下放置AndroidManifest.xml文件
- Unity打包時PackageName不依賴于引用文件
- 發(fā)布簡單经柴,只需要導(dǎo)出arr并直接拷貝到/Plugins/Android目錄下即可使用,不用對文件做任何修改
文章DEMO對應(yīng)的IDE版本
- AndroidStudio 3.0 (2.1親測通過)
- Unity 2017.2 (5.4.3親測通過)
流程
Android部分
創(chuàng)建AndroidStudio項目
首先我們打開AndroidStudio墩朦,并創(chuàng)建一個新項目坯认,這里隨便填寫項目名斩跌、包名即可挽唉,因為這個項目我們后面并不會用到。
SDK我們選最低的就行篙耗。
-
Activity我們選個EmptyActivity也行劳吠。
image然后我們點擊「Finish」完成AndroidStudio項目創(chuàng)建引润。
創(chuàng)建和unity交互的Moudle項目
-
項目創(chuàng)建好以后開始我們的主菜,選中app然后新建一個moudle
image -
類型選擇「Android Library」
image Application/Library name認(rèn)真填寫痒玩,之后為arr導(dǎo)出的名稱椰拒,這里我們叫「MyUnityLib」晶渠。
Module name沒有強(qiáng)迫癥就不用管它
Package name認(rèn)真填寫,之后unity里會用到燃观,不過它和unity導(dǎo)出的包名沒有什么關(guān)系這里我們叫「com.jing.unity」好了
-
Minimum SDK能選多低選多低褒脯,反正不超過unity發(fā)布的版本就行
image 創(chuàng)建
-
然后我們在com.jing.unity包下創(chuàng)建一個類,作為Unity和Android通信的核心類缆毁,名字盡量炫酷一點番川,這里我們叫「Unity2Android」
image
編寫Android端代碼
-
然后我們直接粘貼該類的代碼,講解直接看注釋脊框。這里我們通過Java的反射原理來獲取本來導(dǎo)入class.jar類才能引用到的com.unity3d.player.UnityPlayer包下的currentActivity上下文颁督。同理給unity發(fā)消息也是反射原理〗奖ⅲ「getActivity」和「callUnity」這兩個方法沉御,有一定的開發(fā)經(jīng)驗應(yīng)該很容易理解。
這里我們實現(xiàn)一個簡單的接口「showToast」昭灵。package com.jing.unity; import android.app.Activity; import android.widget.Toast; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Created by Jing on 2018-1-18. */ public class Unity2Android { /** * unity項目啟動時的的上下文 */ private Activity _unityActivity; /** * 獲取unity項目的上下文 * @return */ Activity getActivity(){ if(null == _unityActivity) { try { Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer"); Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype); _unityActivity = activity; } catch (ClassNotFoundException e) { } catch (IllegalAccessException e) { } catch (NoSuchFieldException e) { } } return _unityActivity; } /** * 調(diào)用Unity的方法 * @param gameObjectName 調(diào)用的GameObject的名稱 * @param functionName 方法名 * @param args 參數(shù) * @return 調(diào)用是否成功 */ boolean callUnity(String gameObjectName, String functionName, String args){ try { Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer"); Method method =classtype.getMethod("UnitySendMessage", String.class,String.class,String.class); method.invoke(classtype,gameObjectName,functionName,args); return true; } catch (ClassNotFoundException e) { } catch (NoSuchMethodException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } return false; } /** * Toast顯示unity發(fā)送過來的內(nèi)容 * @param content 消息的內(nèi)容 * @return 調(diào)用是否成功 */ public boolean showToast(String content){ Toast.makeText(getActivity(),content,Toast.LENGTH_SHORT).show(); //這里是主動調(diào)用Unity中的方法吠裆,該方法之后unity部分會講到 callUnity("Main Camera","FromAndroid", "hello unity i'm android"); return true; } }
導(dǎo)出arr準(zhǔn)備給unity使用
- 代碼寫好了我們選中module然后選擇「Build」「Rebuild Project」
![image](//upload-images.jianshu.io/upload_images/9825434-feffddaaa8148784.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/586/format/webp)
- 接著將這個arr文件找到,就是我們要導(dǎo)入到unity的文件了烂完。
Unity部分
創(chuàng)建一個unity項目
-
創(chuàng)建目錄Assets/Plugins/Android试疙,并將剛才導(dǎo)出的arr文件放到該文件夾下,我們的導(dǎo)入就算完成了抠蚣。沒錯就是這么Easy祝旷,然后我們看看怎么來調(diào)用它。
image 在界面上放一個按鈕嘶窄,并且創(chuàng)建一個Script綁定到「Main Camera」怀跛。用一個文本控件來展示Android發(fā)送過來的消息。
-
Script的代碼內(nèi)容如下
using UnityEngine; using UnityEngine.UI; public class Main : MonoBehaviour { /// <summary> /// 場景上的文本框用來顯示android發(fā)送過來的內(nèi)容 /// </summary> public Text text; /// <summary> /// android原生代碼對象 /// </summary> AndroidJavaObject _ajc; void Start () { //通過該API來實例化導(dǎo)入的arr中對應(yīng)的類 _ajc = new AndroidJavaObject("com.jing.unity.Unity2Android"); } void Update () { } /// <summary> /// 場景上按點擊時觸發(fā)該方法 /// </summary> public void OnBtnClick() { //通過API來調(diào)用原生代碼的方法 bool success = _ajc.Call<bool>("showToast","this is unity"); if(true == success) { //請求成功 } } /// <summary> /// 原生層通過該方法傳回信息 /// </summary> /// <param name="content"></param> public void FromAndroid(string content) { text.text = content; } }
-
然后打包APK到我們的Android設(shè)備上進(jìn)行測試柄冲。
image -
點擊按鈕吻谋,查看效果
image
DEMO地址
- 「國外git」GitHub:https://github.com/power-pieces/unity_with_android
- 「國內(nèi)git」Coding:https://coding.net/u/jinglikeblue/p/unity_with_android/git
結(jié)束語
- aar和jar的區(qū)別各位可以自行百度了解。
- 如果要對接第三方庫羊初,可以在moudle下對接滨溉,并打包aar給Unity使用。切記jar需要放到aar的libs下引用长赞,才可以在打包的時候一并導(dǎo)出晦攒。通過gradle的網(wǎng)絡(luò)下載編譯方式是不會被打包到aar中的。gradle網(wǎng)絡(luò)下載的文件的jar可以自行百度查看如何找到得哆。
作者:Pieces_Jing
鏈接:http://www.reibang.com/p/86b275da600e
來源:簡書