1.背景
這里的實(shí)現(xiàn)是在Android studio 2.2和Unity 5.4上。本人是Android開(kāi)發(fā)者,因?yàn)楣镜臉I(yè)務(wù)需求需要與unity進(jìn)行對(duì)接。那么暴露出來(lái)最需要解決的問(wèn)題就是android上實(shí)現(xiàn)的方法和unity腳本上實(shí)現(xiàn)的方法如何進(jìn)行相互的調(diào)用。在解決該問(wèn)題的過(guò)程中,找了很多的教程以及google了很多其中問(wèn)題的解決方法。下面就是我整理出來(lái)的一些操作步驟和問(wèn)題的解決方式。
2 Android上的操作
2.1 新建Android項(xiàng)目
首先新建一個(gè)android項(xiàng)目,file-->new-->new project,這里新建項(xiàng)目的名稱為UnityAndroid,包名為cn.unity.android,一直點(diǎn)擊next到finish就ok了。
新建android項(xiàng)目
然后將項(xiàng)目切換成project的格式,打開(kāi)app目錄下的build.gradle文件,將apply plugin: 'com.android.application' ,改成apply plugin: 'com.android.library' ,因?yàn)閍ndroid studio只有在這種格式下才可以導(dǎo)出unity需要使用的aar或者jar文件。然后刪除defaultConfig下的applicationId,去掉默認(rèn)的dependencies下的
compile 'com.android.support:appcompat-v7:25.0.0' 的引入,因?yàn)檫@里不需要用到它,而且這個(gè)包包含了很多的資源文件我們是用不到的,最后格式為。
build.gradle文件
project格式
接下來(lái)我們需要修改AndroidManifest文件和res文件,首先刪除values下的style.xml文件,因?yàn)檫@里面默認(rèn)包含的是之前刪除的com.android.support:appcompat-v7:25.0.0 包里面的主題。然后修改AndroidManifest文件中application下的theme為android自帶的主題。同時(shí)將<activity android:name=".MainActivity"> 修改為<activity android:name="cn.unity.android.MainActivity"> ,防止在unity中導(dǎo)出的app與AndroidManifest中的包名不一致產(chǎn)生的問(wèn)題。 然后添加<meta-data>信息,否則在 Unity 導(dǎo)出 APK 時(shí)會(huì)報(bào)找不到manifest 文件的錯(cuò)誤信息
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
最后得到的AndroidManifest和res的格式如下
修改后的AndroidManifest
res目錄結(jié)構(gòu)
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項(xiàng)目app目錄下的libs目錄下,然后進(jìn)行導(dǎo)入,導(dǎo)入之后可以發(fā)現(xiàn)在build.gradle中就有他的引入了。
導(dǎo)入classes.jar
classes.jar導(dǎo)入成功
2.3 為unity寫(xiě)android方法
首先需要讓MainActivity繼承UnityPlayerActivity,因?yàn)閡nity導(dǎo)出的app的視圖展示需要在UnityPlayerActivity下。假如MainActivity繼承的是Activity,那么顯示的就是Android自己的界面。在這里我們寫(xiě)兩個(gè)方法,一個(gè)是彈出Toast通知,一個(gè)是獲取當(dāng)前時(shí)間,具體代碼如下。
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));
}
}
接下來(lái)需要導(dǎo)出aar包和jar包,為接下來(lái)unity調(diào)用提供方法。點(diǎn)擊build-->build apk,然后在app-->build-->outputs-->aar目錄下的到app-debug.aar文件
app-debug.aar
將app-debug.aar文件解壓,得到根目錄下的classes.jar文件,請(qǐng)注意這個(gè)classes.jar文件并不是最開(kāi)始從unity中導(dǎo)入到android的classes.jar文件,而且你寫(xiě)的android代碼的class文件的壓縮包(可以解壓看看里面實(shí)際的內(nèi)容)。之后unity所需要使用的是res文件夾下的文件,classes.jar(android的)和AndroidManifest文件。
解壓后的文件
(ps:理論上來(lái)說(shuō)現(xiàn)在版本的unity是直接可以使用android的aar包的,但是博主在實(shí)際使用過(guò)程中一直會(huì)有問(wèn)題,所以這邊所使用的還是jar包和res文件的形式,如果有小伙伴使用aar成功的話請(qǐng)告知博主)
3 Unity上的操作
3.1 創(chuàng)建Unity項(xiàng)目
打開(kāi)unity,創(chuàng)建項(xiàng)目名稱為UnityDemo,layout的格式改為2by3,project下修改為One column layout(純粹是個(gè)人喜歡這種布局的方法,當(dāng)然你也可以用其他的)。
One column layout
2by3
往unity添加一個(gè)canvas(畫(huà)布),設(shè)置render mode為screen space camera(跟隨相機(jī)的模式),然后設(shè)置ui scale mode 為scale with screen camera 并設(shè)置x,y為600和400。
添加canvas
往canvas中添加一個(gè)text和一個(gè)button,并調(diào)整他們的大小和位置,用于之后的事件操作和顯示。
text
最終的ui顯示
然后將我們之前導(dǎo)出的jar和res文件拷貝到Plugins/Android文件夾下。
導(dǎo)入文件
3.2 編寫(xiě)unity腳本
新建一個(gè)AndroidControl的C#腳本,并將其掛載到Canvas對(duì)象上。(直接通過(guò)鼠標(biāo)左鍵拖動(dòng)到Canvas上)。打開(kāi)腳本,在OnStart()方法中獲取android的MainActivity對(duì)象。
private AndroidJavaObject jo;
void Start ()
{
//獲取Android的Java接口
AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject> ("currentActivity");
}
首先獲取unityPlayer實(shí)例,每個(gè)unity app在啟動(dòng)的時(shí)候都會(huì)有一個(gè)unityPlayer實(shí)例。通過(guò)獲取該實(shí)例里面currentActivity對(duì)象,其實(shí)就是我們的MainActivity實(shí)例。我們可以在android studio中查看源碼的方式知道為什么是獲取這個(gè)currentActivity。
UnityPlayer
創(chuàng)建方法ShowAndroidTime來(lái)獲取系統(tǒng)時(shí)間并進(jìn)行顯示。
public void ShowAndroidTime ()
{
string time = jo.Call<string> ("getNowTime");
jo.Call ("showToast", new object[]{ time });
}
首先調(diào)用MainActivity中的getNowTime方法得到時(shí)間,然后在調(diào)用showToast方法讓時(shí)間Toast出來(lái)。接下來(lái)是要對(duì)button設(shè)置點(diǎn)擊事件去調(diào)用這個(gè)ShowAndroidTime方法。選中button,然后砸onclick點(diǎn)擊+。由于我們的腳本是掛在到Canvas上的,所以需要選擇canvas對(duì)面里面的AndroidControl腳本的ShowAndroidTime方法。
添加點(diǎn)擊事件
3.3 導(dǎo)出Android app
將scene保存,然后點(diǎn)擊file-->build settings,選擇platform為android,然后點(diǎn)擊switch platform,同時(shí)將要導(dǎo)出的scene add進(jìn)來(lái)。
settings
點(diǎn)擊player settings進(jìn)行一些android 導(dǎo)出的設(shè)置。在這里我們?cè)O(shè)置apk的名稱為UnityDemo,顯示為橫屏,設(shè)置包名為cn.unity.demo,要注意的是把install location設(shè)置為Automatic,否則apk會(huì)安裝失敗,同時(shí)需要指定apk的簽名。
名稱
橫屏
包名
簽名
最后點(diǎn)擊build導(dǎo)出apk,如果已經(jīng)連接上android設(shè)備的話,可以直接build and run進(jìn)行導(dǎo)出和啟動(dòng)。
導(dǎo)出apk
看下我們最終實(shí)現(xiàn)的效果
效果
4 Android上調(diào)用Unity的方法
以上我們實(shí)現(xiàn)了unity上調(diào)用android的方法,那么android上如何調(diào)用unity的方法呢,我們先回到unity的AndroidControl腳本。添加方法OnTimeResult,注意在這里需要導(dǎo)入U(xiǎn)nityEngine.UI包usingUnityEngine.UI;
public void OnTimeResult (string result)
{
Text text = GameObject.Find ("TimeShow").GetComponent<Text> ();
text.text = result;
}
上面代碼的意思是獲取名稱為TimeShow的對(duì)象,然后將該對(duì)象上的Text腳本的文本改為得到的result。所以我們需要將之前的Text對(duì)象名稱改為TimeShow
修改名稱
回到android的MainActivity,修改方法showToast,讓Toast時(shí)間的時(shí)候同時(shí)調(diào)用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); 方法的意思是調(diào)用名稱為Canvas對(duì)象上的OnTimeResult方法,傳入的參數(shù)為text。這樣我們的操作就完成了,重復(fù)上面的操作,我們來(lái)看下效果。
效果
5 使用adb logcat查看日志
上述的過(guò)程已經(jīng)完成了unity和android之間的方法的相互調(diào)用,但是問(wèn)題來(lái)了。這樣沒(méi)有出錯(cuò)還好,一旦出錯(cuò),如何查看日志呢。這個(gè)時(shí)候我們可以使用android的adb工具了。(使用之前我們需要配置環(huán)境變量,至于如何配置adb的環(huán)境,這里就不多闡述了)。 在unity的腳本代碼中,增加日志的輸出。并導(dǎo)出apk
public void OnTimeResult (string result)
{
Text text = GameObject.Find ("TimeShow").GetComponent<Text> ();
text.text = result;
Debug.Log ("UnityTime-->"+result);
}
打開(kāi)控制臺(tái),輸入adb logcat -s Unity,然后打開(kāi)apk,點(diǎn)擊button,這個(gè)時(shí)候就可以看到剛剛的日志輸出了。(ps:更多的adb logcat的語(yǔ)法可以自己百度google查看)
logcat
logcat輸出
6 后續(xù):
至此,一個(gè)比較完整的unity和android交互的步驟和如何查看日志就已經(jīng)完成了。如果大家在學(xué)習(xí)使用的過(guò)程有什么問(wèn)題或者有什么更好的方法方式歡迎一起交流。
|