[Unity]Plugin建立過程 - JAR

Version:
  1.Unity                        : 3.5.7f6
  2.Anddroid                 : 2.3.3
  3.Android SDK Tools : r22
  4.Eclipse                     : Juno SR2

 這邊使用簡單的計算範例來呈現,如何建立要給Unity使用的Plugin。 這邊的Plugin是使用JAR。

 1.建立新的Android專案 
    I.在Eclipse介面上,點選「File」->「New」->「Project」。

    II.選擇「Android Application Project」。


    III.設定相關設定,這邊就依個人的需求,自行設定即可。

    IV.專案建立過程中,[Create custom launcher icon]與[Create activity]預設都會被勾選。但是目前並用不到這兩個設定,所以在這裡就把這兩個設定設定為不選擇。



    V.取消[Create custom launcher icon]與[Create activity]後,按下「Finish」按鈕,就可以完成專案建立的流程了。


    VI.建立好的專案架構如下圖


    VII.加入新的[Package]:於[src]上按下滑鼠右鍵->[New]->[Package]


    VIII.設定[Package]的名稱,[Package]的名稱會在Unity內使用到。


    IX.新增[Class]給[Package]在新建立好的[package]上按下滑鼠右鍵->[New]->[Class]


    X.設定[Class]的名稱,這邊設定的名稱之後也會在Unity內使用到。


    XI.建立想要使用的功能的程式碼
         A.Number Adder:
package com.calculator.numberincreasing;  
 public class NumberAdder   
 {  
     public int Add(int base, int factor)  
     {  
         return (base + factor);  
     }  
 }  


         B.Number Multiple:
package com.calculator.numberincreasing;  
 public class NumberMultipler   
 {  
     public int Multiple(int base, int rate)  
     {  
         return (base * rate);  
     }  
 }  


    XII.程式碼編寫完成後,就可以透過[Export]的方式將程式封裝,並交給Unity使用。
           專案上按滑鼠右鍵->[Export]。

    XIII.選擇[Java]->[JAR File]

    XIV.把要匯出的資料勾選起來,這邊預設會勾選所有的資料夾。 然後指定JAR檔要輸出的位置即可。

2.如何在Unity內使用JAR檔內的方法:
I.把JAR檔放到"./Asset/Plugins/Android/"下即可。(Plugins與Android資料夾皆需要自行建立)

II.建立操作用的Script
public class Calculator : MonoBehaviour   
 {  
     private int Org = 10;  
     private int factor = 20;  
     private int Mutiple = 30;  
     private int Added = 0;  
     private int Mutiplier = 0;  
     private AndroidJavaObject    mCal = null;  
     // Use this for initialization  
     void Start ()   
     {          
     //產生NumberAdder物件  
         this.mCal = new AndroidJavaObject("com.calculator.numberincreasing.NumberAdder");  
     //建立傳入參數陣列  
         object[] arglist = new object[2];  
         arglist[0] = (object)this.Org;  
         arglist[1] = (object)this.factor;  
     //呼叫方法,並取得回傳值  
         this.Added = this.mCal.Call<int>("Add", arglist);          
         this.mCal = new AndroidJavaObject("com.calculator.numberincreasing.NumberMultipler");          
         arglist[0] = (object)this.Org;  
         arglist[1] = (object)this.Mutiple;  
         this.Mutiplier = this.mCal.Call<int>("Multiple", arglist);  
     }  

//輸出測試結果
     void OnGUI()  
     {  
         GUI.Label(new Rect(100.0f, 100.0f, 100.0f, 50.0f), string.Format("Org = {0}\nAdded = {1}\nMultipled = {2}", this.Org, this.Added, this.Mutiplier));  
     }  
 }  

   如果要使用JAR檔內的類別,需要透過AndroidJavaObject來產生目標類別的物件。 在產生AndroidJavaObject時所傳入的名稱為Package名稱與Class名稱的合稱。(Package = com.calculator.numberincreasing, Class = NumberAdder. Package.Class = com.calculator.numberincreasing.NumberAdder) 之後再使用AndroidJavaObject.Call()來操作指定的函式。

III.產生apk檔,並安裝到Android裝置內。

  透過上述方式,就可以把一些方法封裝到其它的Package內。然後就可以給其它的專案使用。
  如有需要使用到一些Android的API,也可以透過Plugins的方式來使用。

5 comments:

  1. 我照著上面的步驟做,
    最後出現這個訊息,
    請問這可能是哪邊有問題呢?

    Exception: JNI: Init'd AndroidJavaClass with null ptr!
    UnityEngine.AndroidJavaClass..ctor (IntPtr jclass) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/Export/AndroidJavaImpl.cs:533)
    UnityEngine.AndroidJavaObject.get_JavaLangClass () (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/Export/AndroidJavaImpl.cs:511)
    UnityEngine.AndroidJavaObject.FindClass (System.String name) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/Export/AndroidJavaImpl.cs:502)
    UnityEngine.AndroidJavaClass._AndroidJavaClass (System.String className) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/Export/AndroidJavaImpl.cs:522)
    UnityEngine.AndroidJavaClass..ctor (System.String className) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/ExportGenerated/Editor/AndroidJava.cs:91)
    Main..ctor ()

    ReplyDelete
    Replies
    1. 您好:
      您所提出的問題,我是沒有遇過。
      不過根據您所提供的錯誤訊息( Init'd AndroidJavaClass with null ptr!),我去google查了一下。
      得到的結果有以下幾點:
      1.可能是Unity指定輸出的Platform不是Android
      2.在new AndroidJavaObject()時所指定的packagename.classname並沒有存在所包裝的package內。

      請問您是把上述整個測試用的程式碼直接複製貼到新的專案去嗎?
      或是可以麻煩您提供您的專案,這樣比較容易抓問題。

      Delete
  2. 請問一下
    如果我的Jar裡面的涵式想要回傳一個string"陣列"(string[])可以嗎?
    我傳其它的像是string, int都可以正常的傳回來, 但是在傳陣列的時候都沒反應,我也不知道該從哪邊看才好。

    ReplyDelete
  3. 我在jar裡面的函式是長這樣
    private List mTestList = new LinkedList();
    public void InitTestList()
    {
    mTestList.add("abc");
    mTestList.add("def");
    mTestList.add("ghi");
    }
    public String GetTestList(int index)
    {
    try
    {
    return mTestList.get(index);
    }
    catch(IndexOutOfBoundsException ex)
    {
    return "";
    }
    }
    public String[] GetTestListAy()
    {
    return (String[]) mTestList.toArray();
    }

    我在Unity裡Call GetTestList(int index)的時候是可以正常拿到string的
    但是string[] tempay = mPlugin.Call("GetTestListAy");
    的時候好像都沒拿到東西。

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete

Build docker image from multiple build contexts

Build docker image from multiple build contexts ...