<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(封装版)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容