最近游戲組讓配合開發一個 “在Unity中點擊按鈕彈出原生二維碼掃碼頁面 -> 再把獲取到的二維碼信息傳回給Unity” 的功能,于是我就開始了學習iOS與Unity3d交互的不歸路~。
由于對Unity不熟,導出的Xcode工程跟平時用的Xcode也有些差異,遇到了很多沒遇到過的問題,只能慢慢摸索,慢慢解決。
剛開始在網上下載下來的Xcode Demo無法在真機上運行(在模擬器上正常)、添加不了Pod,只好自己新建一個干凈的Unity工程,仿照Unity Demo編寫交互代碼再重新導出Xcode工程,沒有問題了再對接二維碼掃碼的功能。
一、代碼實現:
1、Unity代碼:
添加一個C#文件,添加實現代碼。
// Unity代碼
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class Test : MonoBehaviour {
? ? public GameObject cube;
? ? // DllImport這個方法相當于是告訴Unity,有一個unityToIOS函數在外部會實現。
? ? // 使用這個方法必須要導入System.Runtime.InteropServices;
? ? [DllImport("__Internal")]
? ? private static extern void unityToIOS ( string str );
? ? public string scanStatus;//二維碼掃描結果
? ? void OnGUI(){
?????????// 當點擊按鈕后,調用外部方法
?????????if (GUI.Button (new Rect (100, 100, 200, 60), "跳轉IOS")) {
?? ????????? // Unity調用ios函數,同時傳遞數據
?? ? ????????unityToIOS ("Hello IOS");
?????????}
? ? ? ? //控件要寫在GUI里面 可以設置一個全局str,賦值,OnGUI是每秒都會自動刷新。
? ? ? ?GUI.Label (new Rect (100, 200, 400, 60), scanStatus);?
? ? }
? ? // 用戶取消了掃碼
? ? void cancelScan(string str){
?????????scanStatus = str;
? ? }
? ? // 獲取二維碼成功
? ? void getQRSuccess(string str){
?????????scanStatus = @"二維碼內容:" + str;
? ? }
? ? // 向右轉函數接口
? ? void turnRight(string num){
?????????float f;
?????????if (float.TryParse (num, out f)) {// 將string轉換為float,數據之間的傳遞只能以string類型
?? ? ????????Vector3 r = new Vector3 (cube.transform.rotation.x, cube.transform.rotation.y - 10f, cube.transform.rotation.z);
?? ? ????????cube.transform.Rotate (r);
?????????}?
}}
2、iOS代碼:
iOS端主要在UnityAppController.mm文件中編寫代碼 (創建一個LARManager.h文件并創建一些交互方法)。
// MARK: - 直接加載unity頁面
- (void)startUnity:(UIApplication*)application{
? ? //新增代碼
? ? [self showUnityPage];
? ? /* 隱藏了一些Unity代碼 */
}
// MARK: - 展示Unity頁面
- (void)showUnityPage {
? ? if ([LARManager sharedInstance].unityIsPaused) {
? ? ? ? UnityPause(false);//打開Unity
? ? ? ? [LARManager sharedInstance].unityIsPaused = NO;
? ? ? ? //設置rootView為Unity界面
? ? ? ? self.window.rootViewController = self.rootViewController;
?}}
iOS調用Unity:通過UnitySendMessage方法實現。
UnitySendMessage("gameobject", "Method", msg);
參數一為unity腳本掛載的gameobject
參數二為unity腳本中要調用的方法名
參數三為傳遞的數據,*注意:傳遞的數據只能是char 類型
// MARK: - iOS傳遞事件給Unity ScanDelegate
//取消掃描
- (void)cancelScan {
? ? [self showUnityPage];
? ? UnitySendMessage("Main Camera", "cancelScan", [@"取消掃描" UTF8String]);
}
//獲取二維碼信息成功
- (void)getQRSuccess:(NSString *)str{
? ? [self showUnityPage];
? ? UnitySendMessage("Main Camera", "getQRSuccess", [str UTF8String]);
}
- (void)turnRight{//右轉
? ? const char* str = [[NSString stringWithFormat:@"10"] UTF8String];
? ? UnitySendMessage("Main Camera", "turnRight", str);//IOS調用Unity的方法,通過UnitySendMessage方法實現。
}
- (void)turnLeft{//左轉
? ? const char* str = [[NSString stringWithFormat:@"10"] UTF8String];
? ? UnitySendMessage("Main Camera", "turnLeft", str);
}
Unity調用iOS:實現Unity的調用方法
// MARK: - Unity傳遞事件給iOS (跳轉到iOS界面,Unity界面暫停)
extern "C"{
? ? void unityToIOS(char* str){// 對Unity中的unityToIOS方法進行實現
? ? ? ? NSLog(@"*************%s",str);// Unity傳遞過來的參數
? ? ? ? UnityPause(true);//暫停Unity
? ? ? ? [LARManager sharedInstance].unityIsPaused = YES;
? ? ? ? //掃碼頁面
? ? ? ? ScanController *vc = [ScanController new];
? ? ? ? vc.delegate = GetAppController().self;//添加代理
? ? ? ? GetAppController().scanVC = vc;
? ? ? ? // GetAppController()獲取appController,相當于self; UnityGetGLView()獲取UnityView,相當于_window; 點擊按鈕后跳轉到IOS界面,設置界面為IOS界面
? ? ? ? GetAppController().window.rootViewController = GetAppController().scanVC;
}}
二、遇到的問題:
1、在Unity中: C#腳本Test和控件Cube要建立好綁定關系,不然無效.
2、(巨坑:浪費了我不少時間~.~)
Xcode:打包出來沒有在IOS中實現Unity定義的交互函數,運行Xcode就報錯,還以為是在網上下載的demo代碼有問題。
原因:
沒有實現Unity定義的交互函數_unityToIOS
解決:
在?extern "C”{中實現相關函數
3、把IOS代碼拖入工程后運行__weak typeof(self) wSelf = self聲明報錯:
a parameter list without types is only allowed in a function definition。
原因:
可能是編譯器識別不了typeof關鍵字
解決:
Apple LLVM 6.1 - Language設置C Language Dialect為Compiler Default或者GNU99[-std=gnu99]
4、繼續報錯
Undefined symbols for architecture arm64: "_kCGImagePropertyExifDictionary", referenced from: -[SGQRCodeObtain captureOutput:didOutputSampleBuffer:fromConnection:] in SGQRCodeObtain.o
原因:
引用第三方庫時是直接把代碼拖進工程的,可能漏了某些文件.
解決:
直接用pod導入第三方庫.
5、用到了相機、相冊或其他功能忘記添加訪問權限配置,導致閃退
解決:
要在info.plist中添加訪問權限配置
三、拓展:
1、Unity導出Xcode工程:
下載好Unity項目并打開?-> File -> Building Setting -> iOS-> Switch Platform -> Add Open Scenes -> Player Setting -> .NET 2.0 -> Build
a、首先在File->Build Settings
b、選擇iOS,第一次裝的時候需要先下載一個iOS支持文件,下載完成后安裝。
重啟unity->Build(release)
這樣就創建成功一個蘋果工程了
選擇iOS后要點擊Switch Platform,不然打不了iOS包
點擊player settings->Target SDK可以選擇映射出來的蘋果項目是運行于模擬器的還是真機的。
2、打包上架遇坑:
在給游戲打蘋果包的時候,發現在最后一步一直顯示Compiling bitcode超時
原因:
Enable Bitcode設置的YES,工程進行了Bitcode編譯很耗時。我查看了其他工程都是設置的NO
解決:
Build Settings->Enable Bitcode設置為NO
3、探索:(待完善)
游戲端的代碼更新了,可不可以做到直接在原有的Xcode工程上替換unity相關文件,而不需要每次都重新生成Xcode工程,再在新工程上重新寫一遍IOS代碼;
如果必須每次都寫一遍的話,那就把代碼封裝到工具類中,每次只需要拖入工具并改少量的代碼就行。把iOS代碼復用性做到最高,耦合性降到最低。
掃碼相關的內容就不細說了,可以下載我的代碼?MyUnityToIOS了解 提取碼:feeg。里面有Unity和Xcode兩端的代碼,感興趣的可以自己下載下來慢慢看~.~
資料