最新:iOS 集成Unity AR

最近接到一個需求,要接入AR,給了個Vuforia官網(wǎng)地址阵难,還有AR開發(fā)部們同事給的demo(需求以demo為主)试溯,就直接開干,查了iOS原生接入Unity的資料传于,還是遇到了很多問題,在此總結(jié)記錄一下。

先看效果:
首頁
AR掃描后視頻播放

目錄

配置依賴
Demo封裝
問題匯總

配置依賴

首先展箱,我們拿到的demo結(jié)構(gòu)是這樣的:


demo目錄
    1. 將 Classes 和 Libraries 文件夾,以及Framework文件夾中的 Vuforia.framework 拖入工程蹬昌,按下圖方式:
      導(dǎo)入Classes混驰,Libraries及Vuforia.framework

      -------------------------------------------------->>>

    1. 將 Data 文件夾拖入工程,按下圖方式:
      導(dǎo)入Data

      -------------------------------------------------->>>

    1. 結(jié)果是這樣的(注意文件夾的路徑皂贩,導(dǎo)入 Header Search Paths按此參照):
      拖入后

注:需將 Data / Raw 文件夾內(nèi)的Vuforia文件夾按步驟二添加到如下位置栖榨,否則會掃描無反應(yīng):


Vuforia

-------------------------------------------------->>>

  • 4.將 Classes 文件夾 main.mm 內(nèi)容復(fù)制到自己項(xiàng)目(ARTest)中的 main.m 中 ,然后ARTest的 main.m 后綴改為 main.mm明刷,刪除 Classes 文件夾中的 main.mm (Move To Trash)有報(bào)錯先忽略, 代碼如下圖:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#include <csignal>

static const int constsection = 0;

void UnityInitTrampoline();

const char* AppControllerClassName = "UnityAppController";
int main(int argc, char * argv[]) {
    
    @autoreleasepool {
        UnityInitStartupTime();
        UnityInitTrampoline();
        
        UnityInitRuntime(argc,argv);
        RegisterMonoModules();
        RegisterFeatures();
        
        std::signal(SIGPIPE, SIG_IGN);
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

-------------------------------------------------->>>

    1. 在build Setting --> other Link Flags 下做如下修改:
 -weak_framework CoreMotion -weak-lSystem
other Link Flags

-------------------------------------------------->>>

    1. 在build Setting --> Header Search Paths 下做如下修改:
"$(SRCROOT)/ARTest/Unity" 
"$(SRCROOT)/ARTest/Unity/Classes"
"$(SRCROOT)/ARTest/Unity/Classes/Native"
"$(SRCROOT)/ARTest/Unity/Libraries"
"$(SRCROOT)/ARTest/Unity/Libraries/libil2cpp/include"
                  (不同項(xiàng)目需要按照文件在工程中的路徑來確定婴栽,本次路徑參照步驟三圖片所示路徑)

如圖所示:
Header Search Paths

-------------------------------------------------->>>

    1. 在build Setting --> Other C Flags 做如下修改:
-DINIT_SCRIPTING_BACKEND=1 -fno-strict-overflow -DRUNTIME_IL2CPP=1 -DNET_4_0

如圖所示:
Other C Flags

-------------------------------------------------->>>

  • 8.在build Setting --> Precompile Prefix Header做如下修改:如圖所示:
    precompile prefix header

注:若ARTest項(xiàng)目有pch 文件,需合并pch 文件辈末,將Classes內(nèi)的prefix.pch 內(nèi)容全部拷貝到本項(xiàng)目中的pch 中愚争,否則編譯會報(bào)錯,如圖:
PCH文件合并

-------------------------------------------------->>>

  • 9.在build Setting 做如下操作:
    Add-user-defined

    加入如下參數(shù):

GCC_THUMB_SUPPORT:NO 
GCC_USE_INDIRECT_FUNCTION_CALLS:NO 
UNITY_RUNTIME_VERSION:2018.2.3f1  <--這個值可能不一樣本冲,根據(jù)自己unity-demo來 
UNITY_SCRIPTING_BACKEND: il2cpp

結(jié)果:
Add-user-defined
  • 10 build Setting --> bitcode關(guān)閉
  • 11 添加依賴庫准脂,根據(jù)demo 來:


    依賴庫,根據(jù)demo來

Demo封裝(以上編譯成功再做如下操作)

#import <UIKit/UIKit.h>
@class DTPUnityController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic , strong)UIWindow *unityWindow;
@property (nonatomic, strong) DTPUnityController *unityController;
- (void)showUnityWindow;
- (void)hideUnityWindow;

@end

AppDelegate.mm:

#import "AppDelegate.h"
#import "DTPUnityController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    _unityController = [[DTPUnityController alloc]init];
    return YES;
}

