2012年2月3日 星期五

Unity 3D Plug-in for Android 開發指南

這是一個摸索筆記。

以下是正文。

一. Unity3D Plug-in 必須知道的概念

Unity 的 Plug-in 是以二進位存在的,所以,在不同的平台上,必須開發不同的 Plug-in,例如,在 PC Windows 平台,使用 dll 檔,在 Android 系統,使用 .so 檔。

在使用 Unity 開發專案時,因為是在 PC Windows 平台上操作,所以當使用了 Android 的 .so 檔時,會造成無法在 Unity Editor 中即時操作遊戲的問題。至於是否可以有個取代方案,例如,另外寫個相同功能的 dll 檔來在 PC Windows 平台上操作,這要再做進一步測試。

二. Unity3D Plug-in 的安裝

Unity 的官方文件,是建議將 Plug-in 複製到專案的 Assets/Plugins/Android 目錄下,如果沒這個目錄,就自行建立一個。

所以,就是將寫好編譯好的 .so 檔,複製到這個目錄下就可。

官方文件上有一個模稜兩可的說法,說 Plug-in 安裝後,Unity 會自動抓出其中的 Java Class 什麼的,不要相信它,因為完全試不出來。

三. Unity3D Plug-in 的使用

.so 檔複製到專案以後,是無法取得任何資料的。必須透過 C# Script 來載入。 官方文件中,只提供了使用 C# Script 來參考 Plug-in 的方法,找不到 Java Script 的方法,所以就先以 C# Script來做。

官方網站上有一個可以參考的範例,"AndroidNativePlugin.zip",可以下載來參考。

zip 檔解開後,將 unity package import 進 Unity Editor,可以抓到 .so 檔,原始程式碼,以及使用 Plug-in 的 C# Script。

C# Script 如下 (已經改過了)

using UnityEngine;

using System.Collections;

using System.Runtime.InteropServices;

public class CallNativeCode : MonoBehaviour {

public GUISkin mySkin;

[DllImport("ttt")]

private static extern float add(float x, float y);

void OnGUI ()

{

GUI.skin = mySkin;

float x = 3;

float y = 10;

GUI.Label (new Rect (15, 125, 450, 100), "add" + x + " and " + y + " equals " + add(x,y));

}

}

幾個重點:

1. [DllImport(“ttt”)] : 這行程式,是負責載入 Plug-in,依照官方規定,這個Plug-in 的檔名是 libttt.so,也就是,前綴必須有”lib” 三個字母,後面是 .so 副檔名。

2. private static extern float add(float x, float y); -- 這一行是宣告Plug-in中的函式。

3. 載入與宣告函式完成後,在 Script 的 OnGUI 函式中,就可以使用這個函式了。

四. Android Plug-in 的開發

接著就是,.so 這個檔怎麼做出來了。

.so 檔,可以視作是 Android 系統上的 Dynamic Load Library (dll)

1. 建立開發環境

一般書籍或網站上找到的 Android 應用開發,多是以 Java 環境來做的,這是無法編譯 .so 檔案的。

Android 的 Development Kit 有兩種,一種是 SDK (Software Development Kit), 一種是 NDK (Native Development Kit),編譯 .so 檔,需要 NDK。

傳統的建立開發環境的方法是,要安裝 cygwin (Windows 上的 Linux 模擬器)、NDK、SDK、Eclipse IDE 等等,現在有個神人把整個開發環境整合到了 Visual Studio 2010上,所以建立開發環境的方法,就以整合 VS 2010 來做了。

vs-android -- Integrated development of Android NDK C/C++ software under Visual Studio

下載vs-android,sample solution,然後下載 Android NDK (r7 or later),SDK,Java SDK (32 bits版),以及 Ant。

需要安裝的安裝,可以解壓縮複製的,就解壓縮複製。( Android SDK 的安裝,比較複雜些,請找資料看看 )

然後要設定幾個環境變數

ANDROID_HOME : Android SDK 的根目錄位置,例如 C:\Develop\android-sdks

ANDROID_NDK_ROOT : Android NDK 的根目錄位置,例如 C:\Develop\android-ndk-r7

ANT_HOME : Apache Ant 的目錄,例如 C:\Develop\apache-ant-1.8.2

2. 測試範例程式 san-angeles

設定完成,打開 VS 2010,載入 Sample Solution,USB接上測試用設備,Build Solution,然後就 OK 了。

<< 不過,還是會碰到編譯不過的情形啦。以下是幾個可能要處理的狀況。

a.
Unable to resolve target 'android-4'
    因為在 SDK中的 Platform 版本裡沒有安裝 API Level 4,修改 project.properties 這個檔案中的 target=android-4,改為 SDK 有安裝的API

b.
ANTBUILD : [dx] error : Could not create the Java Virtual Machine.
ANTBUILD : [dx] error : A fatal exception has occurred. Program will exit.
[dx] Error occurred during initialization of VM
[dx] Could not reserve enough space for object heap
這問題,打開 android-sdks\platform-tools 目錄中的 dx.bat 檔案,將
set defaultXmx=-Xmx1024M
改為
set defaultXmx=-Xmx512M

>>

3. 建立要編譯 .so 檔的專案

因為 vs-android 的神人作者,還沒有寫好 Project Wizard,所以,要靠半手動的方式來建立新專案。

簡單一點的做法是,就在範例程式 solution 下新加入一個專案,選擇 Win32 Console App,然後建立 Empty Project。

Project 的名稱,以 lib 開始,符合 Unity Plug-in 的規則。例如,libunityplug1

專案建立完成,開啟專案的 Property Page,點選 Configuration Manager

clip_image004

新建立的專案還是 Win32 Platform,點選專案的 Platform 下拉箭頭,選擇 <<New>>,建立新的專案 Platform。

clip_image006

Platform 選擇 Android, Copy Setting 選擇 <Empty>,底下的 Create new solution platforms 要取消打勾。

然後按下 OK

新專案的 Project Platform 就會改成 Android,而專案中的 Property 也會自動調整為 Android 平台相關的設定。

因為要產生的是 Dynamic Library ( .so ) 檔,所以,將 Configuration Type 調整為 Dynamic Library。

clip_image008

其他的 API Level, Architecture,有需要也可以改看看。

然後就開始加入原始程式碼檔案吧!!

4. Plug-in 程式碼與使用

很快,隨便寫了個 .c 的程式

float multiply(float x, float y)

{

return x * y;

}

然後 Build 這個 libunityplug1 專案,沒問題的話,會得到 libunityplug1.so 的檔案,把 .so 檔案複製到 Unity 的 Assets/Plugins/Android 目錄下

修改 Unity C# Script

[DllImport("unityplug1")]

private static extern float multiply(float x, float y);

然後,就可以使用這個函式了。