<iOS和Unity交互>之界面跳轉

本文介紹了iOS和Unity交互,主要涉及兩個界面之間的跳轉.

如果對iOS和Unity交互傳參方法不熟悉的朋友,可以參考我的另一篇文章
<iOS和Unity交互>之參數傳遞

一.程序啟動入口.

  • main.mm
    了解OC或者C的朋友一定知道main方法,這是整個程序的入口.以下是Unity轉iOS工程后的main文件中的部分代碼.
  const char* AppControllerClassName = "UnityAppController";

  int main(int argc, char* argv[])
{
    @autoreleasepool
    {
        UnityInitTrampoline();
        UnityParseCommandLine(argc, argv);

        RegisterMonoModules();
        NSLog(@"-> registered mono modules %p\n", &constsection);
        RegisterFeatures();

        std::signal(SIGPIPE, SIG_IGN);
                
        // 程序啟動入口
        UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
    }

    return 0;
    }

根據代碼得知,程序需要創建UnityAppController對象.那么,程序就來到了UnityAppController文件.
在UnityAppController.mm文件中的以下方法中添加打印:NSLog(@"%s",__func__);

  - (id)init
  - (void)startUnity:(UIApplication*)application
  - (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  - (void)applicationDidBecomeActive:(UIApplication*)application

打印結果為:

2017-05-24 04:50:09.597338+0800 ProductName[5622:1888712] [DYMTLInitPlatform] platform initialization successful
2017-05-24 04:50:09.693476+0800 ProductName[5622:1888655] -> registered mono modules 0x100df3fa0
2017-05-24 04:50:09.714814+0800 ProductName[5622:1888655](標記) -[UnityAppController init]
2017-05-24 04:50:09.930542+0800 ProductName[5622:1888655] -[UnityAppController application:willFinishLaunchingWithOptions:]
2017-05-24 04:50:09.931002+0800 ProductName[5622:1888655](標記) -[UnityAppController application:didFinishLaunchingWithOptions:]
-> applicationDidFinishLaunching()
2017-05-24 04:50:10.013760+0800 ProductName[5622:1888655] Metal GPU Frame Capture Enabled
2017-05-24 04:50:10.014789+0800 ProductName[5622:1888655] Metal API Validation Enabled
2017-05-24 04:50:10.178127+0800 ProductName[5622:1888655](標記) -[UnityAppController applicationDidBecomeActive:]
-> applicationDidBecomeActive()
2017-05-24 04:50:10.190176+0800 ProductName[5622:1888655](標記) -[UnityAppController startUnity:]
Init: screen size 640x1136
Initializing Metal device caps: Apple A7 GPU
Initialize engine version: 5.3.5f1 (960ebf59018a)
UnloadTime: 2.714958 ms
Setting up 1 worker threads for Enlighten.
Thread -> id: 16ea3b000 -> priority: 1 

根據帶(標記)的打印結果得知
1.程序會先調用- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法,進行Unity界面初始化并布局UI.
2.準備激活Unity,已激活程序則調用- (void)applicationDidBecomeActive:(UIApplication*)application方法,方法中設置了UnityPause(0);表示Unity為啟動狀態,在方法最后,執行[self performSelector:@selector(startUnity:) withObject:application afterDelay:0];.
3.調用- (void)startUnity:(UIApplication*)application方法,展示Unity界面.

二.Unity跳轉iOS界面.

  • 程序啟動為Unity界面,通過點擊跳轉iOS按鈕,調用unityToIOS方法創建iOS界面并將iOS創建的控制器設置為窗口的跟控制器.以實現跳轉iOS界面.
    .cs代碼
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using SClassLibrary;

  public class Test : MonoBehaviour
{
    public GameObject cube;

    // DllImport這個方法相當于是告訴Unity,有一個unityToIOS函數在外部會實現。
    // 使用這個方法必須要導入System.Runtime.InteropServices;
    [DllImport("__Internal")]
    private static extern void unityToIOS(string str);

    // 向右轉函數接口
    public void turnRight(string num)
    {
        float f;
        if (float.TryParse(num, out f))
        {// 將string轉換為float,IOS傳遞數據只能用以string類型
            Vector3 r = new Vector3(cube.transform.rotation.x, cube.transform.rotation.y + f, cube.transform.rotation.z);
            cube.transform.Rotate(r);
        }
    }
    // 向左轉函數接口
    public void turnLeft(string num)
    {
        float f;
        if (float.TryParse(num, out f))
        {// 將string轉換為float,IOS傳遞數據只能用以string類型
            Vector3 r = new Vector3(cube.transform.rotation.x, cube.transform.rotation.y - f, cube.transform.rotation.z);
            cube.transform.Rotate(r);
        }
    }

    public void DllTest()
    {
        var user = new User
        {
            Id = 1,
            Name = "張三"
        };
  #if UNITY_IPHONE && !UNITY_EDITOR
        unityToIOS(user.ToString());
  #else
        Debug.Log(user.ToString());
  #endif
    }
  }
  • 添加屬性,該屬性用來保存創建的iOS控制器(盡量設置為私有屬性)
@interface UnityAppController ()
@property (nonatomic, strong) UIViewController *vc;
@end
  • Unity會調用unityToIOS方法,跳轉iOS界面之前,先暫停Unity,即UnityPause(true);方法.因為在C語言中,不能直接使用self調用對象方法.所以需要通過GetAppController()調用setupIOS方法.GetAppController()即UnityAppController類型的對象.在setupIOS方法中,讓
    UnityAppController對象持有vc后,再將vc直接設置為窗口的跟控制器GetAppController().window.rootViewController = GetAppController().vc;
  • unityToIOS方法
// 跳轉iOS界面
 extern "C" void unityToIOS(char *str)
 {
     // Unity傳遞過來的參數
     NSLog(@"%s",str);
     UnityPause(true);
     
     // GetAppController()獲取appController,相當于self
     // 設置iOS界面,GetAppController()獲取appController,相當于self
     [GetAppController() setupIOS];
     
     // 點擊按鈕后跳轉到IOS界面,設置窗口的跟控制器為iOS的控制
     GetAppController().window.rootViewController = GetAppController().vc;
 }
  • setupIOS 方法
// 設置iOS界面
  - (void)setupIOS
 {
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor greenColor];
    vc.view.frame = [UIScreen mainScreen].bounds;
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(70, 530, 180, 30)];
    btn.backgroundColor = [UIColor whiteColor];
    [btn setTitle:@"跳轉到Unity界面" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(setupUnity) forControlEvents:UIControlEventTouchUpInside];
    
    [vc.view addSubview:btn];
     
     self.vc = vc;
     NSLog(@"設置界面為IOS界面");
     self.window.rootViewController = vc;
 }

