天天看点

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 ;
   }
           

根据代码得知,程序需要创建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
           

打印结果为:

-- ::+ ProductName[:] [DYMTLInitPlatform] platform initialization successful
-- ::+ ProductName[:] -> registered mono modules 
-- ::+ ProductName[:](标记) -[UnityAppController init]
-- ::+ ProductName[:] -[UnityAppController application:willFinishLaunchingWithOptions:]
-- ::+ ProductName[:](标记) -[UnityAppController application:didFinishLaunchingWithOptions:]
-> applicationDidFinishLaunching()
-- ::+ ProductName[:] Metal GPU Frame Capture Enabled
-- ::+ ProductName[:] Metal API Validation Enabled
-- ::+ ProductName[:](标记) -[UnityAppController applicationDidBecomeActive:]
-> applicationDidBecomeActive()
-- ::+ ProductName[:](标记) -[UnityAppController startUnity:]
Init: screen size x1136
Initializing Metal device caps: Apple A7 GPU
Initialize engine version: 1 (ebf59018a)
UnloadTime:  ms
Setting up  worker threads for Enlighten.
Thread -> id: ea3b000 -> priority:  
           

根据带

(标记)

的打印结果得知

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 = ,
            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(, , , )];
    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(, , , )];
    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界面");
}
           

简书

iOS和Unity交互之界面跳转

个人博客

iOS和Unity交互之参数传递

GitHub

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

iOS和Unity界面交互(封装版)