1. 程式人生 > >實現Unity和Android進行互動

實現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互動的步驟和如何檢視日誌就已經完成了。如果大家在學習使用的過程有什麼問題或者有什麼更好的方法方式歡迎一起交流。

作者:請叫我百米衝刺 連結:https://www.jianshu.com/p/7e46fe7485bb 來源:簡書 簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。