近期 在作AR這一塊,用EasyAR集成到iOS端,因爲如今到項目已經上線,下一版本要作一個AR功能,因而迫於需求須要,本身研究和翻閱讀好多集成到資料。app
經過整理分出幾個重要到模塊,其中在這裏指出Xcode9版本確實好坑,建議棄坑,該用稍微好點到版本Xcode9.1.dom
一模塊.Unity3D導出iOS項目(UD,表示)。socket
二模塊.從UD取出重要到三個文件。ide
三模塊.新建一個iOS項目(ID,表示)atom
四模塊.在ID配置Unity3D的環境spa
五模塊.在ID建立Unity3D的控制器文件及代碼3d
開始演示:code
一模塊.Unity3D導出iOS項目(UD,表示)。orm
1.在搞好Unity的代碼開發後就能夠倒出iOS版本了(若是沒有AR項目,能夠到EasyAR去找dome來作)。server
2.導出到相關配置如標,按裏面的配置好就好,注意【’容許使用相機?‘,要寫,否則導出iOS後運行會崩潰】:(圖是取來別人的圖)
二模塊.從UD取出重要到三個文件。
1.三個目錄,Classes,Libraries,Data。
三模塊.新建一個iOS項目(ID,表示)
1.引用UD項目裏的三個文件,並集成到ID項目裏。
2.這裏須要注意的是,Classes和Libraries目錄做爲Group引用,切記不要勾選copy。
3.而Data目錄不須要參與編譯,做爲folder引用進來便可。
文件結構以下:(能夠不要建立文件夾放置,按照UD項目的結構來作)
四模塊.在ID配置Unity3D的環境
1.關閉bitcode。新版的Unity已經支持Bitcode但EasyAR並不支持,不關閉沒法正常編譯。如圖:
2.修改Linking -> Other Linker Flags選項,添加參數 -weak_framework CoreMotion -weak-lSystem
。
3.修改頭文件搜索目錄,如圖:
結構如:
"$(SRCROOT)/項目名稱/Classes"
"$(SRCROOT)/項目名稱/Libraries"
"$(SRCROOT)/項目名稱/Libraries/libil2cpp/include"
"$(SRCROOT)/項目名稱/Classes/Native"
"$(SRCROOT)/項目名稱"
"$(SRCROOT)"
4.修改庫搜索目錄,如圖:
結構如:
"$(SRCROOT)/項目名稱/Libraries"
"$(SRCROOT)/項目名稱/Libraries/Plugins/iOS"
"$(SRCROOT)/項目名稱"
5. 修改LLVM - Custom Complier Flags -> Other C Flags選項,添加兩個參數: -DINIT_SCRIPTING_BACKEND=1
和 -DRUNTIME_IL2CPP=1
。
6.修改LLVM - Language -> C Language Dialect選項,選擇C99
。
7.修改LLVM - Language - C++ -> C++ Language Dialect選項,選擇 C++11
。
8.添加三項自定義設置
9.新建一個PCH文件,並修改Precompile Prefix Header爲YES,關聯pch文件路徑。此處新建文件名爲 PrefixHeader.pch。
10.添加工程依賴(注意三個Optional)
五模塊.在ID建立Unity3D的控制器文件及代碼
1.ID項目中,將Classes/
下的main.mm
文件裏面的內容,複製所有到集成項目的Supporting Files/
下的main.m
文件中,而後刪除Classes/main.mm
,而且把文件後綴改爲.mm
。而且按照下圖對內容進行修改
2.修改 UnityAppController文件
改以前:
改以後:(‘delegate.unityController’的unityController,是以後要建的自定義文件,用來處理AR界面處理的,不明白能夠無論)
3.新建一個UnityController文件繼承於UnityAppController用來處理AR界面處理(注意變成C++混編文件【把.m文件變成.mm文件】)
UnityController.mm文件以下:
// Created by XY IOS on 2017/11/18.
// Copyright © 2017年 陳詩友. All rights reserved.
//
#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;
}
- (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]];
}
- (UIView *)playView
{
return self.unityView;
}
static const int constsection = 0;
void UnityInitTrampoline();
void initMain() {
@autoreleasepool
{
// UnityInitTrampoline();
// 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;
}
}
@end
4.在ViewController 文件建立一個(sbtn)按鈕[驅動AR], 一個view[AR容器],要注意一點要在AppDelegate.m文件初始化UnityController
#import "ViewController.h"
#import "UnityController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initUI];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)initUI
{
// self.view.backgroundColor = [UIColor whiteColor];
UIButton *sbtn = [UIButton buttonWithType:UIButtonTypeCustom];
sbtn.frame = CGRectMake((CGRectGetMaxX(self.view.frame) - 60 ) / 2, 150, 60, 40);
sbtn.backgroundColor = [UIColor purpleColor];
[sbtn setTitle:@"AR開始" forState:UIControlStateNormal];
[sbtn addTarget:self action:@selector(Actions) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:sbtn];
// UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// button1.frame = CGRectMake((CGRectGetMaxX(self.view.frame) - 60 ) / 2, 150 + 40, 60, 40);
// [button1 setTitle:@"AR暫停" forState:UIControlStateNormal];
// [self.view addSubview:button1];
// button1.backgroundColor = [UIColor redColor];
// [button1 addTarget:self action:@selector(clickHandler1:) forControlEvents:UIControlEventTouchUpInside];
// 供Unity顯示的View
// UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(sbtn.frame) + 50, CGRectGetWidth(self.view.frame), 400)];
UIView *view = [[UIView alloc] initWithFrame:self.view.bounds];
[view setBackgroundColor:[UIColor grayColor]];
[view setTag:22];
view.hidden = YES;
[self.view addSubview:view];
}
- (void) clickHandler1:(id)sender
{
if ([[UnityController instance] isPaused]) {
[[UnityController instance] startUnity];
}
else {
[[UnityController instance] pauseUnity];
}
}
- (void)Actions
{
NSLog(@"ar");
// self.unityController = [[UnityController alloc]init];
[self.view viewWithTag:22].hidden = NO;
[[UnityController instance]initUnity];
[UnityController instance].playView.frame = [self.view viewWithTag:22].bounds;
[[self.view viewWithTag:22] addSubview:[UnityController instance].playView];
// AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
5.在AppDelegate.m文件初始化UnityController
問題表現爲,在使用Unity打包出來的項目運行是正常的,可是集合到現有項目的時候,攝像頭顯示區域是黑屏。錯誤碼是:EasyAR is running on an unsupported graphics device of type -4
。
解決的方法:
運行結果: