赞
踩
Unity发布到iOS平台得到的是一个Xcode工程,这个Xcode工程可以直接编译运行,但是我们现在已经有个iOS项目了,Unity是作为项目的一部分,所以需要在已有的Xcode工程中集成Unity。
环境:Xcode 9 + Unity 2017。
Unity导出时设置图形API不要用Metal,因为我发现按我的集成方法使用Metal会崩,不知道什么原因。
下图为Unity发布得到的Xcode工程,红框中是我们要添加到自己的项目的文件夹。
Copy items if needed
,并选择Create groups
。(这里我把Unity相关的文件都放入了Unity逻辑文件夹下,便于管理,话说Xcode 9终于默认创建物理文件夹了,老版本默认创建的是逻辑文件夹,逻辑文件夹只在Xcode中显示,在Finder中是看不到的)
Copy items if needed
,并选择Create folder references
。Remove References
。Move To Trash
,因为我们使用自己的main文件,main.mm中有一些Unity初始化的代码,我将其放入了UnityController.mm中,下文会说到。Classes下的UnityAppController类就是用于启动、显示Unity界面的类,不过它创建的是全屏界面,而我们需要的是让Unity只占整个界面的一部分,所以需要修改;我的方法是自己建一个类继承它,从而自定义自己的方法,代码如下:
// // UnityController.h // #import "UnityAppController.h" @interface UnityController : UnityAppController @property (nonatomic, readonly, weak) UIView *playView; /* 展示Unity的view */ + (instancetype)instance; - (void)initUnity; - (void)pauseUnity; - (void)startUnity; - (BOOL)isPaused; @end
// // UnityController.mm // #import "UnityController.h" #import "UnityAppController.h" #import "UnityAppController+ViewHandling.h" #import "UnityAppController+Rendering.h" #import "DisplayManager.h" #import "UnityView.h" #include "RegisterMonoModules.h" #include "RegisterFeatures.h" #include <csignal> @interface UnityController() @property (nonatomic, assign) BOOL isInitUnity; @end @implementation UnityController + (instancetype)instance { return (UnityController *)[[UIApplication sharedApplication] valueForKeyPath:@"delegate.unityController"]; } - (instancetype)init { self = [super init]; if (self) { self.isInitUnity = NO; // 注册Unity的事件 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillTerminate:) name:UIApplicationWillTerminateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; } return self; } - (UIView *)playView { return self.unityView; } static const int constsection = 0; void UnityInitTrampoline(); void initMain() { @autoreleasepool { UnityInitStartupTime(); UnityInitTrampoline(); UnityInitRuntime(0, NULL); RegisterMonoModules(); NSLog(@"-> registered mono modules %p\n", &constsection); RegisterFeatures(); // iOS terminates open sockets when an application enters background mode. // The next write to any of such socket causes SIGPIPE signal being raised, // even if the request has been done from scripting side. This disables the // signal and allows Mono to throw a proper C# exception. std::signal(SIGPIPE, SIG_IGN); } } - (void)initUnity { if (!self.isInitUnity) { initMain(); if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO) [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; UnityInitApplicationNoGraphics([[[NSBundle mainBundle] bundlePath] UTF8String]); [self selectRenderingAPI]; [UnityRenderingView InitializeForAPI: self.renderingAPI]; _window = nil; _unityView = [self createUnityView]; [DisplayManager Initialize]; _mainDisplay = [DisplayManager Instance].mainDisplay; [_mainDisplay createWithWindow: _window andView: _unityView]; [super applicationDidBecomeActive:[UIApplication sharedApplication]]; self.isInitUnity = YES; } } - (void)pauseUnity { //[self applicationWillResignActive:[UIApplication sharedApplication]]; UnityPause(1); } - (void)startUnity { //[self applicationDidBecomeActive:[UIApplication sharedApplication]]; UnityPause(0); } - (BOOL)isPaused { if (UnityIsPaused() == 1) { return YES; } else { return NO; } } - (void)appWillEnterForeground:(NSNotification *)notification { [self applicationWillEnterForeground:[UIApplication sharedApplication]]; } - (void)appDidBecomeActive:(NSNotification *)notification { if (nil == self.unityView) { return; } [self applicationDidBecomeActive:[UIApplication sharedApplication]]; } - (void)appWillResignActive:(NSNotification *)notification { [self applicationWillResignActive:[UIApplication sharedApplication]]; } - (void)appWillTerminate:(NSNotification *)notification { [self applicationWillTerminate:[UIApplication sharedApplication]]; } - (void)appDidReceiveMemoryWarning:(NSNotification *)notification { [self applicationDidReceiveMemoryWarning:[UIApplication sharedApplication]]; } @end
inline UnityAppController* GetAppController()
{
// return (UnityAppController*)[UIApplication sharedApplication].delegate;
return (UnityAppController *)[[UIApplication sharedApplication] valueForKeyPath:@"delegate.unityController"];
}
// // ViewController.m // #import "ViewController.h" #import "UnityController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame = CGRectMake(60, 60, 80, 40); [button setTitle:@"开启Unity" forState:UIControlStateNormal]; [self.view addSubview:button]; [button addTarget:self action:@selector(clickHandler:) forControlEvents:UIControlEventTouchUpInside]; UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect]; button1.frame = CGRectMake(160, 60, 80, 40); [button1 setTitle:@"暂停Unity" forState:UIControlStateNormal]; [self.view addSubview:button1]; [button1 addTarget:self action:@selector(clickHandler1:) forControlEvents:UIControlEventTouchUpInside]; // 供Unity显示的View UIView *view = [[UIView alloc] initWithFrame:CGRectMake(10, 150, 300, 300)]; [view setBackgroundColor:[UIColor grayColor]]; [view setTag:22]; [self.view addSubview:view]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void) clickHandler:(id)sender { [[UnityController instance] initUnity]; [UnityController instance].playView.frame = [self.view viewWithTag:22].bounds; [[self.view viewWithTag:22] addSubview:[UnityController instance].playView]; } - (void) clickHandler1:(id)sender { if ([[UnityController instance] isPaused]) { [[UnityController instance] startUnity]; } else { [[UnityController instance] pauseUnity]; } } @end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。