当前位置:   article > 正文

Unity为Android编写插件_u3d游戏作为app插件

u3d游戏作为app插件

  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,具体的大家可以自己去查看它的类空间。好了,我们下面编写这样一个脚本:

[csharp]  view plain  copy
  1. package com.android.android2unity;  
  2.   
  3. import android.app.AlertDialog;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7. import android.os.Vibrator;  
  8. import android.widget.Toast;  
  9.   
  10.   
  11. /* 引入Unity的包  */  
  12. import com.unity3d.player.UnityPlayerActivity;  
  13. import com.unity3d.player.UnityPlayer;  
  14.   
  15. /* 如果需要Activity与Unity对接,可以通过继承UnityPlayerActivity来实现  */  
  16. /* 我们需要重写Activity的相关方法,在此节代码中,我们只需要调用Android API  */  
  17. public class MainActivity extends UnityPlayerActivity {  
  18.   
  19.     //当前上下文  
  20.     private Context mContext=null;  
  21.       
  22.     @Override  
  23.     protected void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         //初始化上下文  
  26.         mContext=this;  
  27.     }  
  28.       
  29.     /* 定义一个调用Unity方法的方法 ,基于UnitySendMessage实现 。由于当前Activity没有采用   */  
  30.     /* Android的布局文件,所以我们无法使用Android的事件来完成这个方法的调用,我们  */  
  31.     /* 采用Unity调用的方法,虽然这样显得舍近求远,可是我们知道了如何在Android中调用   */  
  32.     /* Unity中定义的方法   */  
  33.     public void InvokeUnity(String mStr)  
  34.     {  
  35.        UnityPlayer.UnitySendMessage("Vabille","SetCameraColor""");  
  36.     }  
  37.       
  38.     /* 定义一个打开Activity的方法,我们将在Unity中调用此方法 */  
  39.     public void StartWebView(String mUrl)  
  40.     {  
  41.         //创建一个Intent以打开一个新的Activity  
  42.         Intent intent=new Intent(mContext,WebActivity.class);  
  43.         //传入一个URL  
  44.         intent.putExtra("URL", mUrl);  
  45.         //打开Activity  
  46.         this.startActivity(intent);   
  47.     }  
  48.   
  49.     /* 定义一个显示对话框的方法,我们将在Unity中调用此方法 */  
  50.     public void ShowDialog(final String mTitle,final String mContent)  
  51.     {  
  52.         /* 在UI线程下执行相关方法 */  
  53.         runOnUiThread(new Runnable()  
  54.         {  
  55.             @Override  
  56.             public void run()   
  57.             {  
  58.                 //创建Builder  
  59.                 AlertDialog.Builder mBuilder=new AlertDialog.Builder(MainActivity.this);  
  60.                 //创建对话框  
  61.                 mBuilder.setTitle(mTitle)  
  62.                         .setMessage(mContent)  
  63.                         .setPositiveButton("确定"null);  
  64.                 //显示对话框  
  65.                 mBuilder.show();  
  66.             }  
  67.         });  
  68.     }  
  69.       
  70.     /* 定义一个使设备震动的方法,我们将在Unity中调用此方法 */  
  71.     public void SetVibrator(long mTime)  
  72.     {  
  73.         Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);  
  74.         mVibrator.vibrate(mTime);  
  75.     }  
  76.       
  77.     /* 定义一个使设备震动的方法,我们将在Unity中调用此方法 */  
  78.     public void ShowToast(String mContent)  
  79.     {  
  80.         Toast.makeText(mContext,mContent,Toast.LENGTH_LONG);  
  81.     }  
  82. }  
     在这段代码中我们让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:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.     <WebView  
  7.         android:id="@+id/webView"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent" />  
  10. </LinearLayout>  
      相应地,它对应于WebActivity类,我们在MainActivity类中定义的StartWebView()方法即指向这个Acitivity:

[java]  view plain  copy
  1. package com.android.android2unity;  
  2.   
  3.   
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.webkit.WebView;  
  7.   
  8.   
  9. public class WebActivity extends Activity  
  10. {  
  11.     //网页组组件  
  12.     private WebView mWebView;  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         //设置当前布局  
  16.         setContentView(R.layout.activity_web);  
  17.         //获取WebView  
  18.         mWebView=(WebView)findViewById(R.id.webView);  
  19.         //获取URL  
  20.         String mUrl=this.getIntent().getStringExtra("URL");  
  21.         //加载网页  
  22.         mWebView.loadUrl(mUrl);  
  23.     }  
  24. }  
