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了。
??然后將項目切換成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'
的引入,因為這里不需要用到它,而且這個包包含了很多的資源文件我們是用不到的,最后格式為。??接下來我們需要修改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的格式如下
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中就有他的引入了。
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文件解壓,得到根目錄下的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(純粹是個人喜歡這種布局的方法,當然你也可以用其他的)。
??往unity添加一個canvas(畫布),設置render mode為screen space camera(跟隨相機的模式),然后設置ui scale mode 為scale with screen camera 并設置x,y為600和400。
??往canvas中添加一個text和一個button,并調整他們的大小和位置,用于之后的事件操作和顯示。
??然后將我們之前導出的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。
??創建方法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進來。
??點擊player settings進行一些android 導出的設置。在這里我們設置apk的名稱為UnityDemo,顯示為橫屏,設置包名為cn.unity.demo,要注意的是把install location設置為Automatic,否則apk會安裝失敗,同時需要指定apk的簽名。
最后點擊build導出apk,如果已經連接上android設備的話,可以直接build and run進行導出和啟動。
看下我們最終實現的效果
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查看)
6 后續:
至此,一個比較完整的unity和android交互的步驟和如何查看日志就已經完成了。如果大家在學習使用的過程有什么問題或者有什么更好的方法方式歡迎一起交流。