Unity和Android交互通常有两种方式:
1、Unity调用为Android平台编写的插件
2、将Unity项目导出为Android项目,然后编写Android程序
这两种方式在实际的应用中各有优劣,我们今天先来讲解第一种方法,第二种方法博主稍后再和大家分享。首先来说说第一种方法的原理,我们首先用Eclipse编写一个Java的库文件(.Jar),在这个库文件中我们会封装一系列的方法来为Unity提供接口,我们将这个库文件导出后可以将其放置到一个特定的目录下(Plugins/Android),然后我们就可以利用Unity提供的API来调用这些方法。好了,下面我们来看具体的过程吧,首先我们创建一个Android项目,并将其设为一个库,这里将其包名设为com.android.android2unity,这个包名很重要,我们在Unity中将用到这个包名。我们接下来在MainActivity.java这个类中编写代码,它将作为我们封装Android API的一个类。在编写代码之前,让我们来做这样一件事情,将位于D:\Program Files\Unity\Editor\Data\PlaybackEngines\androidplayer\release\bin\classes.jar(不同的计算机上,这个位置可能会有所不同,大家按照自己的路径添加即可)这个库加入到我们的项目中来,如图:
这个库是Unity为Android提供的一个库,主要提供了支持该平台的Player,具体的大家可以自己去查看它的类空间。好了,我们下面编写这样一个脚本:
- package com.android.android2unity;
-
- import android.app.AlertDialog;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.Vibrator;
- import android.widget.Toast;
-
-
-
- import com.unity3d.player.UnityPlayerActivity;
- import com.unity3d.player.UnityPlayer;
-
-
-
- public class MainActivity extends UnityPlayerActivity {
-
-
- private Context mContext=null;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mContext=this;
- }
-
-
-
-
-
- public void InvokeUnity(String mStr)
- {
- UnityPlayer.UnitySendMessage("Vabille","SetCameraColor", "");
- }
-
-
- public void StartWebView(String mUrl)
- {
-
- Intent intent=new Intent(mContext,WebActivity.class);
-
- intent.putExtra("URL", mUrl);
-
- this.startActivity(intent);
- }
-
-
- public void ShowDialog(final String mTitle,final String mContent)
- {
-
- runOnUiThread(new Runnable()
- {
- @Override
- public void run()
- {
-
- AlertDialog.Builder mBuilder=new AlertDialog.Builder(MainActivity.this);
-
- mBuilder.setTitle(mTitle)
- .setMessage(mContent)
- .setPositiveButton("确定", null);
-
- mBuilder.show();
- }
- });
- }
-
-
- public void SetVibrator(long mTime)
- {
- Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);
- mVibrator.vibrate(mTime);
- }
-
-
- public void ShowToast(String mContent)
- {
- Toast.makeText(mContext,mContent,Toast.LENGTH_LONG);
- }
- }
在这段代码中我们让MainActivity类继承自Unity提供的UnityPlayerActivity,这样我们就可以在Android中使用Unity提供的某些方法。在这段代码中我们定义了5个方法,即用于显示对话框的ShowDialog()方法、用于显示Toast的ShowToast()方法、用于打开一个Activity的StartWebView()方法、用于使设备震动的方法SetVibrator()方法以及用于调用Unity中定义的方法的InvokeUnity()方法,其中ShowDialog()方法需要在UI线程下运行。在这里,我们不需要为当前的Activity设置一个布局文件,所以我们没有使用setContentView()方法。
接下来我们创建一个继承自Activity的类WebActivity,我们希望在这个页面中加载一个网页,网页的地址可以通过Unity来指定,我们首先来看布局文件avtivity_web.xml,它是一个简单的线性布局,在它的内部只有一个用于显示网页的WebView组件webView:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <WebView
- android:id="@+id/webView"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
相应地,它对应于WebActivity类,我们在MainActivity类中定义的StartWebView()方法即指向这个Acitivity:
- package com.android.android2unity;
-
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.webkit.WebView;
-
-
- public class WebActivity extends Activity
- {
-
- private WebView mWebView;
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.activity_web);
-
- mWebView=(WebView)findViewById(R.id.webView);
-
- String mUrl=this.getIntent().getStringExtra("URL");
-
- mWebView.loadUrl(mUrl);
- }
- }
它的意义很明确,从MainActivity中读取传来的字符型参数URL,这是一个网页地址,我们通过这个地址打开一个网页。最后,我们来看项目的配置文件AndroidManifest.xml文件,这是一个比较重要的文件,我们在这里要做的事情是注册WebActivity、给应用分配相应的权限:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.android2unity"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="9"
- android:targetSdkVersion="14" />
- <uses-permission android:name="android.permission.VIBRATE"/>
- <uses-permission android:name="android.permission.INTERNET"/>
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name="com.android.android2unity.MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity android:name=".WebActivity"/>
- </application>
-
-
- </manifest>
好了,到现在为止,我们基本上完成了Android插件的编写,最后我们要做的就是将它输出为一个Jar库,以便我们在Unity中使用,在这里要注意的是,所有的Java类、Android生成的配置文件类(如属性、布局、值等)都要编译,博主之前就是因为没有搞懂Jar库的编译,结果在Java、Unity两边费了不少的周折、来回奔波。如果对Java熟悉的朋友,一定会采用命令来输出库文件吧,不过博主是个菜鸟,对Java命令不太熟悉,所以博主采用的方法是通过文件->导出来导出Jar文件的,如图,我们需要选中src目录和R.java文件,如果有第三方的库的话还需要选中libs文件夹:
这样我们就可以直接输出我们需要的Jar库文件了。这样我们就完成了在Android中编写Unity插件的任务,接下来,我们进入Unity的势力范围吧,哈哈!
在Unity这块呢,我们继续用我们前一篇文章中的项目,我们继续使用FF中这个漂亮的妹子(原谅我不知道她叫什么名字)如图:
下面请大家按照这样的结构来组织Android插件的目录:
----------Assets
----Plugins
-----Android
-----bin(存放导出的Jar)
-----libs(存放第三方的库)
-----res(资源文件夹,可直接复制Android项目)
-----AndroidManifest.xml(配置文件,可直接复制Android项目)
最终的效果应该是这样:
好了,下面我们来编写C#脚本AndroidAPI.cs
- using UnityEngine;
- using System.Collections;
-
- public class AndroidAPI : MonoBehaviour {
-
- void Start()
- {
-
- this.name="Vabille";
- }
-
-
- void SetCameraColor()
- {
-
- Camera.main.backgroundColor=new Color(1.0F,0.5F,0.5F);
- }
-
- void OnGUI ()
- {
-
- if(GUILayout.Button("调用Android API显示对话框",GUILayout.Height(45)))
- {
-
- AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");
-
- string[] mObject=new string[2];
- mObject[0]="Unity3D";
- mObject[1]="Unity3D成功调用Android API";
-
- jo.Call("ShowDialog",mObject);
- }
-
-
- if(GUILayout.Button("调用Android API中打开Activity",GUILayout.Height(45)))
- {
-
- AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");
-
- jo.Call("StartWebView","http://blog.csdn.net/qinyuanpei");
- }
-
-
- if(GUILayout.Button("调用Android API中的Toast",GUILayout.Height(45)))
- {
-
- AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");
-
- jo.Call("ShowToast","为Unity3D编写Android插件是件苦差事!");
- }
-
-
- if(GUILayout.Button("调用Android API中的震动方法",GUILayout.Height(45)))
- {
-
- AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");
-
- jo.Call("SetVibrator",40);
- }
-
-
- if(GUILayout.Button("通过SendMessage调用Unity中的方法",GUILayout.Height(45)))
- {
-
- AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");
- AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");
-
- jo.Call("InvokeUnity","");
- }
-
- }
- }
这里的方法都是调用在Android中定义好的方法,主要是利用AndroidJavaObject的Call()方法,该方法有两个参数,第一个参数是一个字符型的变量,是我们要调用的方法的名字,第二个参数是一个object[]类型,是我们要调用的方法的参数。好了,我们一起来看看手机上运行的效果吧!
这就是今天的成果了,不过大家都知道我的习惯,每次我在文章中解决不了的问题都会在博客里说出来让大家帮我解决,而今天的问题就是ShowToast()方法和SetVibrator()方法一直没有被调用,博主怀疑是不是Unity提供的Java接口能力有限,只能访问Android的某些接口,不知道大家是怎么看的,如果大家知道的话,希望大家可以告诉我啊,呵呵。
最后,想说的一点就是我们在C#里定义了一个SetCameraColor()的方法,这是一个改变摄像机背景的方法,我们在Android中使用InvokeUnity()方法来访问这个方法,由于在第一个页面中,我们没有使用Android的布局元素,因此Android的事件我们无法使用,我们依然采用在Unity中调用的方法,最然这样显得舍近求远,但是这说明了一个问题,Android可以调用Unity的的方法,而具体实现就是通过SendMessage()来实现的,博主个人觉得这是一种委托吧。大家注意到最后屏幕的颜色变成了红色,说明这个方法被调用了。好了,今天的内容就是这样啦,写完这篇文章博主感觉好累啊!
每日箴言:孤独是人生的伴侣,寂寞是人生的常客。人生就是一场修行,修行要有耐性,要能忍受孤独、无悔寂寞。
喜欢我的博客请记住我的名字:秦元培,我博客地址是blog.csdn.NET/qinyuanpei。
转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.Net/qinyuanpei/article/details/39348677