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編譯完成, 再到載入真機的過程是相當的漫長。機子效能不行的,額。。。自己感受吧。