美文网首页unity
iOS工程与unity相互调起、交互、传值

iOS工程与unity相互调起、交互、传值

作者: jason825 | 来源:发表于2019-02-17 00:42 被阅读0次

    好长时间没有写了,一直忙没来得及写,继续把上篇已经实现了将Unity导出的工程集成到原生iOS项目中了,接下来实现与Unity相互切换、调起、传值。

    需要注意的是,Unity一旦初始化,是不能关闭的,否则App直接就会被关闭。所以,一旦调起Unity,内存就不会降下来了。第一次启动会比较慢,之后就很快了。另外,集成Unity之后,就只能真机运行了。

    1、之前我们已经在pch中import了UnityAppController,所以其他地方不用再import了。所有的接口建议写在AppDelegate中。

    首先,将AppDelegate.m改名为AppDelegate.mm ,然后,在AppDelegate.h中,如下

    
    #import <UIKit/UIKit.h>
    
    @class UnityAppController;
    
    @interface AppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    @property (strong, nonatomic) UIWindow *unityWindow;
    
    @property (strong, nonatomic) UnityAppController *unityController;
    
    - (void)showUnityWindow;
    
    - (void)hideUnityWindow;
    
    - (void)shouldAttachRenderDelegate;
    
    @end
    
    

    接下来,修改AppDelegate.mm 如有报错,先暂时忽略

    #import "AppDelegate.h"
    
    @interface AppDelegate ()
    {
        //这里的两个BOOL,是用来区分,是否第一次加载Unity,以及Unity视图是否出现
        BOOL _notFirstShow;
        BOOL _isShowing;
    }
    @end
    
    @implementation AppDelegate
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.backgroundColor = [UIColor whiteColor];
        
        self.unityController = [[UnityAppController alloc]init];
        [self.unityController application:application didFinishLaunchingWithOptions:launchOptions];
    }
    - (void)shouldAttachRenderDelegate {}
    - (void)showUnityWindow {
        
        
        if (!_notFirstShow) {
            //第一次启动
            [self.unityController startUnityFirstTime];
            _notFirstShow = YES;
        } else {
            //已经初始化
            [self.unityController startUnityOtherTime];
            
        }
        _isShowing = YES;
        
    }
    - (void)hideUnityWindow {
        [self.unityController doExitSelector];
        //看到这里就明白了,我用的是模态的方式展示的~哈哈哈
        [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
        _isShowing = NO;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application {
        [self.unityController applicationWillResignActive:application];
        
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application {
        
        [self.unityController applicationDidEnterBackground:application];
        
        _backgroundView = [Util createSnapShotView];
        [self.window addSubview:_backgroundView];
        
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application {
        [self.unityController applicationWillEnterForeground:application];
        
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application {
        [self.unityController applicationDidBecomeActive:application];
        
        if (_backgroundView != nil) {
            [_backgroundView removeFromSuperview];
            _backgroundView = nil;
        }
        
        if (_notFirstShow && !_isShowing) {
            //如果unity处于暂停状态,从后台唤醒时也要保持暂停状态
            [self.unityController doExitSelector];
        }
        
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application {
        [self.unityController applicationWillTerminate:application];
        
    }
    
    @end
    
    

    现在来修改UnityAppController.h,添加如下方法

    //自定义开启关闭Unity
    - (void)startUnityFirstTime;
    - (void)startUnityOtherTime;
    - (void)doExitSelector;
    

    找到下面这个方法

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

    替换成如下

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

    接下来修改UnityAppController.mm
    在它引用头文件的最后一行,引入自定义控制器#import "GameViewController.h" 为了放unity,如果没有,创建一个
    接下来找到方法

    - (void)shouldAttachRenderDelegate  {}
    

    实现这个方法

    - (void)shouldAttachRenderDelegate  {
        AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        [delegate shouldAttachRenderDelegate];
    }
    

    找到如下方法

    - (void)applicationDidBecomeActive:(UIApplication*)application
    {
        ::printf("-> applicationDidBecomeActive()\n");
    
        [self removeSnapshotView];
    
        if (_unityAppReady)
        {
            if (UnityIsPaused() && _wasPausedExternal == false)
            {
                UnityWillResume();
                UnityPause(0);
            }
            UnitySetPlayerFocus(1);
        }
        else if (!_startUnityScheduled)
        {
            _startUnityScheduled = true;
            [self performSelector: @selector(startUnity:) withObject: application afterDelay: 0];
        }
    
        _didResignActive = false;
    }
    

    改成如下

    //首先在这个方法上面声明一个bool变量
    bool homePageEnable = true;
    //修改这个方法
    - (void)applicationDidBecomeActive:(UIApplication*)application
    {
        ::printf("-> applicationDidBecomeActive()\n");
        
        if(_snapshotView)
        {
            [_snapshotView removeFromSuperview];
            _snapshotView = nil;
        }
        if (homePageEnable) {
            homePageEnable = false;
            [self performSelector:@selector(startHomePage:) withObject:application afterDelay:0];
        }
        if(_unityAppReady)
        {
            if(UnityIsPaused())
            {
                UnityPause(0);
                UnityWillResume();
            }
            UnitySetPlayerFocus(1);
        }
        else if(!_startUnityScheduled)
        {
            _startUnityScheduled = true;
        }
        
        _didResignActive = false;
    }
    
    - (void)startHomePage:(UIApplication *)application {
        AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        [delegate.window makeKeyAndVisible];
    }
    
    - (void)startUnityFirstTime {
        [self startUnity:[UIApplication sharedApplication]];
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[[GameViewController alloc] init] animated:YES completion:nil];
    }
    
    - (void)startUnityOtherTime {
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[[GameViewController alloc] init] animated:YES completion:nil];
        if (_didResignActive) {
            UnityPause(false);
        }
        _didResignActive = false;
    }
    
    - (void)doExitSelector {
        UnityPause(true);
        _didResignActive = true;
        Profiler_UninitProfiler();
    }
    

    接下来找到刚才创建的GameViewController.h

    #import <UIKit/UIKit.h>
    
    @interface GameViewController : UIViewController
    
    @property (strong, nonatomic) UnityAppController *unityController;
    @property (strong, nonatomic) UIWindow *unityWindow;
    
    @end
    

    然后在GameViewController.m中,导入#import "UnityAppController.h"

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.view.backgroundColor = [UIColor whiteColor];
    
        
        [self.view addSubview:UnityGetMainWindow().rootViewController.view];
        [self addChildViewController:UnityGetMainWindow().rootViewController];
        
    }
    

    接下来就是调起Unity、关闭Unity、相互传值(交互)
    调起Unity:
    调起是很方便的,因为是从原生跳转过去,比如点击某个按钮,那么只需在按钮的点击方法中调用就可以了:

    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    [delegate showUnityWindow];
    

    这样就会模态出来Unity的界面
    关闭Unity:
    接下来是关闭Unity,对于返回原生,要在做处理的GameViewController这个方法里进行处理_BackBtnPress这个方法名是需要和unity那边点击方法名一致

    void _BackBtnPress(){
        
        AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        [delegate hideUnityWindow];
        
    }
    

    传值呢,很简单,就一句话,Unity那边做接收就可以了

    //第一个参数:消息的接受者,或者说谁来执行方法
    //第二个参数:函数名
    //第三个参数:需要传的值
    UnitySendMessage("ReceiveiOSMessage", "ReceiveiOSInputMessage", _unityStr);
    //注意,三个参数都是C语言字符串,没有@哦
    

    OK啦~~

    相关文章

      网友评论

        本文标题:iOS工程与unity相互调起、交互、传值

        本文链接:https://www.haomeiwen.com/subject/cueweqtx.html