說明:
1.GetAppController()
跳轉到GetAppController()方法內部,實現如下,可以看出,該方法獲取到UIApplication的單例類,而它的代理,則為UnityAppController對象,最后再使用(UnityAppController*)進行強制轉換.所以,在UnityAppController.mm文件中使用GetAppController()相當于self.

inline UnityAppController *GetAppController()
{
    return (UnityAppController*)[UIApplication sharedApplication].delegate;
}

2.UnityGetGLViewController()
返回Unity的根控制器,根控制器上的視圖是Unity的視圖.,如果將窗口的根控制器設置為UnityGetGLViewController(),其實就是將Unity界面顯示在手機上.

extern "C" UIViewController *UnityGetGLViewController()
{
     return GetAppController().rootViewController; 
}

3.UnityGetGLView()
返回Unity視圖,這個視圖其實就是顯示在UnityGetGLViewController()上的.

extern "C" UIView *UnityGetGLView()
{
    return GetAppController().unityView; 
}

三.iOS跳轉Unity界面.

  • 實現iOS界面中的按鈕的方法.來跳轉到Unity界面.self.rootViewController的作用相當于GetAppController().rootViewController,然后設置window的rootViewController為Unity的跟控制器
  • setupUnity 方法
// 設置Unity界面
 - (void)setupUnity
 {
     // 設置Unity狀態為開啟狀態
     UnityPause(false);
     
     // 設置rootViewController為Unity的跟控制器
     self.window.rootViewController = self.rootViewController;
     // 等同于
     // self.window.rootViewController = UnityGetGLViewController();
     NSLog(@"設置rootView為Unity界面");
 }

四.封裝界面跳轉代碼.

  • 查看UnityAppController.mm文件,發現其中代碼太多,為了減少代碼以及便于我們管理和維護,我們要創建一個單例類來管理Unity和iOS界面互相跳轉的操作.之前在UnityAppController.mm文件中寫的代碼全部刪除.
    1.需要創建一個自定義類,如:BYJumpEachOther,繼承至NSObject.
    2.添加屬性
  // 存儲的iOS控制器
  @property (nonatomic, strong) UIViewController *vc;

3.入口:unityToIOS,與之前不同的是,調用setupIOS方法,改為單例對象去調用[[BYJumpEachOther sharedInstance] setupIOS];獲取vc也通過單例對象去獲取.

// 跳轉iOS界面
extern "C" void unityToIOS(char *str)
{
    // Unity傳遞過來的參數
    NSLog(@"%s",str);

    // 跳轉到IOS界面,Unity界面暫停
    UnityPause(true);
    
    // GetAppController()獲取UnityAppController對象
    // UnityGetGLView()獲取UnityView對象,相當于_window
    
    [[BYJumpEachOther sharedInstance] setupIOS];
    
    // 點擊按鈕后跳轉到IOS界面,設置界面為IOS界面
    GetAppController().window.rootViewController = [BYJumpEachOther sharedInstance].vc;
}

4.添加BYJumpEachOther創建單例的方法

  + (instancetype)sharedInstance
{
    static BYJumpEachOther *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[BYJumpEachOther alloc] init];
    });
    return instance;
}

5.跳轉iOS界面代碼

// 設置iOS界面
  - (void)setupIOS
{
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor greenColor];
    vc.view.frame = [UIScreen mainScreen].bounds;
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(70, 530, 180, 30)];
    btn.backgroundColor = [UIColor whiteColor];
    [btn setTitle:@"跳轉到Unity界面" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(setupUnity) forControlEvents:UIControlEventTouchUpInside];
    
    [vc.view addSubview:btn];
    
    self.vc = vc;
    NSLog(@"設置界面為IOS界面");
    
    GetAppController().window.rootViewController = vc;
}

6.跳轉Unity界面代碼

// 設置Unity界面
  - (void)setupUnity
{
    UnityPause(false);
    
    GetAppController().window.rootViewController = UnityGetGLViewController();
    // 等同于
    // GetAppController().window.rootViewController = GetAppController().rootViewController;
    NSLog(@"設置rootView為Unity界面");
}

CSDN

iOS和Unity交互之界面跳轉

個人博客

iOS和Unity交互之界面跳轉

GitHub

iOS和Unity界面交互Demo(未封裝版)
iOS和Unity界面交互Demo(封裝版)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容