Unity與Android通信優(yōu)化方案

引言

最近為了實現(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項目
  1. 首先我們打開AndroidStudio墩朦,并創(chuàng)建一個新項目坯认,這里隨便填寫項目名斩跌、包名即可挽唉,因為這個項目我們后面并不會用到。

  2. SDK我們選最低的就行篙耗。

  3. Activity我們選個EmptyActivity也行劳吠。

    image

    然后我們點擊「Finish」完成AndroidStudio項目創(chuàng)建引润。

創(chuàng)建和unity交互的Moudle項目
  1. 項目創(chuàng)建好以后開始我們的主菜,選中app然后新建一個moudle

    image
  2. 類型選擇「Android Library」

    image
  3. Application/Library name認(rèn)真填寫痒玩,之后為arr導(dǎo)出的名稱椰拒,這里我們叫「MyUnityLib」晶渠。

  4. Module name沒有強(qiáng)迫癥就不用管它

  5. Package name認(rèn)真填寫,之后unity里會用到燃观,不過它和unity導(dǎo)出的包名沒有什么關(guān)系這里我們叫「com.jing.unity」好了

  6. Minimum SDK能選多低選多低褒脯,反正不超過unity發(fā)布的版本就行

    image
  7. 創(chuàng)建

  8. 然后我們在com.jing.unity包下創(chuàng)建一個類,作為Unity和Android通信的核心類缆毁,名字盡量炫酷一點番川,這里我們叫「Unity2Android」

    image
編寫Android端代碼
  1. 然后我們直接粘貼該類的代碼,講解直接看注釋脊框。這里我們通過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使用
  1. 代碼寫好了我們選中module然后選擇「Build」「Rebuild Project」
![image](//upload-images.jianshu.io/upload_images/9825434-feffddaaa8148784.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/586/format/webp)
  1. 接著將這個arr文件找到,就是我們要導(dǎo)入到unity的文件了烂完。

Unity部分

  1. 創(chuàng)建一個unity項目

  2. 創(chuàng)建目錄Assets/Plugins/Android试疙,并將剛才導(dǎo)出的arr文件放到該文件夾下,我們的導(dǎo)入就算完成了抠蚣。沒錯就是這么Easy祝旷,然后我們看看怎么來調(diào)用它。

    image
  3. 在界面上放一個按鈕嘶窄,并且創(chuàng)建一個Script綁定到「Main Camera」怀跛。用一個文本控件來展示Android發(fā)送過來的消息。

  4. 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;
        }
    }
    
    
  5. 然后打包APK到我們的Android設(shè)備上進(jìn)行測試柄冲。

    image
  6. 點擊按鈕吻谋,查看效果

    image

DEMO地址

結(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
來源:簡書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脯颜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贩据,更是在濱河造成了極大的恐慌栋操,老刑警劉巖闸餐,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異矾芙,居然都是意外死亡舍沙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門剔宪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拂铡,“玉大人,你說我怎么就攤上這事葱绒「兴В” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵地淀,是天一觀的道長失球。 經(jīng)常有香客問我,道長帮毁,這世上最難降的妖魔是什么实苞? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮作箍,結(jié)果婚禮上硬梁,老公的妹妹穿的比我還像新娘前硫。我一直安慰自己胞得,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布屹电。 她就那樣靜靜地躺著阶剑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪危号。 梳的紋絲不亂的頭發(fā)上牧愁,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機(jī)與錄音外莲,去河邊找鬼猪半。 笑死,一個胖子當(dāng)著我的面吹牛偷线,可吹牛的內(nèi)容都是我干的磨确。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼声邦,長吁一口氣:“原來是場噩夢啊……” “哼乏奥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亥曹,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤邓了,失蹤者是張志新(化名)和其女友劉穎恨诱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骗炉,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡照宝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了句葵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硫豆。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖笼呆,靈堂內(nèi)的尸體忽然破棺而出熊响,到底是詐尸還是另有隱情诗赌,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布洪碳,位于F島的核電站,受9級特大地震影響叼屠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镜雨,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荚坞。 院中可真熱鬧挑宠,春花似錦颓影、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旧找。三九已至,卻和暖如春鞭缭,著一層夾襖步出監(jiān)牢的瞬間岭辣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工仑濒, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留墩瞳,地道東北人氏豌。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓泵喘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親相速。 傳聞我的和親對象是個殘疾皇子鲜锚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355