1. 程式人生 > >Unity- 實現 Building Plugins for iOS(含Demo)

Unity- 實現 Building Plugins for iOS(含Demo)

這段時間,由於專案需求,需要實現Unity和iOS之間的程式碼互動(如,在Unity中使用iOS原生UI,二者之間方法互調等),故做了相關的技術預研及演示Demo。下文簡單記錄了本次實現,僅供參考。由於本人也是初學Unity,又不足之處望高手指正。

在Unity中使用iOS原生程式碼,其實唯一的方法就是通過外掛的方式,官方文件 Building Plugins for iOS 其實已經對此做了較詳細的闡述(當然也有對應的  )。我想實現的需求,能夠在Unity匯出生成的Xcode專案執行後,螢幕下方使用iOS原生UI--ToolBar,左右各有原生Item進行方法的互動。

Unity中呼叫Objective-C/C++方法

1、[DllImport("__Internal")] 特性

在Unity新建專案中,Progect --> Create --> C# Script ,然後使用 [DllImport("__Internal")] 特性來標識用Objective-C/C++實現的函式。如下:

[DllImport ("__Internal")]
private static extern void ActivateUI_iOS();

而在指令碼中,我選擇在voidStart () 呼叫該方法:

void Start () {
	if (Application.platform == RuntimePlatform.IPhonePlayer) {
		ActivateUI_iOS();
	}
}

指令碼寫好後,新增引用:usingSystem.Runtime.InteropServices ,然後繫結到目標物件(本Demo繫結到 Main Camera,同時建立了球和文字物件作為Unity的顯示)。

2、extern"C" 

在對應的iOS專案檔案 .mm 中對應的用 extern"C"  來標識介面,以及 voidActivateUI_iOS()方法的實現:

extern "C" {
    void ActivateUI_iOS() {
        //Get the applications UIWindow
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        //Create the RootViewController from a XIB file.
        ViewController *rootViewController = [ViewController sharedManager];
        rootViewController.view.frame = window.bounds;
        rootViewController.view.frame = CGRectMake(0, window.bounds.size.height - 44, 320, 44);
        //Add the RootViewController view to the main window.
        [window addSubview: rootViewController.view];
    }
}

因為 extern"C" 是C++語法,故應將.m檔案改為.mm,編譯才能通過。而 ViewController.h/m/xib 實現的就是介面展示的功能(View背景色為透明,才能顯示Unity所展示的):

  

3、檔案匯入Unity專案中,生成Xcode工程,編譯執行

Xcode執行專案沒問題後,將原生程式碼(.a,.m,.mm,.c,.cpp檔案)選中,拖入 Unity --> Project --> Plugins --> iOS 中(不能再有子目錄),然後 File --> Build Settings 生成Xcode 工程編譯執行。你會發現新版Unity已經自動合併這些檔案到Xcode工程的Libraries目錄下。而.h檔案不會被包括在Xcode專案樹之中,但是他們會在最終產生的檔案系統中出現,這樣能支援.m/.mm/.c/.cpp的編譯。注:必須真機執行。效果如下(右圖為點選 ShowAlert 後彈出 AlertView):

    

若執行後沒有展示下面的 ToolBar,請修改生成工程中 UnityAppController.mm -->- (void)showGameUI:(UIWindow*)window 方法。

iOS原生程式碼呼叫Unity的指令碼程式碼

上文已實現了Unity指令碼呼叫iOS原生程式碼,下面來實現在iOS原生程式碼中如何呼叫Unity指令碼方法。

1、UnitySendMessage

Unity iOS版支援利用UnitySendMessage進行簡單的本地管理回撥功能:

UnitySendMessage("GameObjectName1","MethodName1", "Message to send");

這個方法包含三個引數:目標遊戲物件的名稱,呼叫的指令碼方法,傳遞給指令碼方法的資訊字串。

所以,在Demo中,實現點選 ToolBar 右邊的 ChangeText 來改變 Unity中GUIText 物件的顯示(由 Hello World 變為 Building Plugins for iOS)。在ViewController.m檔案中加入ChangeText 點選事件:

-(IBAction)clickItem2:(id)sender
{
    UnitySendMessage("Main Camera", [@"changeLabelShow" UTF8String], [@"Building Plugins for iOS" UTF8String]);
}
對應的Unity指令碼中,實現changeLabelShow 這個方法:
public void changeLabelShow(string textStr){
	textObject.text = textStr;
}
記住先要宣告和關聯這個textObject:
public GUIText textObject;

最後,按照 3 中步驟,真機編譯執行,點選右邊Item後效果如下:

注:

1、只有符合以下結構的指令碼方法才能被從本地方法呼叫:

            function MethoName(message:string)

2、呼叫UnitySendMessage是非同步的,會有1幀的延遲。

總結

1、在Unity中通過外掛的方式實現呼叫iOS原生程式碼。

2、 在Unity中使用原生UI,但是比起在Unity中直接繪製UI,原生UI效率要更低。因為在Unity中繪製UI時, Unity可以儘可能的優化, 用盡量少的draw call去繪製UI, 而NativeUI並不受控制。

3、編譯執行是個麻煩的過程, 從Unity生成一個XCode工程, 然後到XCode編譯完成, 再到載入真機的過程是相當的漫長。機子效能不行的,額。。。自己感受吧。