iOS中集成unity

- 說明

0.png

- 導(dǎo)入unity模塊

  1. unity中導(dǎo)出的iOS工程是這樣子的:
1.png
  1. 將Classes文件夾、Data文件夾、Libraries、MapFileParser、MapFileParser.sh這五個(gè)復(fù)制到自己的iOS工程中
2.png
  1. 將Data、QCAR(QCAR文件在Data->Raw里面)文件夾以以下方式添加
3.png
  1. 將Classes、Libraries以以下方式添加
4.png
  1. 添加引用庫文件
    打開從unity中導(dǎo)出的iOS工程,查看其引用的庫文件,如圖所示
5.png

將上面的庫文件,添加到自己的工程中

  1. 關(guān)閉bitcode
    在build settings中關(guān)閉bitcode
  2. 在 other Linker Flags 添加
    -weak_framework CoreMotion -weak-lSystem


    14.png
  3. 在Other C Flags中添加 -DINIT_SCRIPTING_BACKEND=1,如圖所示
6.png
  1. 添加pch文件
7.png

如果項(xiàng)目中有多個(gè)pch文件,請將其合并成一個(gè)pch文件,再添加

  1. 在Header Search Paths 添加頭文件引用
    打開從unity導(dǎo)出的工程,查看Header Search Paths中添加的頭文件,如圖所示
8.png

將其添加到自己工程的Header Search Paths中

  1. 在Library Search Path 中添加庫引用
    打開從unity導(dǎo)出的工程,查看ibrary Search Path中添加的頭文件,如圖所示
9.png

將其添加到自己工程的ibrary Search Path中

  1. 在user-Defined 添加
    打開從unity導(dǎo)出的工程, 在build settings中查看user-Defined,如圖所示
10.png

并將其添加到自己項(xiàng)目的 user-Defined中

11.png
  1. 添加Run Script
    打開從unity導(dǎo)出的工程, 在build phases中查看Run Script,如圖所示:
12.png
  1. 更改main.m文件為main.mm文件。將Classes中的main.mm中的內(nèi)容復(fù)制,粘貼到原來工程的main.mm中。然后刪除Classes中的main文件。
 
#include "RegisterMonoModules.h"
#include "RegisterFeatures.h"
#import "AppDelegate.h"
#include <mach/mach_time.h>
#include <csignal>

// Hack to work around iOS SDK 4.3 linker problem
// we need at least one __TEXT, __const section entry in main application .o files
// to get this section emitted at right time and so avoid LC_ENCRYPTION_INFO size miscalculation
static const int constsection = 0;

void UnityInitTrampoline();

// WARNING: this MUST be c decl (NSString ctor will be called after +load, so we cant really change its  value)
const char* AppControllerClassName = "UnityAppController";

int main(int argc, char* argv[])
{
  signed long long startTime = mach_absolute_time();
  @autoreleasepool
  {
      UnitySetStartupTime(startTime);
      UnityInitTrampoline();
      UnityInitRuntime(argc, argv);
      
      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);
      
      //UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String:AppControllerClassName]);
      UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
  
  return 0;
}

#if TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR

#include <pthread.h>

extern "C" int pthread_cond_init$UNIX2003(pthread_cond_t *cond, const pthread_condattr_t *attr)
{ return pthread_cond_init(cond, attr); }
extern "C" int pthread_cond_destroy$UNIX2003(pthread_cond_t *cond)
{ return pthread_cond_destroy(cond); }
extern "C" int pthread_cond_wait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex)
{ return pthread_cond_wait(cond, mutex); }
extern "C" int pthread_cond_timedwait$UNIX2003(pthread_cond_t *cond, pthread_mutex_t *mutex,
                                             const struct timespec *abstime)
{ return pthread_cond_timedwait(cond, mutex, abstime); }

#endif // TARGET_IPHONE_SIMULATOR && TARGET_TVOS_SIMULATOR

并將main函數(shù)中的 UIApplicationMain方法修改為UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

  1. 在Classes的UnityAppController.mm中的- (void)applicationDidBecomeActive:(UIApplication*)application方法中,注釋掉[self performSelector: @selector(startUnity:) withObject: application afterDelay: 0]方法,這樣做的目的,是為防止unity的內(nèi)容隨著應(yīng)用的啟動(dòng),而啟動(dòng);
- (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;
}
  1. 修改appDelegate.h
#import <UIKit/UIKit.h>
@class UnityAppController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property(strong,nonatomic)UINavigationController *navi;
@property (strong, nonatomic) UIWindow *window;
@property (strong,nonatomic)UnityAppController* unityAppController;
- (void)shouldAttachRenderDelegate;
@end
  1. 將appDelegate.m修改為appDelegate.mm,并對其內(nèi)容進(jìn)行修改
   #import "AppDelegate.h"
#import "ViewController.h"
#import "UnityAppController.h"
@interface AppDelegate ()

@end

extern "C" void VuforiaSetGraphicsDevice(void* device, int deviceType, int eventType);
extern "C" void VuforiaRenderEvent(int marker);

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Override point for customization after application launch.
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  BOOL returnBool;
  if (_unityAppController == nil) {
      
      _unityAppController = [[UnityAppController alloc] init];
  }
  [_unityAppController application:application didFinishLaunchingWithOptions:launchOptions];
  
  ViewController *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"viewVC"];
  self.navi = [[UINavigationController alloc] initWithRootViewController:vc];
  self.window.rootViewController=self.navi;
  [self.window makeKeyAndVisible];
  return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
  [_unityAppController applicationWillResignActive:application];
  // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
  // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
  
  [_unityAppController applicationDidEnterBackground:application];
  // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
  // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
  [_unityAppController applicationWillEnterForeground:application];
  // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
  [_unityAppController applicationDidBecomeActive:application];
  // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}