#pragma mark ---------------unity開啟與隱藏
- (UIWindow *)unityWindow
{
    if (!_unityWindow) {
        if (!UnityGetMainWindow()) {
            _unityWindow = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
        }else{
            _unityWindow = UnityGetMainWindow();
        }
    }
    return _unityWindow;
}
- (void)showUnityWindow
{
    [self.unityWindow makeKeyAndVisible];
}

- (void)hideUnityWindow
{
    [self.window makeKeyAndVisible];
    [self.unityController pauseUnity];
}

@end
  • 2.新建一個類 DTPUnityController 繼承自 UnityAppController 以下是 .h 內(nèi)容:
#import "UnityAppController.h"

@interface DTPUnityController : UnityAppController

+ (instancetype)instance;

- (void)initUnity;

- (void)pauseUnity;

- (void)startUnity1;

- (BOOL)isPaused;

@end

.m 內(nèi)容:

#import "DTPUnityController.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>
#import "AppDelegate.h"

@interface DTPUnityController()

@property (nonatomic, assign) BOOL isInitUnity;

@end

@implementation DTPUnityController

+ (instancetype)instance {
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    return 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 UnityInitTrampoline();

- (void)initUnity {
     AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    if (!self.isInitUnity) {
        
        [super applicationDidBecomeActive:[UIApplication sharedApplication]];
        
        UnityInitApplicationNoGraphics([[[NSBundle mainBundle] bundlePath] UTF8String]);
        [self selectRenderingAPI];
        [UnityRenderingView InitializeForAPI: self.renderingAPI];

        _window = delegate.unityWindow;
        _unityView      = [self createUnityView];
        
        [DisplayManager Initialize];
        _mainDisplay    = [DisplayManager Instance].mainDisplay;
        [_mainDisplay createWithWindow: _window andView: _unityView];
        
        [self createUI];
        [self preStartUnity];
        self.isInitUnity = YES;
        
        _unityView.back = ^{
            [delegate hideUnityWindow];
        };

    }else{
        [self startUnity1];
    }
     [delegate showUnityWindow];
}

- (void)pauseUnity {
    UnitySendMessage("ARCamera", "Exit", "");  // 調(diào)Unity方法 退出模型 (與unity交互)
    UnityPause(1);
}

- (void)startUnity1 {
    UnityPause(0);
}

- (BOOL)isPaused {
    if (UnityIsPaused() == 1) {
        return YES;
    }
    else {
        return NO;
    }
}

-(void)applicationDidFinishLaunching:(UIApplication *)application{
    
}

- (void)appWillEnterForeground:(NSNotification *)notification {
    [super applicationWillEnterForeground:[UIApplication sharedApplication]];
}

- (void)appDidBecomeActive:(NSNotification *)notification {
    if (nil == self.unityView) {
        return;
    }
    [super applicationDidBecomeActive:[UIApplication sharedApplication]];
}

- (void)appWillResignActive:(NSNotification *)notification {
    [super applicationWillResignActive:[UIApplication sharedApplication]];
}

- (void)appWillTerminate:(NSNotification *)notification {
    [super applicationWillTerminate:[UIApplication sharedApplication]];
}

- (void)appDidReceiveMemoryWarning:(NSNotification *)notification {
    [super applicationDidReceiveMemoryWarning:[UIApplication sharedApplication]];
}


@end
    1. 調(diào)整demo代碼添怔,掃描頁面添加返回按鈕callback(UnityView.h):
點(diǎn)擊返回退出的回調(diào)

UnityView.mm 添加返回按鈕UI湾戳, addBackBtn 方法在initWithFrame中調(diào)用:

- (void)addBackBtn{
    UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    backBtn.frame = CGRectMake(20, 20, 70, 40);
    [self addSubview:backBtn];
    [backBtn setTitle:@"< 返回" forState:UIControlStateNormal];
    [backBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(touchEvents) forControlEvents:UIControlEventTouchUpInside];
}

- (void)touchEvents{
    if (self.back) {
        self.back();
    }
}

------------------------------------->>

  • 4.在UnityAppController.h 中按如圖修改:
    修改方法
  • 5.在ViewController中添加開啟AR代碼:
- (IBAction)startAR:(id)sender {
    
    DTPUnityController *vc = [DTPUnityController instance];
    [vc initUnity];
}

以上就是全部過程了。

問題匯總

    1. 第一次運(yùn)行demo 掃描后發(fā)現(xiàn)可以播放广料,但沒有聲音砾脑,音量也開到最大,以為是bug,找了好久艾杏,后面同事提示是否手機(jī)開了靜音韧衣,煞筆了。。畅铭。氏淑。
    1. 當(dāng)配置環(huán)境時,出現(xiàn)各種頭文件引用報(bào)錯硕噩,看是否引用了C C++代碼 是的話看下文件是否.mm 結(jié)尾假残,不是的話要相應(yīng)做修改 。另外炉擅,多數(shù)情況是Header Search Paths 路徑有誤辉懒,pch 文件合并,還有frameWork路徑帶來的報(bào)錯谍失,當(dāng)然還有build setting 中的 C Language 設(shè)置眶俩。
    1. 有些報(bào)錯還是無法解決,只能重新弄個工程集成了袱贮,xcode有時會抽風(fēng)仿便。
    1. 初始化在main 函數(shù)里面進(jìn)行了,然后沒找到返回按鈕的退出api攒巍,只能暫停嗽仪,然后調(diào)用unity 的移除模型api (若沒有需要與unity 工程師溝通)。
    1. 最大的坑就是好不容易集成了柒莉,掃描無反應(yīng)闻坚,掃描的圖片都是需要在官網(wǎng)先注冊的,然后有對應(yīng)的.dat .xml 文件兢孝,掃描不了就是這兩個文件路徑有問題窿凤,具體路徑設(shè)置代碼在哪,還希望廣大高手指出跨蟹,非常感激雳殊。
    1. 項(xiàng)目多Target時,Target名不能為中文窗轩,否則會 EXC_BAD_ACCESS 閃退夯秃,原因尚且不知。

---------------------------------后續(xù)補(bǔ)充內(nèi)容---------------------------------------------------

    1. 當(dāng)xcode集成的unity工程有改動需要替換時痢艺,只需將新導(dǎo)出的unity包內(nèi)的Data與Classes中的Native 2個文件夾替換即可仓洼。
    1. Xcode 11 中修改app名,需在info.plist中修改 bundle Display Name,直接在General 中修改Display Name,并且如果帶有中文的話堤舒,進(jìn)入unity 會在"initQCARiOS" 處出現(xiàn)EXC_BAD_ACCESS 的錯誤色建。原因是Xcode 11 在G general 中修改app名,會連同Product Name 一起修改舌缤。此外箕戳,引入Vuforia.framework及VuforiaDL.framework時某残,應(yīng)設(shè)置為Embed & Sign。
    1. AR 掃一掃出現(xiàn)黑屏漂羊,有可能是vuforia 購買的key 過期了驾锰。另外卸留,替換新key 后走越,還要檢查unity 中的設(shè)置: 1.去掉metal 只保留openGLES 2.0,2.ARCamera 中不勾選Allow MSAA耻瑟,勾選Allow HDR.
    1. 以上集成旨指,可能也會出現(xiàn)報(bào)錯,可以試著調(diào)整build-setting 中的 C Language Dialect 選項(xiàng)喳整,一般為GNU99谆构,來回切換下,可能會有效框都。
    1. 集成unity 后搬素,打包出來的ipa 包普遍很大,只保留arm64 架構(gòu)可以減少很多魏保。
    1. 編譯出現(xiàn)prinft_console 報(bào)錯熬尺,找到對應(yīng)代碼,注釋即可谓罗。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粱哼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子檩咱,更是在濱河造成了極大的恐慌揭措,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刻蚯,死亡現(xiàn)場離奇詭異绊含,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)炊汹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門躬充,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兵扬,你說我怎么就攤上這事麻裳。” “怎么了器钟?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵津坑,是天一觀的道長。 經(jīng)常有香客問我傲霸,道長疆瑰,這世上最難降的妖魔是什么眉反? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮穆役,結(jié)果婚禮上寸五,老公的妹妹穿的比我還像新娘。我一直安慰自己耿币,他們只是感情好梳杏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淹接,像睡著了一般十性。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上塑悼,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天劲适,我揣著相機(jī)與錄音,去河邊找鬼厢蒜。 笑死霞势,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斑鸦。 我是一名探鬼主播愕贡,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鄙才!你這毒婦竟也來了颂鸿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤攒庵,失蹤者是張志新(化名)和其女友劉穎嘴纺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浓冒,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡栽渴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了稳懒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闲擦。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖场梆,靈堂內(nèi)的尸體忽然破棺而出墅冷,到底是詐尸還是另有隱情,我是刑警寧澤或油,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布寞忿,位于F島的核電站,受9級特大地震影響顶岸,放射性物質(zhì)發(fā)生泄漏腔彰。R本人自食惡果不足惜叫编,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霹抛。 院中可真熱鬧搓逾,春花似錦、人聲如沸杯拐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藕施。三九已至寇损,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裳食,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工芙沥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诲祸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓而昨,卻偏偏與公主長得像救氯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子歌憨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容