它的意义很明确,从MainActivity中读取传来的字符型参数URL,这是一个网页地址,我们通过这个地址打开一个网页。最后,我们来看项目的配置文件AndroidManifest.xml文件,这是一个比较重要的文件,我们在这里要做的事情是注册WebActivity、给应用分配相应的权限:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.android.android2unity"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="9"  
  9.         android:targetSdkVersion="14" />  
  10.     <uses-permission android:name="android.permission.VIBRATE"/>  
  11.     <uses-permission android:name="android.permission.INTERNET"/>  
  12.   
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:theme="@style/AppTheme" >  
  18.         <activity  
  19.             android:name="com.android.android2unity.MainActivity"  
  20.             android:label="@string/app_name" >  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.                 <category android:name="android.intent.category.LAUNCHER" />  
  24.             </intent-filter>  
  25.         </activity>  
  26.         <activity android:name=".WebActivity"/>  
  27.     </application>  
  28.   
  29.       
  30. </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

[csharp]  view plain  copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class AndroidAPI : MonoBehaviour {  
  5.   
  6.     void Start()  
  7.     {  
  8.         //设置当前游戏体的名字,在Android中我们将使用这个名字  
  9.         this.name="Vabille";  
  10.     }  
  11.   
  12.     //定义一个方法以改变摄像机背景颜色,我们将在Android中调用这个方法  
  13.     void SetCameraColor()  
  14.     {  
  15.         //设置摄像机背景颜色  
  16.         Camera.main.backgroundColor=new Color(1.0F,0.5F,0.5F);  
  17.     }  
  18.   
  19.     void OnGUI ()   
  20.     {  
  21.         //通过API调用对话框  
  22.         if(GUILayout.Button("调用Android API显示对话框",GUILayout.Height(45)))  
  23.         {  
  24.             //获取Android的Java接口  
  25.             AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
  26.             AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");  
  27.             //构造参数  
  28.             string[] mObject=new string[2];  
  29.             mObject[0]="Unity3D";  
  30.             mObject[1]="Unity3D成功调用Android API";  
  31.             //调用方法  
  32.             jo.Call("ShowDialog",mObject);  
  33.         }  
  34.   
  35.         //通过传值打开Activity  
  36.         if(GUILayout.Button("调用Android API中打开Activity",GUILayout.Height(45)))  
  37.         {  
  38.             //获取Android的Java接口  
  39.             AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
  40.             AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");  
  41.             //打开博主的博客  
  42.             jo.Call("StartWebView","http://blog.csdn.net/qinyuanpei");  
  43.         }  
  44.   
  45.         //通过API调用Toast  
  46.         if(GUILayout.Button("调用Android API中的Toast",GUILayout.Height(45)))  
  47.         {  
  48.             //获取Android的Java接口  
  49.             AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
  50.             AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");  
  51.             //打开博主的博客  
  52.             jo.Call("ShowToast","为Unity3D编写Android插件是件苦差事!");  
  53.         }  
  54.   
  55.         //通过API调用Toast  
  56.         if(GUILayout.Button("调用Android API中的震动方法",GUILayout.Height(45)))  
  57.         {  
  58.             //获取Android的Java接口  
  59.             AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
  60.             AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");  
  61.             //打开博主的博客  
  62.             jo.Call("SetVibrator",40);  
  63.         }  
  64.   
  65.         //通过API调用Toast  
  66.         if(GUILayout.Button("通过SendMessage调用Unity中的方法",GUILayout.Height(45)))  
  67.         {  
  68.             //获取Android的Java接口  
  69.             AndroidJavaClass jc=new AndroidJavaClass("com.unity3d.player.UnityPlayer");  
  70.             AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity");  
  71.             //打开博主的博客  
  72.             jo.Call("InvokeUnity","");  
  73.         }  
  74.   
  75.     }  
  76. }  
     这里的方法都是调用在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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/119149?site
推荐阅读
相关标签
  

闽ICP备14008679号