- (void)applicationWillTerminate:(UIApplication *)application {
  [_unityAppController applicationWillTerminate:application];
  // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (void)shouldAttachRenderDelegate
{
  UnityRegisterRenderingPlugin(&VuforiaSetGraphicsDevice, &VuforiaRenderEvent);
}
@end
  1. 在Classes的UnityAppController.h中,更改GetAppController()方法(當(dāng)然要先引入#import "AppDelegate.h"
inline UnityAppController*  GetAppController()
{
  AppDelegate *dele = (AppDelegate *)[UIApplication sharedApplication].delegate;
  return (UnityAppController *)dele.unityAppController;
}
  1. 在UnityAppController.mm中重寫- (void)shouldAttachRenderDelegate方法
- (void)shouldAttachRenderDelegate  {
 AppDelegate *deleg = [UIApplication sharedApplication].delegate;
 [deleg shouldAttachRenderDelegate];
}
  1. ok,通過上面的步驟,我們就已經(jīng)將unity的功能導(dǎo)入自己的項(xiàng)目中,接下來做的,就是點(diǎn)擊按鈕,啟動(dòng)unity模塊

  2. Main.storyBoard的ViewController創(chuàng)建一個(gè)UIButton,并將Storyboard ID設(shè)為“viewVC”

13.png
  1. 在ViewController.m實(shí)現(xiàn)其點(diǎn)擊事件(記得倒入#import "UnityAppController.h",#import "AppDelegate.h")
 #pragma mark----打開AR-----
- (IBAction)doOpenAR:(id)sender {
   
   static bool flg=NO;
   if (flg) {//如果不是第一次啟動(dòng),則之間切換window
       [GetAppController() restartUnity]; 
   }
   else//如果是第一次點(diǎn)擊按鈕,則需要啟動(dòng)unity
   {
       [GetAppController() preStartUnity];
       [GetAppController() startUnity:[UIApplication sharedApplication]];

[UnityGetMainWindow() makeKeyAndVisible];
       flg=YES;
   }
   
}
  1. 在UnityAppController.h中申明-(void) restartUnity,在UnityAppController.mm中實(shí)現(xiàn)
-(void) restartUnity
{
 _window.rootViewController=_rootController;
 [_window makeKeyAndVisible];
 [UnityGetMainWindow() makeKeyAndVisible];
 if (_didResignActive) {
     UnityPause(false);
     
     _didResignActive=NO;
 }
}
  1. 這樣,我們就能啟動(dòng)unity的模塊了,但是,關(guān)閉或隱藏unity模塊,也需要我們操作。
  2. 我們需要在UnityAppController.mm中的- (void)startUnity:(UIApplication*)application方法里,添加一個(gè)按鈕
- (void)startUnity:(UIApplication*)application
{
 NSAssert(_unityAppReady == NO, @"[UnityAppController startUnity:] called after Unity has been initialized");

 UnityInitApplicationGraphics(UNITY_FORCE_DIRECT_RENDERING);

 // we make sure that first level gets correct display list and orientation
 [[DisplayManager Instance] updateDisplayListInUnity];

 UnityLoadApplication();
 Profiler_InitProfiler();

 [self showGameUI];
 
 
 UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
 [button addTarget:self action:@selector(doHideenUnity) forControlEvents:UIControlEventTouchUpInside];
 button.frame=CGRectMake(0, 0, 50, 50) ;
 [button setTitle:@"退出" forState:UIControlStateNormal];
 //[button setBackgroundColor:[UIColor purpleColor]];
 [_rootView addSubview:button];
 
 [self createDisplayLink];

 UnitySetPlayerFocus(1);
}
  1. 并實(shí)現(xiàn)按鈕的點(diǎn)擊事件
-(void)doHideenUnity
{
 UnityPause(true);
 _didResignActive=YES;
 Profiler_UninitProfiler();
 AppDelegate *delet=[UIApplication sharedApplication].delegate;
     
     [delet.window makeKeyAndVisible];
 
}
  1. ok,完成

可能遇到了問題

  • 重復(fù)的main.mm,記得刪除Classes文件的main.mm
  • 如果有多個(gè)pch文件,記得進(jìn)行合并
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS中添加unity模塊說明 iOS中添加unity模塊的demo,可以在 看一看->項(xiàng)目 中找到.2.參考網(wǎng)址...
    焉逢12閱讀 4,425評論 3 5
  • 集成步驟 所有的配置參考Unity導(dǎo)出來的工程的配置 1. iOS工程中新建Vendor group 2. 添加U...
    沃倫蓋茨閱讀 2,613評論 0 0
  • unity版本:unity 5.4.3f1 xcode版本:xcode 8 一、導(dǎo)出unity項(xiàng)目 1.File-...
    MUYO_echo閱讀 20,053評論 37 95
  • 最近遇到一個(gè)識別圖像后顯示3D模型的需求,權(quán)衡再三選擇了國內(nèi)的easyAR SDK。Unity建模完成后,導(dǎo)出相應(yīng)...
    Lotheve閱讀 3,007評論 11 6
  • Z先生又自己出去旅行,這次選擇了墾丁,在那找了一個(gè)別墅的一層,自己住3天。 這個(gè)別墅就在墾丁的著名景點(diǎn),7-11旁...
    Caphintty圖圖閱讀 184評論 0 1

友情鏈接更多精彩內(nèi)容